20-CS-694 Advanced Programming Techniques Spring 2012
Exceptions for control

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

       Previous     Next     Applet Source     All lectures

Example: Kalotan Puzzle

Kaloton Puzzle:
    The Kalotans are a tribe with a peculiar quirk: their males always tell the truth. Their females 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 says: "Kibi said: `I am a boy.'" The other adds: "Kibi is a girl. Kibi lied."

Solve for the sex of the parents and Kibi.

 
   import java.awt.*;
   import java.awt.event.*;
   import java.util.*;
   import javax.swing.*;
   import java.applet.*;
   
   //   Let variable parent1 be the first responding parent,
   //   let variable parent2 be the second responding parent,
   //   let variable kid be the sex of Kibi
   class KalotanPuzzle extends Puzzle implements Variable {
      Variable parent1, parent2, kid, kid_lied;
      G problem;
   
      public KalotanPuzzle (G problem) {  this.problem = problem; }
   
      public void checkit () throws Up, Out {
         // Parents must be of different sex
         assert_(!parent1.value().equals(parent2.value()));
         // If the first parent responding is male then either
         // the kid is male and did not lie or
         // the kid is female and lied
         assert_(parent1.value().equals("female") ||
                 (kid.value().equals("male") &&
                  kid_lied.value().equals("false")) ||
                 (kid.value().equals("female") &&
                  kid_lied.value().equals("true")));
         // If the second parent responding is male then
         // the kid is female and lied
         assert_(parent2.value().equals("female") ||
                 (kid.value().equals("female") &&
                  kid_lied.value().equals("true")));
         // If the second parent responding is female then
         // either the kid is male and lied or
         // the kid is female and did not lie
         assert_(parent2.value().equals("male") || 
                 (kid.value().equals("male") && 
                  kid_lied.value().equals("true")) ||
                 (kid.value().equals("female") &&
                  kid_lied.value().equals("false")));
         // If all assertions are true, print the values of parents, and kid
         problem.out.append("Parent1:"+parent1.value()+" "+
                            "Parent2:"+parent2.value()+" "+
                            "Kid:"+kid.value()+"\n");
         throw new Out();
      }
   
      public void solve () {
         try { 
            parent1  = new Choose("male female", this);
            parent2  = new Choose("male female", parent1);
            kid      = new Choose("male female", parent2);
            kid_lied = new Choose("true false", kid);
            kid_lied.checkit(); 
         } 
         catch (Up up) {
            problem.out.append("No solution found\n");
         }
         catch (Out out) { 
            problem.out.append("Done\n"); 
         }
      }
   }
   
   /*** The following remains the same for all problems of this type  ***/
   interface Variable {  void checkit () throws Up, Out;  String value (); }
   
   class Up extends Exception { }
   
   class Out extends Exception { }
   
   class Choose implements Variable {
      Variable next_for;
      String [] strs;
      String val;
      int n;
      
      public Choose(String s, Variable next_for) {  
         this.next_for = next_for;
         StringTokenizer t = new StringTokenizer(s," ");
         n = t.countTokens();
         strs = new String[n];
         for (int i=0 ; i < n ; i++) strs[i] = t.nextToken();
      }
   
      public String value () { return val; }
   
      public void checkit () throws Up, Out {
         for (int i=0 ; i < n ; i++)  {
            val = strs[i];
            try {  next_for.checkit();  } catch (Up up) { }
         }
         throw new Up();
      }
   }
   
   class Puzzle {
      public String value () { return null; }
      public void assert_ (boolean e) throws Up { if (!e) throw new Up(); }
   }
   
   /*** end of the common code section  ***/
   
   public class G extends Applet implements ActionListener {
      JTextArea out;
      JButton button;
   
      public void init () {
         setLayout(new FlowLayout());
         add(new JScrollPane(out = new JTextArea(16,30)));
         add(button = new JButton("Press Me"));
         button.addActionListener(this);
      }
   
      public void doit() {
         KalotanPuzzle kalotan = new KalotanPuzzle(this);
         kalotan.solve();
      }
   
      public void actionPerformed (ActionEvent evt) {  doit(); }
   }