Enigmatic Code

Programming Enigma Puzzles

Enigma 236: Men on a bummel

From New Scientist #1382, 3rd November 1983 [link]

On the last night of their German holiday, Amble, Bumble, Crumble and Dimwit ate at Das Goldene Rätsel, famous for its Anglo-German cuisine. Each had one dish from each course. Here is the menu.

Dimwit is, alas, now recovering from food poisoning and too ill to recall what he ate or spent. Nor can the others recall, but the three spent the same amount each and know what each of the three ate. Making the reasonable assumption that Dimwit was done for by something he alone chose, they have deduced what the offending dish must have been.

Can you do the same?

Coincidentally, I am currently reading Jerome K. Jerome‘s “Three Men on the Bummel“.

Note: I now have a phone line installed at my new house, but I’m waiting for ADSL to be activated on it, so I only have sporadic access to the internet at the moment. The current estimate is that I should have an internet connection next week.

[enigma236]

One response to “Enigma 236: Men on a bummel”

1. Jim Randell 9 November 2014 at 7:29 am

This Python 3 program runs in 50ms.

```# A, B and C must have consumed 8 of the dishes between them (in order
# to be able to determine the remaining dish that poisoned D), so
# exactly one of the dishes is shared between 2 of them

from itertools import permutations, product
from enigma import irange, uniq, flatten, printf

# the dishes (the dishes in each course can be distinguished by price)
courses = ([2, 4, 5], [4, 8, 10], [3, 5, 7])

# total price of all dishes on the menu
total = sum(flatten(courses))

# return a copy of <s> with the first <x> removed
def remove(s, x):
# if list.remove() returned the list this would just be: [[ return list(s).remove(x) ]]
s = list(s)
s.remove(x)
return s

# choose a dish from each course, so the total sums to s
# return (<dishes chosen>, <remaining dishes in each course>)
def dishes(courses, s):
# is there only one course?
if len(courses) == 1:
# is there a dish of the required price?
if s in courses[0]:
yield ([s], [remove(courses[0], s)])
else:
# consider possible dishes from the first course
for d in uniq(courses[0]):
if not(d < s): continue
# choose the remaining courses
for (ds, cs) in dishes(courses[1:], s - d):
yield ([d] + ds, [remove(courses[0], d)] + cs)

# choose dishes from courses for each diner
# until all dishes are used up
def choose(courses, s, ds=[]):
if len(courses[0]) == 0:
yield ds
else:
# find a choice for the next diner, and remaining dishes
for (d, cs) in dishes(courses, s):
# require the dishes to be ordered by diner (to remove duplicate solutions)
if len(ds) > 0 and d < ds[-1]: continue
yield from choose(cs, s, ds + [d])

# consider each course
for (i, c) in enumerate(courses):
# choose a poisoned dish and a repeated dish
for (p, r) in permutations(c, 2):
# how much did A, B, C spend each?
# (they had all the dishes, except the poisoned one, and the repeated one twice)
(s, x) = divmod(total - p + r, 3)
if x > 0: continue
# construct the courses consumed by A, B, C
abc = list(courses)
# in course i remove the poisoned dish and add the repeated dish
abc[i] = list(courses[i])
abc[i].remove(p)
abc[i].append(r)
# find choices for A, B, C
for ds in choose(abc, s):
printf("poisoned course = {i}, poisoned dish cost = {p}, A/B/C = {ds}", i=i + 1)
```

Solution: Dimwit was the only one who had the Aalspastete.

We can deduce that the other three diners each spent DM 15 and had the following combination of courses:

Lumpensuppe; Kröte im Loch; Walise Seltenstück.