B. Pym
2024-08-06 03:19:32 UTC
Rosetta: Zebra puzzle
;; Iterate over all permutations of a list, and
;; call a function on each.
(define (permute permute.seq permute.func (permute.built '()))
(if (null? permute.seq)
(permute.func permute.built)
(let (seq (copy permute.seq))
(dotimes (i (length seq))
(unless (zero? i) (rotate seq -1))
(permute
(rest seq)
permute.func
(cons (first seq) permute.built))))))
(define (same-house obj0 lst0 obj1 lst1)
(= (find obj0 lst0) (find obj1 lst1)))
(define (distance obj0 lst0 obj1 lst1)
(- (find obj1 lst1) (find obj0 lst0)))
(define (next-to) (= 1 (abs (apply distance (args)))))
(permute '(danish english german norwegian swedish)
(fn (men)
(if (= 'norwegian (men 0))
(permute '(beer coffee milk tea water)
(fn (drinks)
(if (and (= 'milk (drinks 2))
(same-house 'danish men 'tea drinks))
(permute '(blue green red white yellow)
(fn (colors)
(if (and (= 1 (distance 'green colors 'white colors))
(same-house 'english men 'red colors)
(same-house 'coffee drinks 'green colors)
(next-to 'norwegian men 'blue colors))
(permute '(blend blue-master dunhill pall-mall prince)
(fn (smokes)
(if (and (same-house 'german men 'prince smokes)
(same-house 'dunhill smokes 'yellow colors)
(same-house 'blue-master smokes 'beer drinks)
(next-to 'water drinks 'blend smokes))
(permute '(birds cats dog horse zebra)
(fn (pets)
(if (and (same-house 'swedish men 'dog pets)
(same-house 'pall-mall smokes 'birds pets)
(next-to 'cats pets 'blend smokes)
(next-to 'horse pets 'dunhill smokes))
(println (transpose (list men drinks colors smokes pets)))
)))))))))))))))
((norwegian water yellow dunhill cats)
(danish tea blue blend horse)
(english milk red pall-mall birds)
(german coffee green prince zebra)
(swedish beer white blue-master dog))
There are five houses.
The English man lives in the red house.
The Swede has a dog.
The Dane drinks tea.
The green house is immediately to the left of the white house.
They drink coffee in the green house.
The man who smokes Pall Mall has birds.
In the yellow house they smoke Dunhill.
In the middle house they drink milk.
The Norwegian lives in the first house.
The man who smokes Blend lives in the house next to the house with cats.
In a house next to the house where they have a horse, they smoke Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Norwegian lives next to the blue house.
They drink water in a house next to the house where they smoke Blend.
The question is, who owns the zebra?
Additionally, list the solution for all the houses.
Optionally, show the solution is unique.
newLISPThe English man lives in the red house.
The Swede has a dog.
The Dane drinks tea.
The green house is immediately to the left of the white house.
They drink coffee in the green house.
The man who smokes Pall Mall has birds.
In the yellow house they smoke Dunhill.
In the middle house they drink milk.
The Norwegian lives in the first house.
The man who smokes Blend lives in the house next to the house with cats.
In a house next to the house where they have a horse, they smoke Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Norwegian lives next to the blue house.
They drink water in a house next to the house where they smoke Blend.
The question is, who owns the zebra?
Additionally, list the solution for all the houses.
Optionally, show the solution is unique.
;; Iterate over all permutations of a list, and
;; call a function on each.
(define (permute permute.seq permute.func (permute.built '()))
(if (null? permute.seq)
(permute.func permute.built)
(let (seq (copy permute.seq))
(dotimes (i (length seq))
(unless (zero? i) (rotate seq -1))
(permute
(rest seq)
permute.func
(cons (first seq) permute.built))))))
(define (same-house obj0 lst0 obj1 lst1)
(= (find obj0 lst0) (find obj1 lst1)))
(define (distance obj0 lst0 obj1 lst1)
(- (find obj1 lst1) (find obj0 lst0)))
(define (next-to) (= 1 (abs (apply distance (args)))))
(permute '(danish english german norwegian swedish)
(fn (men)
(if (= 'norwegian (men 0))
(permute '(beer coffee milk tea water)
(fn (drinks)
(if (and (= 'milk (drinks 2))
(same-house 'danish men 'tea drinks))
(permute '(blue green red white yellow)
(fn (colors)
(if (and (= 1 (distance 'green colors 'white colors))
(same-house 'english men 'red colors)
(same-house 'coffee drinks 'green colors)
(next-to 'norwegian men 'blue colors))
(permute '(blend blue-master dunhill pall-mall prince)
(fn (smokes)
(if (and (same-house 'german men 'prince smokes)
(same-house 'dunhill smokes 'yellow colors)
(same-house 'blue-master smokes 'beer drinks)
(next-to 'water drinks 'blend smokes))
(permute '(birds cats dog horse zebra)
(fn (pets)
(if (and (same-house 'swedish men 'dog pets)
(same-house 'pall-mall smokes 'birds pets)
(next-to 'cats pets 'blend smokes)
(next-to 'horse pets 'dunhill smokes))
(println (transpose (list men drinks colors smokes pets)))
)))))))))))))))
((norwegian water yellow dunhill cats)
(danish tea blue blend horse)
(english milk red pall-mall birds)
(german coffee green prince zebra)
(swedish beer white blue-master dog))