Monday, April 28, 2014

Read your code before you test it.

In his  book 'Program Construction: Calculating Implementations from Specifications'  published in 2003, Backhouse says

" to write a program that
would compare two strings for equality. One student's solution was to assign the
value true or false to a boolean equal as follows:

equal := (stringl.length = string2.length);
if equal
then for i := 1 to string1.length
do equal := (stringl.character[i] = string2.character[i])

The program is coded in Pascal. The characters of a string s are assumed to be stored in the
array s.character, indexed from 1 to s.length.

The problem with this code is that it returns the value true whenever the two
strings have equal length and their last characters are identical. For example, the
two strings 'cat' and 'mat' would be declared equal because they both have length
three and end in 't'. The student was quite taken aback when I demonstrated the error.
 Indeed, upon further questioning, it emerged that the program had been tested quite systematically."

Obviously, the testing was not sufficient.

He adds "(Needless to say, I observed the error by reading the code, not by testing. The
student was blameless. The error was the responsibility of the student's teacher
for having failed to teach proper design principles and suggesting that testing
was adequate.)"

I wonder what sort of design principles are not taught and what sort of testing was taught to be adequate. Whenever assignment statement is used within a loop there is a possibility of getting the updating process wrong and logical reasoning from school math can help.

A typical declarative programmer would reason like this.
Two strings of length 1 are equal if they have the same character.
Two strings of length more than 1 are equal if they have the same first character and the rest of the strings are equal.

In Prolog,

eqs([X], [X]).//
eqs([F1| R1], [F2| R2]) :- eqs([F1],[F2]), eqs(R1, R2).
               

This is a very common idiom in declarative languages. With a little care, this can be translated into an imperative language like java that allows recursion.

public class StringEqualCheck {

public static void main(String[] args) {

System.out.println(check("aab","bba"));
System.out.println(check("abc","ddc"));
System.out.println(check("abc", "abc"));
}
public static boolean check(String s1, String s2) {
if (s1.length() == 1)
return   (s1.charAt(0) == s2.charAt(0)) ? true:false;
return   (s1.charAt(0) == s2.charAt(0))
        && check(s1.substring(1), s2.substring(1)) ;
}

}

It is possible to think iteratively as the student attempted to do.
What is the meaning of the boolean variable 'equal'?
It is the truth value of the comparison of the prefixes of the strings of length i - 1.
It is not the truth value  of the comparison of characters at i. (the mistake made by the student).
Correct updating statement follows from this understanding. My second child, Saurya recognized this immediately. My translation into java.

public static boolean itercheck(String s1, String s2) {
boolean equal = true;
for (int i=0; i < s1.length(); i++){
if(!equal) return false;
   equal = equal && (s1.charAt(i) == s2.charAt(i));
}
   return equal;
}

Update on 2 May 2014.

From the above code the line
if(!equal) return false; 
can be removed and it is still correct and may be more (less) efficient.
Another possibility pointed out by Sarada is to replace the conjunction by just comparison.
Instead of
equal = equal && (s1.charAt(i) == s2.charAt(i));
have
equal =  (s1.charAt(i) == s2.charAt(i));
because the return statement above ensures that the boolean variable is always true just before the character comparison. We have two reasonable different programs.

Saurya's program:
public static boolean itercheck(String s1, String s2) {
boolean equal = true;
for (int i=0; i < s1.length(); i++){
    equal = equal && (s1.charAt(i) == s2.charAt(i));
}
    return equal;
}

Sarada's program:
public static boolean itercheck(String s1, String s2) {
boolean equal = true;
for (int i=0; i < s1.length(); i++){
if(!equal) return false;
    equal =  (s1.charAt(i) == s2.charAt(i));
}
    return equal;
}
The student's program combines two reasonable ideas to produce a buggy program.
My guess is his thinking was close to Sarada's program and probably forgot to include the if statement but went ahead with testing and felt good about many tests passing and submitted the faulty code.

Saturday, April 12, 2014

Coffeescript oneliner for square root calculation

To calculate square root of a  number.

coffee> srr = (x,est) -> if Math.abs(est*est - x) < 0.0005 then est else srr x, (est + x/est)*0.5
[Function]
coffee> srr 2,1
1.4142156862745097

Easy translation from English to code. 

If the square of a given estimate is within the tolerance of  0.0005 from the number, then the given estimate is the result, otherwise the result is the one given by the function with a new estimate which is the average of the given estimate and the quotient of the number divided by the given estimate.

Fairly declarative reading. If we do minimum necessary operational reasoning we can have an iterative formulation instead of the above recursive formulation.

If the square of a given estimate is within the tolerance of  0.0005 from the number, then the given estimate is the result, otherwise update the estimate by a new estimate which is the average of the given estimate and the quotient of the number divided by the given estimate and repeat the process until the tolerance is achieved.

Or equivalently, we can say while tolerance is not achieved, update the estimate.

Code in sri.coffee file indented as required by coffeescript

sri = (x,est) -> while Math.abs(est*est - x) > 0.0005
                               est = (est + x/est)*0.5
console.log(sri 2,1)

Let us execute this.

$ coffee sri.coffee
[ 1.5, 1.4166666666666665, 1.4142156862745097 ]

It is the peculiarity of while loop of coffeescript the result returned is an array of all estimates.