📜 ⬆️ ⬇️

Einstein's problem on the prolog

I wanted to continue the week of Einstein's task on Habré. After very and not very non-standard solutions, I would like to show how logical problems can (and should) be solved in logical programming languages ​​(sorry for the tautology).
Under the cut, you can see why the Prologue is so well suited for this task.

The task is probably already fed up with everything, so I will be brief.
Basics of the prologue are already very well written by comrade xonix , so my task is quite simple.

We will present the house as a list of 5 elements, one for each attribute: nationality of the owner, pet, brand of cigarettes, drink and color of the house, respectively. There are 5 houses altogether, therefore we will search for a solution among the lists (lists) of length 5.
To do this, we need standard predicates:
Also, we need to be able to say that 2 houses are next to each other. This can be implemented with such a simple predicate:
neighbors ( X , Y , List ) :- nextto ( X , Y , List ) .
neighbors ( X , Y , List ) :- nextto ( Y , X , List ) .
That is, either X is to the left of Y, or vice versa.
')
And here is the solution:
einstein :-
/* 0. 5 */
Houses = [ _ , _ , _ , _ , _ ] ,
/* 1. . */
nth1 ( 1 , Houses , [ norwegian , _ , _ , _ , _ ] ) ,
/* 2. . */
member ( [ englishman , _ , _ , _ , red ] , Houses ) ,
/* 3. , . */
nextto ( [ _ , _ , _ , _ , green ] , [ _ , _ , _ , _ , white ] , Houses ) ,
/* 4. . */
member ( [ dane , _ , _ , tea , _ ] , Houses ) ,
/* 5. , Marlboro, , . */
neighbors ( [ _ , _ , marlboro , _ , _ ] , [ _ , cat , _ , _ , _ ] , Houses ) ,
/* 6. , , Dunhill. */
member ( [ _ , _ , dunhill , _ , yellow ] , Houses ) ,
/* 7. Rothmans. */
member ( [ german , _ , rothmans , _ , _ ] , Houses ) ,
/* 8. , , . */
nth1 ( 3 , Houses , [ _ , _ , _ , milk , _ ] ) ,
/* 9. , Marlboro, . */
neighbors ( [ _ , _ , marlboro , _ , _ ] , [ _ , _ , _ , water , _ ] , Houses ) ,
/* 10. , Pall Mall, . */
member ( [ _ , bird , pallmall , _ , _ ] , Houses ) ,
/* 11. . */
member ( [ swede , dog , _ , _ , _ ] , Houses ) ,
/* 12. . */
neighbors ( [ norwegian , _ , _ , _ , _ ] , [ _ , _ , _ , _ , blue ] , Houses ) ,
/* 13. , , . */
member ( [ _ , horse , _ , _ , blue ] , Houses ) ,
/* 14. , Winfield, . */
member ( [ _ , _ , winfield , beer , _ ] , Houses ) ,
/* 15. . */
member ( [ _ , _ , _ , coffee , green ] , Houses ) ,

/* , : ? */
member ( [ Owner , fish , _ , _ , _ ] , Houses ) ,

/* */
print ( 'Owner of the fish: ' ) , print ( Owner ) , nl ,
print ( 'Full Solution: ' ) , print ( Houses ) , nl .


As you can see, the total number of lines in the program almost coincides with the number of conditions in the original task.
And the lines themselves are read almost as original conditions. Prologue is a very declarative language, we just need to describe what we want from it.
The interpreter does all the dirty work for us, and fast enough. On my machine, the script runs in 0.08sec, if you compile it will be a little faster.

To run the program you need to install SWI-Prolog yourself, copy the text to the file and add just such a hash-bang:
# ! / usr / bin / pl - q - t einstein - s
(well, or take the code from here )

These functions are included in the standard library. These are here for completeness of the solution, to show that even on a “clean” Prolog the solution is not much more.
member ( X , [ X | _]).
member ( X , [_ | Rest ]) :- member ( X , Rest ).

nth1 ( 1 , [ Elem | _], Elem ).
nth1 ( N , [_ | Rest ], Elem ) :- N > 1 , K is N - 1 , nth1 ( K , Rest , Elem ).

nextto ( L , R , [ L , R | _]).
nextto ( L , R , [_ | Rest ]) :- nextto ( L , R , Rest ).

Also, conditions 0, 1 and 8 can be simplified to one:
Houses = [[norwegian,_,_,_,_],_,[_,_,_,milk,_],_,_]
then the nth1 predicate is not needed, but I wanted to be as close as possible to the original.

Source: https://habr.com/ru/post/122142/


All Articles