Brainteaser 1263: I do apologise
From The Sunday Times, 16th November 1986 [link]
The artist Pussicato has a new painting which is a 6×6 array of squares and each square is red or blue or green.
(A) Label the horizontal rows of the painting U, V, W, X, Y, Z from top to bottom and the vertical columns 1, 2, 3, 4, 5, 6 from left to right. Then U1, U3, V5 are red; W2, Z2 are blue; and U2, V4, X2, X3, Y3, Y4 are green. Also V1 and W1 are the same colour, as are Y1 and Z1, and also X6 and Y6. Each row and each column contains two red squares, two blue and two green.
(B) I do apologise. The information in (A) gives you a painting which is wrong in every square.
(C) Use the information in (B), together with the following facts. Any two squares which are next to each other, horizontally or vertically, have different colours. There are more green squares than blue squares.
(D) Look, I am so sorry. The information in (C) gives you a painting which is wrong in every square.
(E) To be serious, the information in (B) and (D) is correct.
Give (in order) the colours of the squares in the top row of Pussicato’s painting.
[teaser1263]

Jim Randell 8:52 am on 22 July 2025 Permalink |
Here is a solution using the [[
SubstitutedExpression()]] solver from the enigma.py library.The program first uses the information in (A) to produce a grid (= “layout 1”). It then uses layout 1, and the information in (B) and (C) to produce another layout (= “layout 2”). It then uses layout 1, layout 2 and the information in (B) and (D) to produce a final layout, that provides the answer to the puzzle.
Unfortunately, the program below fails with the standard CPython implementation (due to limitations in the CPython interpreter), but works fine with PyPy.
(The code on codepad includes a workaround for CPython [*]).
The following Python program runs in 132ms (under PyPy). (Internal runtime is 37.9ms).
Run: [ @codepad ]
from enigma import (enigma, SubstitutedExpression, first, sprintf as f, join, printf) # symbols for the 36 cells syms = first(enigma.str_upper + enigma.str_lower, 36) # map cells to symbols (rs, cs) = ("UVWXYZ", "123456") (v, vs) = (dict(), iter(syms)) for r in rs: for c in cs: v[r + c] = next(vs) # rows and cols rows = list(list(r + c for c in cs) for r in rs) cols = list(list(r + c for r in rs) for c in cs) # colours (red, green, blue) = (0, 1, 2) # find layout 1 def solve1(): # construct expressions exprs = list() # U1, U3, V5 are red exprs.extend(f("{{{x}}} = {red}", x=v[x]) for x in ["U1", "U3", "V5"]) # W2, Z2 are blue exprs.extend(f("{{{x}}} = {blue}", x=v[x]) for x in ["W2", "Z2"]) # U2, V4, X2, X3, Y3, Y4 are green exprs.extend(f("{{{x}}} = {green}", x=v[x]) for x in ["U2", "V4", "X2", "X3", "Y3", "Y4"]) # V1 = W1; Y1 = Z1; X6 = Y6 exprs.extend(f("{{{x}}} = {{{y}}}", x=v[x], y=v[y]) for (x, y) in [("V1", "W1"), ("Y1", "Z1"), ("X6", "Y6")]) # each row/column contains 2 red, 2 green, 2 blue check = lambda *vs: all(vs.count(x) == 2 for x in (red, green, blue)) for r in rows: exprs.append(join((f("{{{x}}}", x=v[x]) for x in r), sep=", ", enc=["check(", ")"])) for c in cols: exprs.append(join((f("{{{x}}}", x=v[x]) for x in c), sep=", ", enc=["check(", ")"])) # make an alphametic puzzle to solve the grid p = SubstitutedExpression(exprs, base=3, distinct=0, env=dict(check=check)) for s in p.solve(verbose=0): yield list(s[k] for k in syms) # find layout 2 def solve2(g1): # no colour from layout 1 is correct d2i={ red: [], green: [], blue: [] } for (k, v) in zip(syms, g1): d2i[v].append(k) # no adjacent squares are the same colour distinct=list() for (i, k) in enumerate(syms): (r, c) = divmod(i, 6) if c < 5: distinct.append(k + syms[i + 1]) if r < 5: distinct.append(k + syms[i + 6]) # there are more green than blue squares check = lambda *vs: vs.count(green) > vs.count(blue) expr = join(syms, sep="}, {", enc=["check({", "})"]) # make an alphametic puzzle to solve the grid p = SubstitutedExpression([expr], base=3, distinct=distinct, d2i=d2i, env=dict(check=check)) for s in p.solve(verbose=0): yield list(s[k] for k in syms) # solve for layout 1 for g1 in solve1(): printf("g1={g1}") # solve for layout 2 for g2 in solve2(g1): printf("g2={g2}") # generate the grid where each cell is different from g1 and g2 g3 = list(3 - (c1 + c2) for (c1, c2) in zip(g1, g2)) printf("g3={g3}") # output the grid d = { red: 'R', green: 'G', blue: 'B' } printf() for (i, v) in enumerate(g3): if i % 6 == 0: printf("[ \\") printf("{v} \\", v=d[v]) if i % 6 == 5: printf("]")Solution: The squares in the top row are: blue, blue, green, red, blue, red.
The requirements in (A) give a single layout (shown below on the left).
The requirements (B) and (C) also give a single layout (shown below in the centre).
And finally, the requirements (D) give a single layout (where each square is different colour to the corresponding positions the first two grids). (This is shown below on the right).
[*] When producing layout 2 there is only a single expression, involving all 36 variables, so the “denesting” code cannot split the expressions into blocks that use fewer expressions. To fix this we add in the following expression, which mentions half the symbols (and is always true), and this allows the denesting code to do its job:
LikeLike