Enigmatic Code

Programming Enigma Puzzles

Enigma 1620: Pieces of eight

From New Scientist #2785, 6th November 2010 [link]

Eight candidates, referred to as A, B, C,…, H are competing for a prize. They sit in a circle in alphabetical order, with H next to A. Each is allotted a whole number known only to the supervisor, who, for each person in turn, announces the sum of the numbers in the trio of neighbours of which he or she is the centre. For example, if H, A, B have numbers 12, 17, 4 then the sum for A is 33. The actual sums are A 38; B 49; C 45; D 48; E 52; F 44; G 39; H 48.

Which two candidates have the closest numbers?

[enigma1620]

Advertisements

One response to “Enigma 1620: Pieces of eight

  1. jimrandell 26 December 2011 at 11:47 am

    The following Python program runs in 30ms:

    from itertools import combinations
    
    # sums of three adjacent terms (A - H)
    s = (38, 49, 45, 48, 52, 44, 39, 48)
    n = len(s)
    
    # terms
    t = [chr(65 + i) for i in range(n)]
    
    # base-n increment/decrement
    def inc(i, j=1): return (i + j) % n
    def dec(i, j=1): return (i - j) % n
    
    # so by subtracting adjacent sums we get the difference between two terms
    d = dict((i, {}) for i in t)
    for i in range(n):
      d[t[dec(i)]][t[inc(i, 2)]] = s[i] - s[inc(i)]
    
    # now lets work out offsets from A
    k = 'A'
    offset = { k: 0 }
    
    def compute(offset, k):
      for i in d[k].keys():
        if i in offset: continue
        offset[i] = offset[k] - d[k][i]
        compute(offset, i)
    
    compute(offset, k)
    
    # now from the first sum we know: H + A + B = 38
    # so: (A + offset['H']) + (A) + (A + offset['B']) = 38
    # so: 3A + offset['H'] + offset['B'] = 38
    # so: A = (38 - offset['H'] - offset['B']) / 3
    
    A3 = 38 - offset['H'] - offset['B']
    (A, r) = divmod(A3, 3)
    assert r == 0
    
    # compute the actual values
    v = dict((i, A + offset[i]) for i in t)
    print(v)
    
    # find the closest values
    # (we could compute these straight from v = offset, as we don't care about the actual values)
    m = None
    for (i, j) in combinations(t, 2):
      x = abs(v[i] - v[j])
      if not(m is None or x < m[0]): continue
      m = (x, i, j)
    print("|{i} - {j}| = {x}".format(i=m[1], j=m[2], x=m[0]))
    

    Solution: C and G have the closest 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: