New Scientist Enigma 586 – The Paint Runs Down
by Keith Austin
From New Scientist #1739, 20th October 1990
In the diagram the lines indicate pipes for the paint to flow down. At each of A, B and C either red or blue paint is poured into the top of the pipe. The circles are paint processors. For the circles marked with a star, if all the paint flowing down into the circle is red then blue flows out of the bottom of the circle, otherwise red flows out. For the other circles, if all the paint flowing into the circle is blue, then blue flows out of the bottom otherwise red flows out. For example, if red is poured into the top of A and C and blue into B, then blue flows out of the pipe 5 and red out of pipes 1, 2, 3, 4, 6 and 7 at the bottom.
Some of the seven numbered bottom pipes are to be directed into a storage drum in such a way that the following condition holds whatever the choice of three paints put in A, B, C:
If red is poured into A then at least one pipe into the drum brings blue;
if blue is poured into A then all the pipes into the drum bring red.
Which of the numbered pipes should go into the drum?
-
Brian Gladman permalink123456789101112131415161718192021222324252627282930313233343536373839404142from itertools import product# with red and blue as ...red, blue = 0, 1# ... empty circles evaluate as bitwise and: (x & y & ...)# ... star circles evaluate as bitwise nor: ~(x | y | ...) & 1# evaluate the output pipes given the three inputsdef flow(A, B, C):D = A & BE = A & CF = B & CG = ~(D | E | F) & 1H = B & EI = A & GJ = B & GK = C & GL = ~(H | I | J | K) & 1M = D & LN = G & LO = E & LP = F & Lreturn I, M, N, O, J, P, K# list the four 7-tuple pipe outputs when A is red# and blue respectivelyrbps = [[], []]for in3 in product((red, blue), repeat=3):rbps[in3[0]].append(flow(*in3))# list the seven 4-tuple pipe outputs when# A is red and blue respectivelyrp = tuple(zip(*rbps[0]))bp = tuple(zip(*rbps[1]))# collect any pipes where red into A gives at least one# blue output and blue into A always gives a red outputpipes = tuple(i for i, (r, b) in enumerate(zip(rp, bp), 1)if any(r) and not any(b))print(f"pipes: {pipes}")