Programming I, 2018-9
Lecture 3 – Notes

Fibonacci numbers

The sequence of Fibonacci numbers Fi is defined as follows: F1 = 1, F2 = 1, and Fi = Fi-1 + Fi-2 for all i ≥ 3. So the sequence is

1, 1, 2, 3, 5, 8, 13, 21, …

Let's write a program that reads an integer N and writes the first N numbers in the Fibonacci sequence.

To accomplish this, we use two integer variables a and b to store the next two numbers that we will output:

var
  a: integer = 1;
  b: integer = 1;
  c: integer;
  n, i: integer;

begin
  readln(n);
  for i := 1 to n do
    begin
      write(a, ' ');
      c := a + b;
      a := b;
      b := c;
    end;
  writeln;
end;

On each loop iteration, we first output a. We then compute c, which is the Fibonacci number that comes after a and b. Then, since we have already output a, we shift b into a and then c into b.

The key to solving a problem like this is figuring out what state we must remember between loop iterations – in this case, the variables a and b.

second largest number

In an earlier lecture we saw how to write a program that reads a series of integers and prints the largest of them. Now let's write a program that prints the second largest of a series of input numbers.

We can achieve this by using two variables to remember the largest and second largest numbers that we've seen so far:

var
  max: integer = - MaxInt;   // largest so far
  max2: integer = - MaxInt;  // second largest so far
  i: integer;

begin
  while not seekEof do
    begin
      readln(i);
      if i > max then  // i is the largest so far
        begin
          max2 := max;
          max := i;
        end
      else if i > max2 then  // i is the second largest so far
        max2 := i;
    end;
    
  writeln(max2);
end;

Study the program to understand how it works. Again, the key to solving this problem is figuring out what state we must keep between iterations – in this case, the variables max and max2.

Also note that the program above allows the largest and second largest numbers to be the same. For example, if the input is the numbers 6, 6, 4, and 4, then the program will write 6. If we don't want this, we can change the else statement above to

else if (i <> max) and (i > max2) then

With this change, if the program sees the current maximum value again then it will ignore it. With the input numbers 6, 6, 4, and 4, the program will print 4.

breaking a number into digits

We can use math to break a decimal number into digits. Suppose that n = 6437. Then

In other words, (n mod 10) gives us the last digit of n. (n div 10) gives us all digits except the last.

Using this idea, we can build a loop that iterates over the digits of n. Here's a program to compute the sum of the digits in a number:

var
  n: integer;
  sum: integer = 0;

begin
  readln(n);

  while n > 0 do
    begin
      sum := sum + (n mod 10);
      n := n div 10;
    end;

  writeln(sum);
end;

In the number n = 6437, 6 is the most significant digit and 7 is the least significant digit. In the program above we can see that it's easy to iterate over the digits from least significant to most significant. (It is also possible, but not quite as easy, to go in the other direction.)

Also note that

So by using a higher power of 10 such as 100 = 102, we can chop off more digits at once.

(Finally, note that the above techniques work in any base, not just base 10. We will begin working with other bases soon.)

constructing a number from digits

Similarly, we can use math to construct a number from a set of decimal digits. If n = 6437, then

So we can append the digit d to n by computing (10 ⋅ n + d).

Using this idea, we can build a loop that constructs a number containing the digits 1 through n:

var
  digits, i: integer;
  n: integer = 0;

begin
  readln(digits);
  for i := 1 to digits do
    n := 10 * n + i;
  writeln(n);
end;

We see here that it's easy to build a number from one digit at a time, starting with the most significant digit. (It is also possible, but not quite as easy, to go in the other direction.)

(Once again, this will work in any base, not just base 10.)

reading and writing characters in a string

The length method returns the number of (8-bit) characters in a string:

var
  s: string;
  
begin
  s := 'watermelon';
  writeln(length(s));  // writes 10
end.

We can use the [] operator to extract individual characters from a string. String characters are always indexed from 1, so in the above string the characters have indices 1 through 10:

var
  s: string = 'watermelon';
  
begin
  writeln(s[1]);  // writes 'w'
  writeln(s[6]);  // writes 'm'
end.

Note that any non-ASCII characters in a string are represented using multiple bytes. Be aware that length and the [] operator will behave differently if a string has such characters:

var
  s: string = 'řehoř';
  
begin
  writeln(length(s));  // writes 7
  writeln(s[3]);       // writes 'e', since 'ř' occupies both s[1] and s[2]
end.

But in this course we will generally work with strings containing only ASCII text.

We can use a loop to iterate over the characters in a string. Here's a program to count the number of occurrences of the letter 'x' in a string:

var
  s: string;
  i: integer;
  count: integer = 0;

begin
  readln(s);
  for i := 1 to length(s) do
    if s[i] = 'x' then
      count := count + 1;
  writeln(count);
end.

A palindrome is a string that reads the same forwards and backwards, such as "racecar". Here's a program to check whether a string is a palindrome:

var
  s: string;
  i: integer;

begin
  readln(s);
  for i := 1 to length(s) div 2 do
    if s[i] <> s[length(s) + 1 - i] then
      begin
        writeln('not a palindrome');
        exit;
      end;
  writeln('palindrome');
end.

Strings in Pascal are mutable: they can change. We can update individual characters in a string like this:

var
  s: string = 'dime';
  
begin
  s[1] := 'l';  // now s = 'lime'
  s[3] := 'n';  // now s = 'line'
end.

range errors and range checking

What will happen if we try to access string characters that are out of bounds? For example:

var
  s: string = 'cantelope';
  
begin
  write(s[100]);    // out of bounds
  s[200] := 'x';    // out of bounds
end.

The above accesses are out of bounds because length(s) = 9, so the only valid indices are 1 through 9.

By default, Pascal will not detect the above range errors. The read of s[100] will return some arbitrary value. The write to s[200] is worse: it will write to some area of memory that is outside the string. This unsafe behavior will have unpredictable effects: it might corrupt other variables in the program or cause the program to crash.

Fortunately we can ask Pascal to turn on range checking, which will check that each string access is in bounds. To do so, include the following at the top of your program:

{$r+}

With range checking enabled, if we run the above program we will see

Runtime error 201 at $0000000000400E1D
  $0000000000400E1D
  $000000000040018C

I strongly suggest that you enable range checking in all programs. If your program has a range error bug, generally you want to learn about it immediately.

arrays

As we saw above, a string holds a set of characters that we can access individually by index. An array generalizes this concept: it is a set of values of some type T that we can we access individually by index.

Arrays in Pascal come in two forms: static and dynamic. A static array has a fixed size, whereas a dynamic array can grow and shrink as the program runs.

You can declare a static array like this:

var
  a: array[1..100] of integer;

The array indices don't need to begin with 1. They can start at 0 or any other value:

var
  a: array[0..49] of boolean;

The length function returns the total number of elements in an array. Also, the built-in functions low and high return an array's lowest and highest index values, respectively:

var
  a: array[0..49] of float;
  
begin
  writeln(length(a));   // writes 50
  writeln(low(a));      // writes 0
  writeln(high(a));     // writes 49
end.

Here is a program that reads 10 integers from standard input and then writes them out in reverse order, using a static array:

var
  a: array[1..10] of integer;
  i: integer;
  
begin
  for i := 1 to 10 do
    readln(a[i]);
    
  for i := 10 downto 1 do
    writeln(a[i]);
end.

Of course, it would be nice if our program were more flexible and could handle any number of integers, not just 10. We can achieve this using a dynamic array. You can declare a dynamic array like this:

var
  a: array of integer;

Before you can use a dynamic array, you must set its length by calling setLength:

setLength(a, 100);

Dynamic arrays are always indexed from 0, so after the call above the array will hold values with indices from 0 to 99.

You can call setLength many times on the same array to grow or shrink it as you like. When growing a dynamic array, setLength sets any newly allocated elements to zero.

Let's rewrite the program above so that it can handle any number of integers. We'll assume that the first line of the input contains a number N indicating how many values will follow. After the program reads them all, it will print them in reverse order:

var
  a: array of integer;
  n, i: integer;
  
begin
  readln(n);  // number of elements;
  setLength(a, n);

  for i := 0 to n - 1 do
    readln(a[i]);

  for i := n - 1 downto 0 do
    writeln(a[i]);
end.

Let's make one more improvement to our program. The input will no longer begin with the count N. Instead, we will simply read as many numbers as are available until the end of the input is reached (i.e. the user has pressed Ctrl+D or Ctrl+Z). To do this, we will need to grow the dynamic array as we add each number:

var
  a: array of integer;
  i: integer;
  
begin
  setLength(a, 0);
  
  while not seekEof do
    begin
      setLength(a, length(a) + 1);
      readln(a[high(a)]);
    end;
    
  for i := high(a) downto 0 do
    writeln(a[i]);
end.

computing the day of year

Let's write a program that lets the user enter a date given by a month and day. The program will print out that date's day number with the year, where

We assume that the year in question is not a leap year, so February has 28 days.

For example:

enter month and day: 2 5
day of year: 36
===
enter month and day: 12 30
day of year: 364

To write this program, it will be helpful to have an array containing the number of days in each month of the year. In Pascal we may specify a set of initial values to be stored in a static array. In our program, this array is a constant:

const
  Days: array[1..12] of integer =
    (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

var
  month, day, i: integer;
  total: integer = 0;
  
begin
  write('enter month and day: ');
  readln(month, day);
  
  for i := 1 to month - 1 do
    total := total + Days[i];
  total := total + day;
  
  writeln('day of year: ', total);
end;

prime factorization

In the last lecture we learned an algorithm for determining whether an integer is prime. We will now study another number-theoretic algorithm, namely for determing an integer's prime factorization.

The Fundamental Theorem of Arithmetic states that

Every positive integer has a unique prime factorization.

For example:

We can use trial division to factor an integer. This is similar to our primality testing algorithm, which also used trial division. Given an integer N, we first try dividing N by 2, then by 3 and so on. If n is actually divisible by a number such as 3, then we must repeatedly attempt to divide by that same number. since the same prime factor may appear multiple times in the factorization.

Here is a first program for prime factorization:

var
  n: integer;
  i: integer;

begin
  write('number to factor: ');
  readln(n);
  
  i := 2;
  while n > 1 do
    if n mod i = 0 then
      begin
        write(i, ' ');
        n := n div i;
      end
    else
      i := i + 1;
end.

Study the program to understand how it works. Note that the program will attempt to divide by non-prime factors, such as when i = 4. But n will never be divisible by such values. That's because any non-prime factor i is itself the product of two (or more) smaller primes, and we have already divided those primes out of n, so n cannot possibly be divisible by i.

The program works, but is inefficient because it potentially tests all values from 1 to n. Just as in our primarily testing algorithm, we can make the program much more efficient by stopping our loop once i reaches sqrt(n).

We can see that this is valid using the same argument as in the last lecture. Once again, if ab = n for integers a and b, then we must have either a ≤ sqrt(n) or b ≤ sqrt(n). Proof: Suppose that a > sqrt(n) and b > sqrt(n). Then ab > sqrt(n) ⋅ sqrt(n) = n, a contradiction. So either a ≤ sqrt(n) or b ≤ sqrt(n).

It follows that if we have tested all the values from 2 through sqrt(n) and none of them divide n, then if ab = n we must have a = 1 or b = 1. And so n must be prime. Therefore we can end the loop and simply print n itself, which must be the last prime factor.

Here is the updated program:

var
  n: integer;
  i: integer;

begin
  write('number to factor: ');
  readln(n);
  
  i := 2;
  while i * i <= n do    // i <= sqrt(n)
    if n mod i = 0 then
      begin
        write(i, ' ');
        n := n div i;
      end
    else
      i := i + 1;
      
  writeln(n);
end.

Note that in this program the while condition can be either 'i * i <= n' or 'i <= sqrt(n)'. These are equivalent, but the first version is a bit more efficient since it uses integer rather than floating-point arithmetic.

capitalizing all words in a string

Here is a program to capitalize all words in a string. Here, a word is a sequence of non-space characters.

var
  s: string;
  prev: char;
  i: integer;

begin
  readln(s);
  prev := ' ';
  
  for i := 1 to length(s) do
    begin
      if (prev = ' ') and (s[i] <> ' ') then
        s[i] := upCase(s[i]);

      prev := s[i];
    end;
  
  writeln(s);
end.

most frequent letter

Here's a program to find the most frequent letter in its input, We ignore case: 'a' and 'A' are considered to be the same letter. The program prints the most frequent letter along with a count of its occurrences.

The program works by computing a histogram of letter frequencies. We use the fact that in Pascal array indices may even be characters! Furthermore we can even use a for loop to loop over a range of characters.

uses character;  // for 'isLetter' function

var
  count: array['a' .. 'z'] of integer;
  c: char;
  m: char;

begin
  for c := 'a' to 'z' do
    count[c] := 0;
  
  while not eof do
    begin
      read(c);
      c := lowerCase(c);
      if isLetter(c) then
        count[c] := count[c] + 1;
    end;
  
  m := 'a';  // most frequent letter so far
  for c := 'b' to 'z' do
    if count[c] > count[m] then
      m := c;
  
  writeln(m, ' ', count[m]);
end.

Pythagorean triples

We all remember from geometry that if a and b are the lengths of the legs of a right triangle, and c is the length of the hypotenuse, then

a2 + b2 = c2

In some such triangles a, b, and c are all integers. For example:

We'd now like to write a program that finds all sets of integers (a, b, c) with 1 ≤ a < b < c ≤ 100 such that a2 + b2 = c2.

We will accomplish this via exhaustive search: we simply try all possible triples (a, b, c) to see which ones satisfy the equation a2 + b2 = c2. We can use a triple for loop:

var
  a, b, c: integer;
  
begin
  for a := 1 to 100 do
    for b := a + 1 to 100 do
      for c := b + 1 to 100 do
        if a * a + b * b = c * c then
          writeln('a = ', a, ', b = ', b, ', c = ', c);
end;

The output is

a = 3, b = 4, c = 5
a = 5, b = 12, c = 13
a = 6, b = 8, c = 10
a = 7, b = 24, c = 25
…