Some loops are used to look for something. For example, suppose that you have an integer n and you want to find the first prime number that is larger than n. The idea is to start at n + 1, and to count upwards. We use variable k to do that. As soon as a value of k is found that is prime, we stop. We assume that function isPrime(k) is available.
Define nextPrime(n: Integer) : Integer by nextPrime(n) = k | Let k = n + 1. While not(isPrime(k)) do Relet k = k + 1. %While %DefineThe big difference between a search loop and an accumulation loop is that an accumulation loop has to look at all values in a given range, but a search loop can stop as soon as it finds what it is looking for, so sometimes it ends very early.
We have used function isPrime(n). Let's define it, using a loop. Integer n is prime if n > 1 and n does not have any factors except 1 and n.
The idea is to search for a factor of n in the list of numbers 2, 3, 4, ..., n-1. We need one variable (say, k) to count from 2 to n-1. As soon as a factor is found, we know that n is not prime.
This time there is a twist. If n is prime, then we will not find a factor. Search loops usually need to decide what to do when the value being sought is not found. In this case, it is just a matter of saying that n is prime.
Define isPrime(n: Integer): Boolean by isPrime(n) = r | Let k = 2. While k < n and n `mod` k =/= 0 do Relet k = k + 1. %While Let r = false. If k == n then Relet r = true. %If %Define
When the loop is done, k will be n if no factor was found. It is tempting to write, at that point,
If k == n then Let r = true. else Let r = false. %If
But that introduces a problem of context. Recall that variables that are created inside an If-statement can only be used in that same If-statement. Since r is created inside the If-statement, it is only available inside the If-statement. You can fix that by writing open in front of the If-statement. So it would work to write
open If k == n then Let r = true. else Let r = false. %If
An even simpler way to do that would be just to write
Let r = k == n.Then r is true if k == n is true, and r is false if k == n is false. So a shortened definition of function isPrime is as follows.
Define isPrime(n: Integer): Boolean by isPrime(n) = r | Let k = 2. While k < n and n `mod` k =/= 0 do Relet k = k + 1. %While Let r = k == n. %Define
[solve] Using a loop, define function any7s(n), which takes an integer n and returns true if the usual (base 10) representation of n contains a 7. For example, any7s(274) = true, but any7s(99) = false. Write Define ... %Define around your definition.
(Hint. Successively divide the number by 10. You are searching for a number whose rightmost digit is a 7. The search is exhausted when the number is 0. For example, when n is 3791, you look at 3791, 379, 37, and stop, because the rightmost digit of 37 is 7. When n is 999, you look at 999, 99, 9, 0, and stop because the search has reached 0. So only keep searching when you current number is not 0 and does not have rightmost digit 7.)
[solve] Using a loop, define a function anyRs(s) that yields true if string s contains the character 'R'. For example, anyRs("MyRabbit") = true, but anyRs("myrabbit") = false. Write Define ... %Define around the definition.
Be careful writing conditions. Do not try to compute s_k when k > length(s), since that will cause an error. Remember the short-circuiting property of the and and or operators.
A search loop stops as soon as it encounters what it is looking for.