20-CS-694 Advanced Programming Techniques Spring 2012

Interfaces, Exceptions, Graphics, Animation, Threads, Reflection, Networking, RMI, JDBC, JNI

Previous     Next     All lectures

Use in Execution Control

Instructions for all applets:

All applets contain a 'Press Me' button. Click it.

    1.   puzzle.java

    Given three variables, i,j,k which take value 0 or 1, we want to find values for these values that cause a logical expression such as
     ¬i ∧ j ⊕ i ∧ ¬k ⊕ ¬j ∧ k
to evaluate to 1, where ∧ means logical 'and', ¬ means 'not' and ⊕ means 'exclusive-or'. This can be solved using three nested for loops as shown in this slide. Variables are declares as integers but are assigned values only from the set {0,1}. Then the multiplication x*y corresponds to x y, (1-x) corresponds to ¬x, and (x+y)%2 corresponds to x y.

A simple solution is to implement nested for loops, one for each variable, to set values. A potential problem is that nesting can be deep and awkward. This sequence of slides flattens this out with exceptions.

    2.   puzzle.java

    The loop structure is flattened. Each Choose object executes the for loop for a particular variable. Each for loop is linked, in order of nesting, through the Choose constructor. The Evaluate object eval solves the problem and must be linked to the most deeply nested loop. But that means it should be the same type as Choose, which creates a problem. The problem is solved by defining a Variable interface which is implemented by Evaluate and Choose. The interface requires checkit() which is the method that either loops through variable values in the case of Choose objects or evaluates the given expression in the case of eval. The interface also requires implementing v() which returns the current value of a Choose object and is used by eval to instantiate values for testing in the given logic expression.

The code is a bit awkward, though, because a set method is needed in the Evaluate class so that eval knows what Variable object values to apply to its logical expression - these cannot be given to eval when it is created because it must be created before the Choose objects. One solution, shown in the next slide, is to create the variables from within the Evaluate object.

    3.   puzzle.java

    Things are looking better because the Choose instantiations have been moved to Evaluate. Now we can try to generalize this so the control structure can be reused for a variety of problems.
    4.   puzzle.java

    The interface Variable has changed: its checkit() method no longer returns a boolean and, instead, throws an Up exception. Accordingly, the Up class is defined, without state, to extend the Exception class. The checkit() method catches an Up exception from its Choose object: this is what keeps the loop going until it ends and, when that happens, checkit() throws an Up to the next higher level. By using Up we can define method assert_() in the Evaluate class: if an expression evaluates to 0 (false), an Up is thrown by assert_(). This allows all control statements to be removed from checkit() in Evaluate which is significant because, except for solve(), that is the method that a user will have to change for every different problem this approach is going to be used to solve.

Two improvements can be made right away to the code below. If we only want one result instead of all results we can define an Out exception class and raise that exception when a solution is found. The Out object will then be passed right up to the top, bypassing all the intermediate catch blocks which are looking for Up exceptions. The second improvement is to remove the v() and abstract_() methods from the Evaluate class. The abstract_() method will be needed to solve any problem like this so let's put it in a Puzzle class and extend from that. We might as well put the v() in there too to get it out of the way. This is done on the next slide.

    5.   puzzle.java

    In order to stop at the first solution we define an Out exception to be used in checkit() of Evaluate in case assert_() succeeds. An Out exception is only caught at the top level in solve of Evaluate. Therefore, throwing an Out terminates computation (after a solution is printed before throwing it). If the top level is reached via a thrown Up, there is no solution and a message is printed.

To streamline the coding process for future users the Puzzle class is created to hold v(), which is required by the Variable interface, and assert_(), which should never change from use to use.

    6.   puzzle.java

    Final cleanup - Generalize Choose to take a string of tokens as constructor argument. Every time through the loop of a Choose object the object's value changes to the next token in the argument string. After all tokens are used, an Up is thrown.
    7.   puzzle.java

    The Kalotans are a tribe with a peculiar quirk: their females always tell the truth. Their males never make two consecutive true statements, or two consecutive untrue statements.

An anthropologist (let's call him Worf) has begun to study them. Worf does not yet know the Kalotan language. One day, he meets a Kalotan (heterosexual) couple and their child Kibi (also called "kid"). Worf asks the kid: ``Are you a boy?'' The kid answers in Kalotan, which of course Worf doesn't understand.

Worf turns to the parents (who know English) for explanation. One of them (parent1) says: "Kibi said: `I am a girl.'" The other (parent2) adds: "Kibi is a boy. Kibi lied."

Solve for the sex of the parents and Kibi.

Let variable prnt1 be the first responding parent, let variable prnt2 be the second responding parent, let variable kid be the sex of Kibi, let variable kid-lied be true if and only if Kibi lied, let variable kid-said be the response of Kibi to Worf's question.