Enigmatic Code

Programming Enigma Puzzles

Enigma 279: Tall stories

From New Scientist #1426, 18th October 1984 [link]

I’ve just been taking to four interesting sisters. I asked the youngest how old she was. She whispered the answer to the tallest sister who whispered the answer to Anita who told me the answer was 53. I was a bit surprised and so I assumed that one of those three must have made a mistake. So I asked the eldest how old she was. She whispered the answer to Barbara who whispered the answer to the shortest who told me the answer was 26! Had these three made a mistake?

Charlotte then explained to me that although all four of them knew their facts and did their calculations correctly, before stating a number they always changed it. One of the sisters always doubled her numbers, one always added 1, one always reversed the digits, and one always squared her numbers and deleted the left-hand digit of that square.

The second eldest sister said she’d help. She asked the eldest and youngest their ages (and the eldest’s answer was the larger of the two) and she calculated the difference and told me what it was: I happened to know that this was also her age.

Then the youngest whispered her age to Davina who whispered it to the second tallest who told me.

What number did she tell me?



One response to “Enigma 279: Tall stories

  1. Jim Randell 9 May 2015 at 8:40 am

    This puzzle is similar to Enigma 242 (also set by Susan Denham), but this version is a bit more involved.

    I wondered if the statement of the sisters “quirks”, which contains a number, was subject to those quirks, but as it was not a direct quote from one of the sisters I decided not to explore that possibility.

    from itertools import permutations
    from collections import defaultdict
    from enigma import is_square, first, printf
    # the four quirks, and their inverses
    # "one sister always doubled her numbers"
    def double(x, inv):
      if inv:
        (d, r) = divmod(x, 2)
        if r == 0:
          yield d
        yield x * 2
    # "one sister always added 1"
    def plus1(x, inv):
      if inv:
        if x > 0:
          yield x - 1
        yield x + 1
    # "one sister always reversed the digits"
    def reverse(x, inv):
      s = str(x)
      if s[-1] != '0':
        yield int(s[::-1])
    # "one sister squared her numbers and deleted the left hand digit"
    def square(x, inv):
      if inv:
        s = str(x)
        for d in '123456789':
          n = is_square(int(d + s))
          if n is not None:
            yield n
        s = str(x * x)[1:]
        if len(s) > 1 and s[0] != '0':
          yield int(s)
    # possible values from evaluating the chain
    # (using inverse functions if inv=True)
    def chain(v, fns, inv=False):
      if not fns:
        yield v
        for x in fns[-1](v, inv):
          yield from chain(x, fns[:-1], inv)
    # label the sisters
    sisters = (A, B, C, D) = (0, 1, 2, 3)
    # assign the quirks
    for quirk in permutations((double, plus1, reverse, square)):
      # assign the age order (youngest to eldest)
      for age in permutations(sisters):
        # A cannot be youngest, B cannot be eldest, D cannot be youngest
        if age[0] == A or age[3] == B or age[0] == D: continue
        # assign the height order (shortest to tallest)
        for height in permutations(sisters):
          # A cannot be tallest, B cannot be shortest, D cannot be 2nd tallest
          if height[3] == A or height[0] == B or height[2] == D: continue
          # youngest cannot be tallest, eldest cannot be shortest
          if age[0] == height[3] or age[3] == height[0]: continue
          # the first chain is: (youngest) -> (tallest) -> (A)
          f1 = tuple(quirk[s] for s in (age[0], height[3], A))
          # calculate the actual age of the youngest sister
          for a0 in chain(53, f1, inv=True):
            # the second chain is: (eldest) -> (B) -> (shortest)
            f2 = tuple(quirk[s] for s in (age[3], B, height[0]))
            # calculate the actual age of the eldest sister
            for a3 in chain(26, f2, inv=True):
              if not(a0 < a3): continue
              # get the reported ages of the youngest and eldest
              for ya0 in chain(a0, [quirk[age[0]]]):
                for ya3 in chain(a3, [quirk[age[3]]]):
                  if not(ya0 < ya3): continue
                  # the difference reported by the second eldest is her actual age
                  for a2 in chain(ya3 - ya0, [quirk[age[2]]]):
                    if not(a0 < a2 < a3): continue
                    # a0 -> (youngest) -> D -> (second tallest) -> ???
                    for v in chain(ya0, [quirk[height[2]], quirk[D]]):
                      printf("{v} [a0={a0} ({ya0}), a2={a2}, a3={a3} ({ya3})]")

    Solution: The number was 312.

    The only solution is as follows (in age order)

    C = youngest (17), 2nd tallest, doubles numbers.
    A = 2nd youngest (18-27), shortest, reverses numbers.
    B = 2nd eldest (28), tallest, adds one to numbers.
    D = eldest (31), 2nd shortest, squares and truncates numbers.

    In the first scenario the youngest (C, aged 17), doubles her age to 34 and tells B (the tallest), who adds one to get 35, and tells A, who reverses to get 53. The setter could well be surprised at a 17 year old with a reported age of 53.

    In the second scenario the eldest (D, aged 31), squares and truncates her age to give 61 and tells B, who adds one to get 62, and tells A (the shortest) who reverses it to give 26. The setter seems to be unsure if a mistake was made here, and it is easier to accept that a 31 year old could be mistaken for a 26 year old.

    Charlotte then explains the situation. Which she either manages to explain without mentioning any numbers (as she would double them before speaking them), or the setter is sufficiently clued up to determine the actual situation and report it to us.

    In the third scenario C (the youngest, aged 17) reports her age as 34 to B (2nd eldest), and D (the eldest, aged 31) reports her age as 62 to B. As required the number reported by the eldest is larger than the number reported by the youngest. B then calculates the difference between these two numbers, 27, and reports that as 28 to the setter. Which co-incidentally is B’s actual age.

    In the final scenario C (the youngest, aged 17) reports her age as 34 to D, who squares and truncates it and reports it back to C as 156. (Note that in this scenario the setter does not tell us that the sisters involved are all different). C then doubles this to report 312 to the setter.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: