Brain-Teaser 231: Holidays abroad
From The Sunday Times, 26th September 1965 [link]
My old friends Alf, Bert, Charlie, Duggie and Ernie went with their wives for holidays abroad last year, to Andorra, Boulogne, Calais, Dunkirk and Ethiopia. I knew that the names of the five wives were Agnes, Beatrice, Clarissa, Daphne and Ethel, but the only information I had about who was married to whom was that for each pair the names of the husband, the wife and last year’s holiday destination all began with different letters.
In conversation with the ladies, Beatrice told me that she was not married to Alf, and that she had heard from Ernie that Charlie went to Dunkirk last year.
Daphne, however, firmly informed me that Charlie went to Ethiopia and that Beatrice went to Dunkirk. “Unlike some people I could mention”, she added darkly, “Alf always tells the truth”.
Clarissa said that when her husband was asked whether Ethel was married to Charlie, he replied: “No”. She went on to tell me that Duggie went to Boulogne.
Of each of these married couples one member always told the truth and the other never did.
Name each man’s wife and holiday resort.
This puzzle is included in the book Sunday Times Brain Teasers (1974).
[teaser231]

Jim Randell 10:03 am on 24 September 2024 Permalink |
I used the [[
SubstitutedExpression]] solver from the enigma.py library to solve this puzzle.I assigned 5 slots (1 – 5), each of which contains one wife, husband, destination and trait (for the wife).
The following run file fills out the slots. It runs in 77ms. (Internal runtime of the generated code is 631µs).
#! python3 -m enigma -rr SubstitutedExpression # let A = 1, B = 2, C = 3, D = 4, E = 5 # # slot : 1 2 3 4 5 # wife : A B C D E # husband : F G H I J {Alf, Bert, Charlie, Duggie, Ernie} # destination: K L M N P {Andorra, Boulogne, Calais, Dunkirk, Ethiopia} # wife trait : V W X Y Z {0 = false or 1 = true} --base=6 --distinct="FGHIJ,KLMNP,FK,GL,HM,IN,JP" --invalid="0,FGHIJKLMNP" --invalid="2|3|4|5,VWXYZ" --invalid="1,FK" --invalid="2,GL" --invalid="3,HM" --invalid="4,IN" --invalid="5,JP" --macro="@hs = (F, G, H, I, J)" # husbands --macro="@ds = (K, L, M, N, P)" # destinations --macro="@ts = (V, W, X, Y, Z)" # traits # find a slot with value v --code="slot = lambda vs, v: vs.index(v)" # check statements truth value "x" says "y" --code="check = lambda x, y: bool(x) == bool(y)" # Beatrice says (Beatrice is not married to Alf) "check(W, G != 1)" # Beatrice says (Ernie says Charlie went to Dunkirk) "check(W, check(@ts[slot(@hs, 5)] ^ 1, @ds[slot(@hs, 3)] == 4))" # Daphne says (Charlie went to Ethiopia) "check(Y, @ds[slot(@hs, 3)] == 5)" # Daphne says (Beatrice went to Dunkirk) "check(Y, L == 4)" # Daphne says (Alf tells the truth) "check(Y, @ts[slot(@hs, 1)] == 0)" # Clarissa says (her husband says (Ethel is not married to Charlie)) "check(X, check(X ^ 1, J != 3))" # Clarissa says (Duggie went to Boulogne) "check(X, @ds[slot(@hs, 4)] == 2)" --template="(F G H I J) (K L M N P) (V W X Y Z)" --solution=""And this following Python program formats the output using the appropriate labels:
from enigma import (SubstitutedExpression, printf) p = SubstitutedExpression.from_file("teaser231.run", # return (<husbands>, <destinations>, <traits>) ["--answer=(@hs, @ds, @ts)"], ) make_map = lambda vs: dict(enumerate(vs.split(), start=1)) husbands = make_map("Alf Bert Charlie Duggie Ernie") wives = make_map("Agnes Beatrix Clarissa Daphne Ethel") destinations = make_map("Andorra Boulogne Calais Dunkirk Ethiopia") traits = { 0: 'False', 1: 'True' } for ans in p.answers(verbose=0): # collect the slots [wife, husband, destination, trait] d = dict((k, [v]) for (k, v) in wives.items()) for (vs, labels) in zip(ans, [husbands, destinations, traits]): for (k, v) in enumerate(vs, start=1): d[k].append(labels[v]) # output the slots for k in sorted(d.keys(), key=(lambda k: d[k][1])): (W, H, D, T) = d[k] printf("{H} and {W} ({T}) -> {D}") printf()Solution: Alf and Clarissa → Dunkirk; Bert and Daphne → Ethiopia; Charlie and Ethel → Andorra; Duggie and Agnes → Boulogne; Ernie and Beatrix → Calais
We know:
We cannot determine the traits for Charlie and Ethel or for Duggie and Agnes.
LikeLike
Frits 11:02 am on 24 September 2024 Permalink |
@Jim,
I have a different naming convention for storing Python programs.
One idea might be to use something like (assuming the filename doesn’t contain periods):
import os runfile = os.path.basename(__file__).split(".")[0] + ".run" p = SubstitutedExpression.from_file(runfile, [ # return (<husbands>, <destinations>, <traits>) "--answer=(@hs, @ds, @ts)", ])LikeLike
Jim Randell 3:28 pm on 26 September 2024 Permalink |
I’ve added a [[
parsepath()]] function to enigma.py that can be used to extract the following components of a path:{path} = the full path name = "{dir}/{file}" {stem} = path without extension = "{dir}/{name}" {dir} = directory containing the file {file} = the filename = "{name}{ext}" {name} = the filename without extension {ext} = the extensionFor example:
{path} = "/users/jim/puzzles/enigma/enigma123.py" {stem} = "/users/jim/puzzles/enigma/enigma123" {dir} = "/users/jim/puzzles/enigma" {file} = "enigma123.py" {name} = "enigma123" {ext} = ".py"You can then call this to make a new path name from an existing one.
For example to make a path in the same directory:
path = parsepath("{dir}/enigma123.run", __file__)Or to just replace the extension:
path = parsepath("{dir}/{name}.run", __file__)path = parsepath("{stem}.run", __file__)As an added bonus [[
SubstitutedExpression.from_file()]] will automatically pass the arguments to [[parsepath()]] if a non-string is provided as a path, to save you the bother:p = SubstitutedExpression.from_file(["{stem}.run", __file__])LikeLike