Enigmatic Code

Programming Enigma Puzzles

Enigma 1123: German squares

From New Scientist #2279, 24th February 2001

In the following statement digits have been consistently replaced by capital letters, different letters being used for different digits:

VIER and NEUN are both perfect squares.

If I told you the number represented by VIER you could deduce with certainty the number represented by NEUN. Alternatively, if I told you the number represented by NEUN you could deduce with certainty the number represented by VIER.

What is the numerical value of the square root of (VIER × NEUN)?

[enigma1123]

Advertisements

3 responses to “Enigma 1123: German squares

  1. Jim Randell 20 March 2017 at 8:37 am

    We can generate the 4-digit squares and look for pairs that match the alphametics VIER and NEUN ourselves, or we can use the SubstitutedExpression() solver from the enigma.py library to get a shorter program (although it does take slightly longer to run).

    Once we have the pairs I use the filter_unique() function to select the sets which give the solution.

    This Python program runs in 47ms.

    from enigma import SubstitutedExpression, filter_unique, is_square, unpack, printf
    
    # use the alphametic solver to find (VIER, NEUN) pairs
    p = SubstitutedExpression(
      [ "is_square(VIER)", "is_square(NEUN)" ],
      answer="(VIER, NEUN)"
    )
    
    # collect (VIER, NEUN) pairs
    r = list(s[1] for s in p.solve())
    
    # functions to extract VIER and NEUN from a (VIER, NEUN) pair
    vier = unpack(lambda v, n: v)
    neun = unpack(lambda v, n: n)
    
    # find pairs where VIER -> NEUN
    (u1, _) = filter_unique(r, vier, neun)
    
    # find pairs where NEUN -> VIER
    (u2, _) = filter_unique(r, neun, vier)
    
    # solution pairs are in both sets
    for (v, n) in set(u1).intersection(u2):
      root = is_square(v * n)
      printf("root = {root} [VIER={v} NEUN={n}]")
    

    Solution: The square root of (VIER × NEUN) is 7663.

    VIER = 6241 = 79², NEUN = 9409 = 97².

    The use of the unpack() function in lines 13-14 allows the code to work unmodified in both Python 2 or Python 3.

  2. geoffrounce 20 March 2017 at 11:15 am

    As different letters are used for different digits, VIER and NEUN must share the letter ‘E’

    I did a Python dictionary solution, with ‘E’ as the key and the tuple (VIER, NEUN ) as the value
    and looked for a single value of (VIER, NEUN ) based on the key ‘E’

    # form a list of 4-digit squares
    sq = [x * x for x in range(32, 100)]
    
    from itertools import permutations
    from collections import defaultdict
    d = defaultdict(list)
    
    for p in permutations ('1234567890', 6):
        v, i, e, r, n, u = p
        if v == '0': continue
        vier = int(v + i + e + r)
        if vier in sq:
            neun = int(n + e + u + n)
            if n == '0': continue
            if neun in sq:
                # reference two squares on common letter 'E'
                d[e] += [(vier, neun)]
                
    # look for a single value of (vier,neun) in dictionary d,
    # referenced by the common letter 'e'
    for k,v in d.items():
        if len(v) == 1:
            print('VIER = {}, NEUN = {} '.format(v[0][0],v[0][1]))
            VIER, NEUN = v[0][0], v[0][1]
            print('Square Root of (VIER * NEUN) = {}'.format \
                  (int(VIER**0.5 * NEUN**0.5)))
    
    # VIER = 6241, NEUN = 9409
    # Square Root of (VIER * NEUN) = 7663
    

    A full dictionary print-out of key (letter ‘E’) and values (VIER,NEUN] gives:

    6 [(1369, 4624), (1369, 5625), (1764, 5625), (4761, 5625),
    (7569, 1681), (7569, 4624)]

    5 [(4356, 1521), (7056, 1521)]

    4 [(6241, 9409)]

  3. Brian Gladman 20 March 2017 at 2:31 pm
    from itertools import product
    from collections import defaultdict
    
    # four digit squares
    sqrs = [str(x ** 2) for x in range(32, 100)]
    # four digit squares without duplicated digits (for VIER)
    vsqr = [x for x in sqrs if len(set(x)) == 4]
    # four digit squares with a duplicated digit (for NEUN)
    nsqr = [x for x in sqrs if len(set(x)) == 3 and x[0] == x[3]]
    
    # map squares for VIER to those for NEUN and vice versa
    v2n, n2v = defaultdict(list), defaultdict(list)
    for v, n in product(vsqr, nsqr):
      # they must have six different digits and share one 
      if len(set(v + n)) == 6 and v[2] == n[1]:
        v2n[v].append(n)
        n2v[n].append(v)
    
    # remove values for VIER that don't identify NEUN and vice versa
    v2n1 = set((v, nl[0]) for v, nl in v2n.items() if len(nl) == 1)
    v2n2 = [(vl[0], n) for n, vl in n2v.items() if len(vl) == 1]
    
    # look for digits for VIER and NEUN whose products are square  
    for v, n in set(v2n1).intersection(v2n2):
      vi, ni = int(v), int(n)
      rt = int((vi * ni) ** 0.5)
      if rt ** 2 == vi * ni:
        print(f'Square root = {rt}, VIER = {vi}, NEUN = {ni}.')
    

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: