Enigmatic Code

Programming Enigma Puzzles

Enigma 967: Prime cubes

From New Scientist #2122, 21st February 1998 [link]

 

George has 27 small blocks which have been identified with 27 different prime numbers — each block has its number on each face. He has assembled the blocks into a 3×3×3 cube, as shown. On each of the three visible faces, the nine numbers total 320 — but this is not true of the three hidden faces.

George remembers that when he bought the blocks they were assembled into a similar 3×3×3 cube, but on that occasion they showed the same total on each of the six faces, this being the smallest possible total if each block has a different prime number.

What was the total on each face when George bought the blocks?

[enigma967]

One response to “Enigma 967: Prime cubes

  1. Jim Randell 27 March 2020 at 8:22 am

    We can see see the values of 19 of the 27 blocks (including the value 2, which must be hidden in the centre of the original arrangement), so we only need to find the values of the 8 “hidden” blocks.

    There are 26 visible primes in the original arrangement, and we know that the 2 block must be the non visible value. So the smallest possible set of visible primes are those in the range [3, 103], and this includes all the primes were are shown in the diagram.

    If we sum the values of each of the faces the grand total is 6× the face sum, but also 3×(corner pieces) + 2×(edge pieces) + 1×(middle pieces).

    We can minimise this value by choosing the 8 smallest primes for the corner pieces, the next 12 for the edge pieces and the remaining 6 for the middles:

    corners = (3, 5, 7, 11, 13, 17, 19, 23), sum = 98
    edges = (29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73), sum = 612
    middles = (79, 83, 89, 97, 101, 103), sum = 552

    The grand total is then 3×98 + 2×612 + 552 = 2070.

    In which case the sum for each individual face is 2070/6 = 345.

    So we need to find if it is possible to assemble a cube with these constraints.

    I used a MiniZinc model to find out. Here it is wrapped using the minizinc.py wrapper:

    from minizinc import MiniZinc, var
    from enigma import Primes, first, div, join as _join, printf
    
    # odd primes
    primes = Primes().range(3)
    
    # allocate the first 26 odd primes into corners, edges, middles
    corners = first(primes, 8)
    edges = first(primes, 12)
    middles = first(primes, 6)
    
    # calculate the target face sum
    T = div(3 * sum(corners) + 2 * sum(edges) + sum(middles), 6)
    
    # allocate the numbers in the following layers:
    #
    #  [ a b c ]  [ j k l ]  [ r s t ]
    #  [ d e f ]  [ m 2 n ]  [ u v w ]
    #  [ g h i ]  [ o p q ]  [ x y z ]
    #
    cs = "acgirtxz"
    es = "bdfhjloqsuwy"
    ms = "ekmnpv"
    
    # change the default join separator
    join = lambda s, sep=", ": _join(s, sep=sep)
    
    # create the model
    m = MiniZinc(f"""
    
    include "globals.mzn";
    
    % corners
    set of int: C = {{ {join(corners)} }};
    
    {var("C", cs)};
    
    constraint all_different([ {join(cs)} ]);
    
    % edges
    set of int: E = {{ {join(edges)} }};
    
    {var("E", es)};
    
    constraint all_different([ {join(es)} ]);
    
    % middles
    set of int: M = {{ {join(middles)} }};
    
    {var("M", ms)};
    
    constraint all_different([ {join(ms)} ]);
    
    % face sums
    constraint (a + b + c) + (d + e + f) + (g + h + i) = {T}; % top
    constraint (r + s + t) + (u + v + w) + (x + y + z) = {T}; % bottom
    constraint (a + d + g) + (j + m + o) + (r + u + x) = {T}; % left
    constraint (c + f + i) + (l + n + q) + (t + w + z) = {T}; % right
    constraint (g + h + i) + (o + p + q) + (x + y + z) = {T}; % front
    constraint (a + b + c) + (j + k + l) + (r + s + t) = {T}; % back
    
    solve satisfy;
    
    """)
    
    # find a solution
    for s in m.solve(result=list(cs + es + ms), solver="minizinc"):
      # output a solution
      printf("--")
      printf("[ {s.a:3d} {s.b:3d} {s.c:3d} ]")
      printf("[ {s.d:3d} {s.e:3d} {s.f:3d} ]")
      printf("[ {s.g:3d} {s.h:3d} {s.i:3d} ]")
      printf("")
      printf("[ {s.j:3d} {s.k:3d} {s.l:3d} ]")
      printf("[ {s.m:3d} {  2:3d} {s.n:3d} ]")
      printf("[ {s.o:3d} {s.p:3d} {s.q:3d} ]")
      printf("")
      printf("[ {s.r:3d} {s.s:3d} {s.t:3d} ]")
      printf("[ {s.u:3d} {s.v:3d} {s.w:3d} ]")
      printf("[ {s.x:3d} {s.y:3d} {s.z:3d} ]")
      printf("--")
    

    Solution: When George bought the blocks the sum on each face was 345.

    Here is a diagram of a possible arrangement of the blocks to give a sum of 345 on each face:

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 )

Google photo

You are commenting using your Google 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: