Enigmatic Code

Programming Enigma Puzzles

Enigma 1432: Roman and Arabic

From New Scientist #2593, 3rd March 2007

XVI and LXIV are both Roman numeral perfect squares. If you replace the capital letters consistently with digits, using a different digit for each letter, you can translate XVI and LXIV into Arabic numeral perfect squares, neither of which starts with a zero.

Using the digital values of I, V, X and L that you have discovered;

(1) find another Roman numeral perfect square that uses only these letters (more than one but not necessarily all of them) and translates into an Arabic numeral perfect square;

(2) find a valid Roman numeral that uses only these letters (more than one but not necessarily all of them) and is not itself a perfect square but translates into an Arabic perfect square.

Give the Roman numerals you found in answer to (1) and (2) and the Arabic numerals that each of them translates to.

[enigma1432]

One response to “Enigma 1432: Roman and Arabic

  1. Jim Randell 12 May 2013 at 6:12 am

    This Python program runs in 46ms.

    from collections import Counter
    from enigma import irange, is_duplicate, split, nconcat, int2roman, is_square, printf
    
    # 3-digit squares with no repeated digits
    sq3 = set(s for s in (i * i for i in irange(10, 31)) if not is_duplicate(s))
    
    # 4-digit squares with no repeated digits
    sq4 = set(s for s in (i * i for i in irange(32, 99)) if not is_duplicate(s))
    
    # translate a word (sequence of letters) to an integer
    def translate(d, w):
      return nconcat(d[x] for x in w)
    
    # find 4-digit squares LXIV such that XVI is a 3-digit square
    for LXIV in sq4:
      d = dict(zip('LXIV', split(LXIV, int)))
      XVI = translate(d, 'XVI')
      if XVI not in sq3: continue
      printf("LXIV={LXIV} XVI={XVI}")
    
      # find roman numerals that are squares when translated
      # (any number 90 or more will have letters we can't use in it)
      numerals = set(d.keys())
      for i in irange(1, 89):
        r = int2roman(i)
        c = Counter(r)
        # must use the required letters, and at least two of them
        if not(len(c.keys()) > 1 and numerals.issuperset(c.keys())): continue
        # translation must be a square
        s = translate(d, r)
        if not is_square(s): continue
    
        if is_square(i):
          # part 1: a (different) roman square
          if i not in (16, 64): printf("[1] {r} => {s}")
        else:
          # part 2: a non-square
          printf("[2] {r} => {s}")
    

    Solution: (1) IV (4) translates to 16; (2) XLIV (44) translates to 9216.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: