Enigmatic Code

Programming Enigma Puzzles

Enigma 1382: Counter pain

From New Scientist #2542, 11th March 2006 [link]

Joe placed five numbered counters in a circle as shown. All Penny had to do was repeat the process for the inner circle with five similarly numbered counters so that no two adjacent counters would have the same number and, when the pairs of adjacent counters (shown joined by a line) were listed, no two pairs would be the same.

Enigma 1382

Penny soon gave up, saying that Joe should have placed a higher number of counters in the outer circle. Joe did and Penny solved the puzzle. Penny wrote down her solution as a multi-digit number formed by all the digits on the counters in order (a b c d e …).

What is the smallest number Penny could have written?

I couldn’t find a source for this puzzle online, but the nice people at the Reference Department at Bristol Central Library were able to find a physical copy of the magazine for me.

I have also enabled ratings for puzzles to allow contributors to the site to rate puzzles on a scale of 1 to 5 stars. Look for the “Rate this:” section below the puzzle statement.

[enigma1382]

Advertisements

One response to “Enigma 1382: Counter pain

  1. Jim Randell 19 October 2013 at 9:03 am

    In this Python 3 program I use a dict() to keep track of the pairs of numbers that have been used. I could have encapsulated this code into a class. The code generates the numbers in the inner in numerical order, but I look for the smallest possible composite number using min() in case we end up with more than 9 counters. This code runs in 53ms.

    from collections import defaultdict
    from itertools import count
    from copy import deepcopy
    from enigma import irange, concat, printf
    
    # we represent used pairs by a dictionary mapping the smallest
    # member of the pair to used larger memebers
    
    # add a pair to a collection (if possible)
    def pairs_add(pairs, a, b):
      if a == b: return False
      if b < a: (a, b) = (b, a)
      if a in pairs:
        if b in pairs[a]: return False
        pairs[a] = pairs[a] + [b]
      else:
        pairs[a] = [b]
      return True
    
    # initialise a pairs dict
    def pairs_init(n, outer):
      pairs = dict()
      for (i, c) in enumerate(outer):
        pairs_add(pairs, c, outer[-1 if i == 0 else i - 1])
        pairs_add(pairs, c, outer[0 if i == n - 1 else i + 1])
      return pairs
    
    # n - number of items in each ring
    # outer - the outer ring
    # inner - the inner ring
    # i - index in the inner ring
    # pairs - pairs made so far
    def solve(n, outer, inner, i, pairs):
      if i == n:
        if pairs_add(pairs, inner[0], inner[-1]):
          yield inner
      else:
        # choose a number
        for c in outer:
          # which we haven't already used
          if c in inner: continue
          # it can't duplicate an existing pair
          ps = pairs.copy()
          if not pairs_add(ps, c, outer[i]): continue
          if inner and not pairs_add(ps, c, inner[-1]): continue
          yield from solve(n, outer, inner + [c], i + 1, ps)
    
    for n in count(5):
      outer = list(irange(1, n))
      r = list(solve(n, outer, [], 0, pairs_init(n, outer)))
      printf("n={n}: {l} solutions", l=len(r))
      if not r: continue
    
      for s in r:
        print(s)
    
      m = min(concat(*s) for s in r)
      printf("min = {m}")
    
      break
    

    Solution: The smallest number Penny could have written is 35728416.

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: