Enigmatic Code

Programming Enigma Puzzles

Enigma 1319: Latin Christmas tree

From New Scientist #2477, 11th December 2004

My junior class has been studying Roman numerals. I asked them to replace each asterisk in the picture below with I, V or X so that each row formed a different valid Roman numeral, and either all were even or all were odd.

Enigma 1319

No letter was to appear in a row if it  did not also occur in all the rows below it. When we totted up all the numbers appearing in each design, we found that Alice’s sum was the same as Barbara’s, although the individual numbers in their designs were not all the same.

What was this score?

[enigma1319]

Advertisements

One response to “Enigma 1319: Latin Christmas tree

  1. Jim Randell 5 June 2014 at 8:27 am

    This Python3 program uses the int2roman() function from the enigma.py library. It runs in 62ms.

    from collections import defaultdict
    from enigma import irange, int2roman
    
    # determine roman numerals by parity and number of digits
    d = (defaultdict(list), defaultdict(list))
    for i in irange(1, 39):
      r = int2roman(i)
      d[i % 2][len(r)].append((i, r))
    # special case for IIII
    d[0][4].append((4, 'IIII'))
    
    # ls - lengths of roman numerals
    # rs - list of roman numerals
    # ns - list of corresponding integers
    # d - roman numerals to consider (by length)
    def solve(ls, rs, ns, d):
      # are we done?
      if not ls:
        yield (rs, ns)
      else:
        # find a roman number of the required length
        for (i, r) in d[ls[0]]:
          # all are unique
          if r in rs: continue
          # and once a letter is used it must be in subsequent numerals
          s = set(r)
          if not all(s.issuperset(x) for x in rs): continue
          yield from solve(ls[1:], rs + [r], ns + [i], d)
    
    # find solutions for the problem and record the sets of roman numerals
    # used by the sum of the numbers involved
    r = defaultdict(set)
    for p in (0, 1):
      for (rs, ns) in solve((1, 2, 3, 4, 5, 6, 7, 3, 3, 4, 4), [], [], d[p]):
        r[sum(ns)].add(tuple(sorted(rs)))
    
    # now find sums with multiple solutions
    for (k, v) in r.items():
      if len(v) < 2: continue
      print(k, v)
    

    Solution: The common score is 246.

    The two designs are:

     10 =        X                X        = 10
     20 =       X X              X X       = 20
     30 =      X X X            X I I      = 12
     22 =     X X I I          X X I I     = 22
     18 =    X V I I I        X X X V I    = 36
     28 =   X X V I I I      X X V I I I   = 28
     38 =  X X X V I I I    X X X V I I I  = 38
     14 =     {X I V}          {X I V}     = 14
     16 =     {X V I}          {X V I}     = 16
     24 =    {X X I V}        {X X I V}    = 24
     26 =    {X X V I}        {X X V I}    = 26
    ---                                     ---
    246                                     246
    ===                                     ===

    The numerals in braces may appear in either order.

    We could simplify the search by noting that the only available 7 letter Roman numeral is 38, and so only consider even numbers.

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: