The Age-of-the-Sons Riddle

This riddle was part of the "Jboss Drools Puzzle Contest", first round. It had been posted by Ellen Zhao to the Drools mailing list in August 2007.

The Riddle

An old man asked a mathematician to guess the ages of his three sons.

Old man said: “The product of their ages is 36.”
Mathematician said: “I need more information.”

Old man said:”Over there you can see a building. The sum of their ages equals the number of the windows in that building.”
After a short while the mathematician said: “I need more information.”

Old man said: “The oldest son has blue eyes.”
Mathematician said: “I got it.”

What are the ages of the three sons of the old man?

Comments on this Riddle

(from Ellen's blog entry)

The rule in the first sentence of the old man is obvious. The mathematician cannot decide the solution after he was told the second condition. This indicates that there are more than one triple of numbers whose products are 36 and sums are the same. The third condition tells that the greatest number in the triple has only one occurrence. So there is nothing really fancy in the rule definition files. The solution space of this puzzle is so tiny that the brute force search is good enough. Indeed, all participators implemented brute force search for this puzzle. Very interestingly there are three slightly different variants of this brute force search in the submissions.

My Solution

I based this solutions on finding two triples of Sons with:

  1. their ages are ordered, that is ai1 >= ai2 >= ai3, to ease comparison between the triples
  2. their product is always = 36: ai1 * ai2 * ai3 = 36 and
  3. equal sum (a11+a12+a13 = a21+a22+a23 (now the mathmatician still needs more information!)
  4. in one of the solutions ai1 > ai2 >= ai3 (there exists one eldest son )

The solution, as expected: two sons are 2 years old, the eldest is 9 years old.

rule "age of the sons"
        when
                // find first triple
                Son( $age1 : age)
                Son( $age2 : age >= $age1)
                Son( $age3 : age >= $age1, age >= $age2)
                eval(($age1*$age2*$age3) == 36 )

                // find second triple with eldest son!
                Son( $2age1 : age != $age1) // this triple differs from first triple!
                Son( $2age2 : age >= $2age1 )
                Son( $2age3 : age >= $2age1, age > $2age2 )
                eval(($2age1*$2age2*$2age3) == 36 )

                // the sum of the ages must be equal
                eval ( ($2age1 + $2age2+ $2age3) == ($age1 + $age2 + $age3))

        then
                System.out.println( "The solution: The younger sons are " + $2age1 + " and " + $2age2 + " yrs, the eldest is " + $2age3  + " yrs.");
                 System.out.println( "Triple 1: " + $age1 + "*" + $age2 + "*" + $age3 + "\tSum = " + ($age1 + $age2 + $age3) );
                System.out.println( "Triple 2: " + $2age1 + "*" + $2age2 + "*" + $2age3  + "\tSum = " + ($2age1 + $2age2 + $2age3) );
end
## The Java part of the solution Before you can evaluate this rule, you have to fill your working memory with some facts, initialize some timers etc:
package arc42.drools.samples.aots_riddle;

import java.io.InputStreamReader;

import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.compiler.PackageBuilder;

public class AgeOfTheSonsRiddle {

  public static void main(final String[] args) throws Exception {

    // timer
    final long startTime = System.currentTimeMillis();

    final PackageBuilder builder = new PackageBuilder();
    builder.addPackageFromDrl(new InputStreamReader(
        AgeOfTheSonsRiddle.class
            .getResourceAsStream("/AgeOfTheSons.drl")));

    final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
    ruleBase.addPackage(builder.getPackage());

    final StatefulSession session = ruleBase.newStatefulSession();

    final long setupTime = System.currentTimeMillis();
    int i;
    for (i = 0; i < 19; i++)
      session.insert(new Son(i));

    session.fireAllRules();

    final long endTime = System.currentTimeMillis();
    session.dispose();

    System.out.print("Setting up the rule base took: " + (setupTime - startTime) + " ms");
    System.out.println("Finding the solution took "
        + (endTime - setupTime) + " ms");
  }
}

The solution in Prolog

Again, the Prolog solution is more elegant, shorter and understandable than everything else :-)

nr(1).
nr(2).
nr(3).
nr(4).
nr(5).
nr(6).
nr(7).
nr(8).
nr(9).
nr(10).
nr(11).
nr(12).
nr(13).
nr(14).
nr(15).
nr(16).
nr(17).
nr(18).

mathRiddle(A1,A2,A3) :- nr(A1), nr(A2), nr(A3), A1 > A2, A2 >= A3,
        36 is A1 * A2 * A3,
        nr(B1), nr(B2), nr(B3), B1 >= B2, B2 >= B3,
        A1 =\= B1,
        36 is B1 * B2 * B3,
        AS is A1 + A2 + A3,
        BS is B1 + B2 + B3,
        AS = BS.