|20-CS-694||Advanced Programming Techniques||Spring 2012|
All applets contain a 'Press Me' button. Click it.
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
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.
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.
||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.|
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.
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
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.
||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.|
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.