Enigmatic Code

Programming Enigma Puzzles

Enigma 1780: Pure hedronism

From New Scientist #2948, 21st December 2013 [link]

Enigma 1780

Joe’s problem for Penny this week was to number each triangle of an icosahedron with one of the digits 1 to 5 so that each of the five triangles meeting at a point was numbered differently. Some of the digits in Penny’s solution are shown in the diagram of an icosahedron dissected and laid flat. Six of the digits are covered with the letters ENIGMA. What are those digits?

New Scientist has announced that this will be the final Enigma puzzle.

I’m a little bit shocked, as I’ve become used to programming solutions to them. Fortunately I’m not quite a third of the way through the archive of all Enigma puzzles, so I’ll be able to keep posting classic puzzles for some time.

[enigma1780]

Advertisements

5 responses to “Enigma 1780: Pure hedronism

  1. Jim Randell 18 December 2013 at 9:39 am

    This puzzle is quite similar to Enigma 1391 (also by Bob Walker), so I took that code and modified it slightly to solve this puzzle. This Python program runs in 33ms.

    #   /\    /\    /\    /\    /\
    #  / 0\  / 1\  / 2\  / 3\  / 4\
    # /____\/____\/____\/____\/____\
    # \    /\    /\    /\    /\    /\
    #  \ 5/10\ 6/11\ 7/12\ 8/13\ 9/14\ 
    #   \/____\/____\/____\/____\/____\
    #    \    /\    /\    /\    /\    /
    #     \15/  \16/  \17/  \18/  \19/
    #      \/    \/    \/    \/    \/
    
    from enigma import irange, nconcat, printf
    
    # the faces (clockwise around each vertex)
    v2f = [
      # "top" vertex
      (0, 4, 3, 2, 1),
      # vertices surrounding "top"
      (0, 1, 6, 10, 5),
      (1, 2, 7, 11, 6),
      (2, 3, 8, 12, 7),
      (3, 4, 9, 13, 8),
      (4, 0, 5, 14, 9),
      # vertices surrounding "bottom"
      (5, 10, 15, 19, 14),
      (6, 11, 16, 15, 10),
      (7, 12, 17, 16, 11),
      (8, 13, 18, 17, 12),
      (9, 14, 19, 18, 13),
      # "bottom" vertex
      (15, 16, 17, 18, 19),
    ]
    
    # colours
    colours = set(irange(1, 5))
    
    # return an updated list
    def update(cs, i, c):
      cs = list(cs)
      cs[i] = c
      return cs
    
    # colour the icosohedron
    def solve(cs):
      # find an uncoloured face
      try:
        i = cs.index(0)
      except ValueError:
        # if there are none, so we're done
        print(cs)
        ENIGMA = nconcat(cs[i] for i in (6, 11, 7, 12, 8, 13))
        printf("ENIGMA={ENIGMA}")
      else:
        # colour it such that no vertex has duplicate colours
        for c in colours:
          if any(c in (cs[i] for i in f) for f in v2f if i in f): continue
          solve(update(cs, i, c))
    
    # initial configuration
    #      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
    solve([2, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 2])
    

    Solution: ENIGMA = 324125.

  2. arthurvause 18 December 2013 at 10:57 am

    Sadly, a very easy puzzle to solve manually:
    Using Jim’s numbering, #18 has to be 4, #1 has to be 1.
    #9 must be 1 or 5. Trying #9 = 5, chasing round the vertices quickly leads to a contradiction, so #9=1, and the remaining cells can be filled in by chasing round the vertices.

    It’s sad to see Enigma go out with such an easy puzzle. I will miss it, as I have been doing Enigma, and its predecessor Tantalizer since I was at school in the early 1970s.

    I will have to do more Project Euler from now on, and of course old Enigmas that Jim puts up.

    • Jim Randell 18 December 2013 at 4:56 pm

      You’re right – it is very straightforward by hand. A bit of a shame for Enigma to bow out in such a manner. Although it’s been quite a while since we’ve had a really interesting puzzle in the magazine – most of the one’s I’ve been finding fun to solve have been from back issues.

      I’ll keep adding “classic” puzzles to the site. I’ll probably put a new one up every other day starting on Saturday.

  3. Brian Gladman 18 December 2013 at 4:44 pm

    I am surprised and disappointed to see the New Scientist enigma puzzles go – I hope that the Sunday Times doesn’t drop its teasers in the same way.

    # Label faces and vertexes as follows (a = 10, b = 11):
    #
    #    0     0     0     0     0
    #   / \   / \   / \   / \   / \
    #  / 0 \ / 1 \ / 2 \ / 3 \ / 4 \
    # 1-----2-----3-----4-----5-----1
    #  \ 5 /1\ 6 /1\ 7 /1\ 8 /1\ 9 /1\
    #   \ / 0 \ / 1 \ / 2 \ / 3 \ / 4 \
    #    6-----7-----8-----9-----a-----6
    #     \ 1 / \ 1 / \ 1 / \ 1 / \ 1 /
    #      \5/   \6/   \7/   \8/   \9/
    #       b     b     b     b     b
    
    # the face numbers at each vertex
    vtx_faces = ( 
        ( 0,  1,  2,  3,  4), ( 0,  4,  5,  9, 14), ( 0,  1,  5,  6, 10),
        ( 1,  2,  6,  7, 11), ( 2,  3,  7,  8, 12), ( 3,  4,  8,  9, 13),
        ( 5, 10, 14, 15, 19), ( 6, 10, 11, 15, 16), ( 7, 11, 12, 16, 17),
        ( 8, 12, 13, 17, 18), ( 9, 13, 14, 18, 19), (15, 16, 17, 18, 19) )
    
    def solve(f):
      while True:
        # find the face values at each vertex
        vtx_strs = tuple(''.join(f[i] for i in x) for x in vtx_faces)
        # skip solutions where any vertex contains a duplicate value
        if any(any(s.count(c) > 1 for s in vtx_strs) for c in '12345'):
          return
        # count the number of unset face values at each vertex 
        cnts, updated = tuple(s.count('?') for s in vtx_strs), False
        # find any vertexes with only one unset face value
        for i, c in enumerate(cnts):
          if c == 1:
            # find the unused face value at this vertex
            n, = set('12345') - set(vtx_strs[i])
            # and set the unset face with this value
            p = vtx_faces[i][vtx_strs[i].index('?')]
            f = f[:p] + n + f[p + 1:]
            updated = True
        # if some new values have been set, repeat the loop to see if 
        # any more can be set in this way; otherwise any vertexes with 
        # unset face values have more than one such value 
        if not updated:
          break
      # have all face values been set
      if '?' not in f:
        yield f
      else:
        # find a vertex with the fewest unset face values
        min_c, min_i = 6, 0 
        for i, c in enumerate(cnts):
          if c > 1 and c < min_c:
            min_c, min_i = c, i
        # now try all unused face values at this vertex on one
        # of the unset faces and continue in this way
        p = vtx_faces[min_i][vtx_strs[min_i].index('?')]
        for v in set('12345') - set(vtx_strs[min_i]):
          yield from solve(f[:p] + v + f[p + 1:])
    
    # the initial face values
    faces = '2???45????????31???2'
    for f in solve(faces):
      print('ENIGMA =', ''.join(f[i] for i in (6, 11, 7, 12, 8, 13)))
    
  4. ahmet çetinbudaklar 18 December 2013 at 6:00 pm

    As a late commer to the Enigmas I am surprised to see the whole series end in 1780.
    Fortunately we have Jim Randell who is spending tremendous time to fill up all the missing enigmas My teaser history goes back to early 1960’s with the Brain Twister of the Observer and The Brain Teaser of the Sunday Times, the former one being stopped in the 300’s with the loss of Dr.Barnard.
    Now just as I became so familiar with the Enigmas we have to say bye bye unfortunately and be content with the 1780 enigmas.
    Fortunately Jim and Brian are the two volunteers who insistingly and consistingly follow up and let us continue in helping our brains updated day after day if not week after week
    Carry on dancing in refreshing our minds.
    .

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: