Enigmatic Code

Programming Enigma Puzzles

Puzzle #171: The magic number bracelet

From New Scientist #3390, 11th June 2022 [link] [link]

“Here’s your 21st birthday present”, said Amy.

“A bracelet?”, frowned Sam.

“Not just any bracelet, it is a magic number bracelet because I know you love numbers. See how it has got five beads, each with a different positive number on it. You can find all the numbers from 1 to 21. But to find most of them, you have to add together adjacent beads.”

“For example, to make the number 17 you add together these three beads”, she said, pointing to the beads in positions A, B and C on the diagram. “Other numbers are found by adding two, three or four adjacent beads. And, of course, to get 21, you add up all five”.

What are the five numbers on Sam’s bracelet?

[puzzle#171]

5 responses to “Puzzle #171: The magic number bracelet

  1. Jim Randell 11 June 2022 at 9:17 am

    We have encountered puzzles with “magic circles” before. See: Teaser 1986, Enigma 985.

    In fact the solution to this puzzle is the same as Teaser 1986.

    Using the magic_circles.py program given in Enigma 985 we can see this is the only magic circle of size 5:

    % python3 magic_circles.py 5
    [n=5: 21 values]
    1: (1, 3, 10, 2, 5)
    [n=5: found 1 magic circles]
    

    Solution: The numbers on the bracelet are: 1, 3, 10, 2, 5.

    With (A, B, C) = (10, 2, 5).

  2. Frits 12 June 2022 at 2:24 pm

    We don’t need the number 17 requirement to find a unique solution.

       
    from itertools import permutations
    
    # for list with n numbers return the set of sums of 1...n-1 adjacent fields
    # (also circular)
    aSums = lambda s: {sum((s * 2)[i:i + j]) for j in range(1, len(s)) 
                                            for i in range(len(s))}  
    
    N = 5
    T = 21
    H = T // 2
    # if we can make sums 1...H with 1, 2, ... , N-1 adjacent beads
    # we can also make H+1, ..., T with the complement (and all beads)
    for p in permutations(range(1, H + 1), 5):
      if sum(p) != T: continue
      
      sums = sorted(aSums(p))
      # can we make sums 1, ..., 10 ?
      if sums[:H] != list(range(1, H + 1)):  continue
      
      # go from 2*N solutions to 1 solution: remove rotations and duplicates
      if p[0] != min(p) or p[1] > p[-1]: continue
      
      # we need to make number 17 with 3 adjacent beads
      if 17 not in {sum((p * 2)[i:i+3]) for i in range(N)}: continue
      
      print(N, "numbers:", p)
    
    • Frits 14 June 2022 at 12:47 pm

      A more general program:

      from enigma import arg
      from itertools import permutations
      
      # for list with n numbers return the set of sums of 1...n-1 adjacent beads
      # (also circular)
      aSums = lambda s: {sum((s * 2)[i:i + j]) for j in range(1, len(s))
                                               for i in range(len(s))}
                                               
      weave = lambda a, b: (b[:i] + a + b[i:] for i in range(len(b)+1))
                                               
      
      N = arg(5, 0, int, prompt="number of sectors")
      assert N > 1
      
      T = N**2 - N + 1
      H = int(T // 2)
      
      list_1toH = list(range(1, H + 1))
      
      # for a magic circle with N numbers and total sum T
      # the highest possible circle number is T - N(N-1)/2 which equals H + 1
      
      print(f"{N} sectors, {T} arrangements")
      
      # if we can make sums 1...H with 1, 2, ... , N-1 adjacent beads
      # we can also make H+1, ..., T with the complement (and all beads)
      
      c = 0
      # exclude mandatory numbers 1 and 2 from the permutations
      for p in permutations(range(3, H + 2), N - 2):
        if sum(p) != T - 3: continue
       
        # weave in the number 2
        for w in weave((2, ), p):
          p1 = (1, ) + w
         
          # remove reflection
          if p1[1] > p1[-1]: continue
         
          sums = sorted(aSums(p1))
          # can we make sums 1, ..., H ?
          if sums[:H] != list_1toH:  continue
      
          c += 1
          print(f"{c}: {N} numbers: {p1}")
      
  3. GeoffR 15 June 2022 at 7:15 pm
    % A Solution in MiniZinc
    include "globals.mzn";
    
    % Letter positions A,B,C,D,E as teaser diagram
    % Assumed upper bounds of five numbers 
    var 1..15:A; var 1..15:B; var 1..15:C; var 1..15:D; var 1..15:E;
    constraint all_different ([A, B, C, D, E]);
    
    % Given requirements
    constraint A + B + C + D + E == 21;
    constraint A + B + C == 17;
    
    set of int: req_nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
    13, 14, 15, 16, 17, 18, 19, 20, 21};
    
    var set of int: soln_nums == 
    { A,B,C,D,E,
      A+B, B+C, C+D, D+E, E+A,
      A+B+C, B+C+D, C+D+E, D+E+A, E+A+B,
      A+B+C+D, B+C+D+E, C+D+E+A, D+E+A+B, E+A+B+C,
      A+B+C+D+E };
    
    % All numbers from 1..21 can be formed from five digits A,B,C,D,E                        
    constraint soln_nums == req_nums;
    
    solve satisfy;
    
    output ["[A, B, C, D, E ] = " ++ show([A,B,C,D,E ] ) ];
    
    % [A, B, C, D, E ] = [5, 2, 10, 3, 1]
    % ----------
    % [A, B, C, D, E ] = [10, 2, 5, 1, 3]  << published solution
    % ----------
    % ==========
    
    
    
    
  4. Frits 16 June 2022 at 5:23 pm
       
    # https://pypi.org/project/python-constraint/
    
    from enigma import arg
    from constraint import Problem, AllDifferentConstraint, ExactSumConstraint
    
    # check whether all adjacent numbers in circular list <li> 
    # sum up to 1,2, ... ,T
    def adjacent_sum(li, T):
      n = len(li)
      li2 = li * 2
      
      # start with single numbers and total
      seen = set(li + (T, ))
      for ln in range(2, n):
        for j in range(1, n + 1):
          if sum(li2[j:j + ln]) in seen:
            return False
          seen.add(sum(li2[j:j + ln]))
        
      return max(seen) == T
    
    N = arg(5, 0, int, prompt="number of sectors")
    assert N > 1
    
    T = N**2 - N + 1
    H = int(T // 2)
    
    print(f"[N={N}] {T} arrangements")
    
    p = Problem()
    
    # Variables
    
    # for a magic circle with N numbers and total sum T
    # the highest possible circle number is T - N(N-1)/2 which equals H + 1
    
    # go from 2*N solutions to 1 solution: remove rotations and duplicates
    p.addVariables(("1"), [1]) 
    p.addVariables(("2"), list(range(2, H + 1))) 
    p.addVariables((str(N)), list(range(3, H + 2))) 
    for i in range(3, N):
      p.addVariables((str(i)), list(range(2, H + 2))) 
    
    # Constraints
    #p.addConstraint(lambda x, y: x > y, ("A", "B"))  
    
    # variables should have different values
    p.addConstraint(AllDifferentConstraint())
    
    # sum of N variables is T
    p.addConstraint(ExactSumConstraint(T))
    
    # remove rotation
    p.addConstraint(lambda x, y: x < y, ('2', str(N)))
    
    # see if we can make numbers 1,2, ..., T 
    p.addConstraint(lambda *li: adjacent_sum(li, T), tuple(str(i) for i in range(1, N + 1)))
    
     
    for i, ans in enumerate(p.getSolutions()):  
      print(str(i) + ":", [x[1] for x in sorted(ans.items())]) 
    

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 )

Connecting to %s

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

%d bloggers like this: