Brain-Teaser 719: Wotta-Woppa!
From The Sunday Times, 27th April 1975 [link]
On the Island of Imperfection there are three tribes; the Pukkas who always tell the truth, the Wotta-Woppas who never tell the truth, and the Shilli-Shallas who make statements which are alternately true and false, or false and true. This story is about three inhabitants; Ugly, Stupid and Toothless, whose names give some indication of the nature of their imperfections.
The island currency is a Hope. The weekly wage of a Pukka is between 10 and 19 Hopes, of a Shilli-Shalla between 20 and 29, and of a Wotta-Woppa between 30 and 39 (in each case a whole number of Hopes). They make three statements each, anonymously:
A says: (1) B is a Wotta-Woppa. (2) My wages are 25% less than 20% more than one of the others. (3) I get 10 hopes more than B.
B says: (1) The wages of one of us is different from the sum of those of the other two. (2) We all belong to the same tribe. (3) More of C‘s statements are true than mine.
C says: (1) Ugly earns more than Toothless. (2) The wages of one of us are 15% less than the wages of another. (3) Stupid is a Shilli-Shalla.
Find C‘s name, tribe and wages.
This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). The puzzle text above is taken from the book.
[teaser718]
Jim Randell 11:17 am on 21 June 2022 Permalink |
This is similar to Puzzle 15 (and Puzzle 66).
Some obvious initial analysis:
Statement B1 (“The wages of one of us is different from the sum of those of the other two”) must always be true, as it it not possible for each of the three to have wages that are equal to the sum of the other two. (Who would have the largest value?)
So B cannot be a Wotta-Woppa. (And so A1 is false).
Which means B3 must be also be true. So C must make more true statements than B, so B cannot be a Pukka. Hence B is a Shilli-Shalla, and C is a Pukka. (And B2 is false).
And so C3 must be true, and “Stupid” is a Shilli-Shalla.
And as A1 is false, then A cannot be a Pukka, and A3 must also be false.
I incorporated these findings into a generic solution to get a program that runs in 71ms.
Run: [ @replit ]
from enigma import (subsets, tuples, irange, product, div, intersect, printf) # Pukka - always tell the truth def P(ss): return all(ss) # Wotta-Woppa - never tells the truth def W(ss): return not any(ss) # Shilli-Shalla - alternates between true and false def S(ss): return all(a != b for (a, b) in tuples(ss, 2)) # wages, by tribe wage = { P: irange(10, 19), S: irange(20, 29), W: irange(30, 39) } # assign tribes to the participants for ts in ((W, S, P), (S, S, P)): (A, B, C) = ts # B's statements Bs = [True, False, True] assert B(Bs) # assign names to the participants for ns in subsets("STU", size=3, select="P"): (nA, nB, nC) = ns if nC == 'S': continue # not possible (iS, iT, iU) = (ns.index(x) for x in "STU") # assign wages to the participants for ws in product(wage[A], wage[B], wage[C]): (wA, wB, wC) = ws # check A's statements As = [False, div(10 * wA, 9) in {wB, wC}, wA == wB + 10] if not A(As): continue # check C's statements Cs = [ ws[iU] > ws[iT], ts[iS] is S, bool(intersect([{ div(85 * x, 100) for x in ws }, ws])), ] if not C(Cs): continue # check B's 3rd statement assert Cs.count(True) > Bs.count(True) # output solution f = lambda x: x.__name__ printf("A={A} {nA} {wA}; B={B} {nB} {wB}; C={C} {nC} {wC} [{As}; {Bs}; {Cs}]", A=f(A), B=f(B), C=f(C))Solution: C is Toothless, he is a Pukka, his wage is 17 Hopes.
A is Ugly, he is a Wotta-Woppa, his wage is 31 – 39 Hopes.
B is Stupid, he is a Shilli-Shalla, his wage is 20 Hopes.
C‘s wage (17) is 15% less than that of B (20).
LikeLike
Frits 3:04 pm on 21 June 2022 Permalink |
@Jim, You swapped the ranges of Wotta-Woppa and Shilli-Shalla.
LikeLike
Jim Randell 3:10 pm on 21 June 2022 Permalink |
Thanks. Fixed now.
LikeLike
Jim Randell 12:25 pm on 27 June 2022 Permalink |
Inspired by Frits’ solution (below) I wrote a solution that uses the [[
SubstitutedExpression]] solver from the enigma.py library, and is just a restatement of the puzzle text with no analysis.The values assigned for the tribes make it easy to express the wages alphametically.
This Python program runs in 73ms.
Run: [ @replit ]
from enigma import (SubstitutedExpression, irange, tuples, div, printf) # statements tribe name wage # A: a d g p x ps # B: b e h q y qt # C: c f i r z ru # # statements: 0 (false), 1 (true) # tribe: 1 (P), 2 (SS), 3 (WW) # name: 1 (S), 2 (T), 3 (U) # wage (units): 0 - 9 # check statements for a tribe def tribe(t, ss): if t == 1: return all(ss) if t == 2: return all(a != b for (a, b) in tuples(ss, 2)) if t == 3: return not any(ss) # B1: one of the wages is different from the sum of the other two def B1(*ws): t = sum(ws) return any(w != t - w for w in ws) # C1: Ugly (3) earns more than Toothless (2) def C1(ns, ws): d = dict(zip(ns, ws)) return d[3] > d[2] # C2: the wages of one of us is 85% the wages of another def C2(*ws): for w in ws: x = div(85 * w, 100) if x in ws: return True return False # expressions to evaluate exprs = [ # tribes and statements "tribe({p}, [{a}, {d}, {g}])", "tribe({q}, [{b}, {e}, {h}])", "tribe({r}, [{c}, {f}, {i}])", # A1: "B is a Wotta-Woppa (3)" = {a} "int({q} == 3) = {a}", # A2: "My wages are [0.9] one of the others" = {d} "int(div({ps} * 10, 9) in { {qt}, {ru} }) = {d}", # A3: "I get 10 Hopes more than B" = {g} "int({ps} == {qt} + 10) = {g}", # B1: "The wages of one of us is different from the sum of the wages # of the other two" = {b} "int(B1({ps}, {qt}, {ru})) = {b}", # B2: "We all belong the same tribe" = {e} "int({p} == {q} == {r}) = {e}", # B3: "More of C's statements are true than mine" = {h} "int({c} + {f} + {i} > {b} + {e} + {h}) = {h}", # C1: "Ugly earns more than Toothless" = {c} "int(C1([{x}, {y}, {z}], [{ps}, {qt}, {ru}])) = {c}", # C2: "The wages of one of us are 0.85 the wages of another" = {f} "int(C2({ps}, {qt}, {ru})) == {f}", # C3: "Stupid (1) is a Shilli-Shalla (2)" = {i} "int({ {x}: {p}, {y}: {q}, {z}: {r} }[1] == 2) = {i}", ] # invalid digit / symbol assignments d2i = dict() for d in irange(0, 9): vs = set() if d > 1: vs.update('abcdefghi') if d < 1 or d > 3: vs.update('pqrxyz') d2i[d] = vs # create the puzzle p = SubstitutedExpression( exprs, distinct="xyz", d2i=d2i, env=dict(tribe=tribe, B1=B1, C1=C1, C2=C2), verbose=0, ) # solve the puzzle and output solutions Ts = { 1: "Pukka", 2: "Shilli-Shalla", 3: "Wotta-Woppa" } Ns = { 1: "Stupid", 2: "Toothless", 3: "Ugly" } for s in p.solve(): (a, b, c, d, e, f, g, h, i, p, q, r, s, t, u, x, y, z) = (s[k] for k in 'abcdefghipqrstuxyz') printf("A: {N:9s} {T:13s} {p}{s} [{a} {d} {g}]", N=Ns[x], T=Ts[p]) printf("B: {N:9s} {T:13s} {q}{t} [{b} {e} {h}]", N=Ns[y], T=Ts[q]) printf("C: {N:9s} {T:13s} {r}{u} [{c} {f} {i}]", N=Ns[z], T=Ts[r]) printf()LikeLike
Frits 1:31 pm on 29 June 2022 Permalink |
Nice idea to let tribes go from 1 to 3 so you can use the tribe value as a tens unit of the wage.
LikeLike
Frits 3:30 pm on 21 June 2022 Permalink |
For all tribes the veracity of the first and third statement must be the same.
from enigma import SubstitutedExpression # tribes 0 = Wotta-Woppa, 1 = Shilli-Shilla, 2 = Pukka # names: 0 = Stupid, 1 = Toothless, 2 = Ugly # stmnts tribe wages name # 0/1 0/1/2 0/1/2 # A: D E D P UV K # B: F G F Q WX L # C: H I H R YZ M # the alphametic puzzle p = SubstitutedExpression( [ # if Wotta-Woppa all statements are false "P != 0 or D == E == 0", "Q != 0 or F == G == 0", "R != 0 or H == I == 0", # if Shilli-Shalla all statements are alternating true/false "P != 1 or D + E == 1", "Q != 1 or F + G == 1", "R != 1 or H + I == 1", # if Pukka all statements are true "P != 2 or D == E == 1", "Q != 2 or F == G == 1", "R != 2 or H == I == 1", # ranges: Pukka 10-19, Shilli-Shalla 20-29 and Wotta-Woppa 30-39 "(P != 0 or U == 3) and (P != 1 or U == 2) and (P != 2 or U == 1)", "(Q != 0 or W == 3) and (Q != 1 or W == 2) and (Q != 2 or W == 1)", "(R != 0 or Y == 3) and (R != 1 or Y == 2) and (R != 2 or Y == 1)", # A1: B is a Wotta-Woppa "(F == G == 0) == D", # A2: My wages are 25% less than 20% more than one of the others "(UV in {0.9 * WX, 0.9 * YZ}) == E", # A3: I get 10 hopes more than B "(UV == WX + 10) == D", # B1: The wages of one of us is different from the sum of those # of the other two "(UV != WX + YZ or UV + WX != YZ or UV + YZ != WX) == F", # B2: We all belong to the same tribe "(P == Q == R) == G", # B3: More of C's statements are true than mine "(2* H + I > 2 * F + G) == F", # C1: Ugly earns more than Toothless "((UV if K == 2 else WX if L == 2 else YZ) > \ (UV if K == 1 else WX if L == 1 else YZ)) == H", # C2: The wages of one of us are 15% less than the wages of another "((20 * UV in {17 * YZ, 17 * WX}) or \ (20 * WX in {17 * YZ, 17 * UV}) or \ (20 * YZ in {17 * UV, 17 * WX})) == I", # C3: Stupid is a Shilli-Shalla. "((K == 0 and P == 1) or \ (L == 0 and Q == 1) or \ (M == 0 and R == 1)) == H", ], answer="(D, E, F, G, H, I), (P, Q, R), (UV, WX, YZ), (K, L, M)", d2i=dict([(0, "UWY")] + [(2, "DEFGHI")] + [(3, "DEFGHIKLMPQR")] + [(k, "DEFGHIKLMPQRUWY") for k in range(4, 10)]), distinct="KLM", verbose=0, ) # print answers for (_, ans) in p.solve(): print(f"{ans}")LikeLike