5 ms·
That's one of the most elegant Prolog formulations of this task I have seen so far. Great use of CLP(FD), especially considering that you have only started to l
by zmonx 10y ago
That's one of the most elegant Prolog formulations of this task I have seen so far. Great use of CLP(FD), especially considering that you have only started to learn this technology, as you mentioned in the other thread!
I have only two small suggestion: First, since you know that Vars = [GreenHouse, ...] (the Prolog program states this as a constraint), you can simply substitute Vars every time for this list. Therefore, you can start the whole program with: puzzle(Vars) :- ...
Second, exactly the same reasoning applies for the query you show. You can write it as: ?- puzzle(Vs), label(Vs).
Thank you very much for posting this beautiful solution, and also for carefully clarifying the additional assumptions!
- carapace 10y agoThat's very kind of you. Your comment made my day! :-) I came to Logic Programming via grokking mrocklin's port of Kanren to Python: https://github.com/logpy/logpy; https://github.com/logpy/logpy; and to solving logic puzzles via Laws of Form: http://www.markability.net/ http://www.markability.net/ (Last year the author of that site George Burnett-Stuart apparently cracked how to encode Predicate Calculus in the notation, which is an exciting development, IMHO!) So I'm not a complete novice. That said, at first I thought I should define relations like smokes and pet_of, but somehow between seeing the table on the Wikipedia entry for the Zebra Puzzle and the SEND MORE MONEY example (https://github.com/triska/clpfd/blob/master/sendmory.pl https://github.com/triska/clpfd/blob/master/sendmory.pl) it became obvious what to do. If you look at the SEND MORE MONEY solution you'll see the Zebra solution is laid out just like it. To me, it seems like the same sort of puzzle as Sudoku, but much simpler. It's unfortunate that the solution and the solving proper (querying for the result) obscure the art of the puzzle-maker, eh? Thanks for the suggestion! I've incorporated it into the version in Github "gist": https://gist.github.com/calroc/603ed919bc814ccee10c1b3df6142fec https://gist.github.com/calroc/603ed919bc814ccee10c1b3df6142... (I kept the more verbose query though, as I think the output is nicer. :-) YMMV)
- zmonx 10y agoVery, very nice formulation! You can apply the same trick to the query, i.e., you only need to write down the whole list once, if you formulate the query for example like this: ?- Vs = [GreenHouse, RedHouse, IvoryHouse, YellowHouse, BlueHouse, Englishman, Spaniard, Ukrainian, Norwegian, Japanese, Dog, Snails, Fox, Horse, Zebra, Coffee, Tea, Milk, OrangeJuice, Water, OldGold, Kools, Chesterfields, LuckyStrike, Parliaments], puzzle(Vs), label(Vs). In the above, I have introduced the logical variable Vs to refer to the same list in both goals. In the case of the Zebra puzzle, we only care about a few of these variables in particular, so we do not even introduce names for others. Instead, we can use anonymous variables, so that not even bindings are reported for those variables that do not matter in this case: ?- Vs = [_,_,_,_,_, Englishman, Spaniard, Ukrainian, Norwegian, Japanese, _,_,_,_,Zebra, _,_,_,_,Water|_], puzzle(Vs), label(Vs). This yields the following solution: Vs = [5, 3, 4, 1, 2, 3, 4, 2, 1|...], Englishman = 3, Spaniard = 4, Ukrainian = 2, Norwegian = Water, Water = 1, Japanese = Zebra, Zebra = 5 . By introducing additional variables like this, you can use maplist/2 to more compactly express the sequence of all_distinct/1 constraints. That's really a very nice way to formulate the puzzle in Prolog, and makes excellent use of features that are still quite recent innovations in Prolog implementations.
- carapace 10y agoCheers! That's awesome. I'm going to set aside some time to learn more Prolog. :-)