prologzebra-puzzle

How to solve this puzzle with swiprolog?


I am trying to solve this puzzle using prolog and I am having difficulty writing down the rules and finishing the solution. This is the puzzle...

Last weekend was the men’s annual bowling tournament, an event of competition and fun for the local townspeople. This year, excitement ran high as five contestants bowled neck and neck for the championship. Each time a bowler won a game, he scored two points and the bowler with the highest number of points at the end of the tournament won. Determine the full name of each bowler, their high score (264 to 288), and how many points each won (28 to 36).

  1. Frank, whose last name wasn’t Thompson, had the highest score but he didn’t win the tournament.

  2. Mr. Smith’s high score was three pins higher than that of the bowler with 30 points.

  3. Steven’s last name wasn’t Stewart. The winner of the tournament, who had 36 points, had an odd number for a high score.

  4. Michael finished the tournament with six points less than Mr. Williams.

  5. The bowler with a high score of 273 had two points more than Mr. Smith but two points less than Craig.

  6. Mr. Thompson won fewer points than Walter but more than Steven Lewis.

And this is what I have so far...

first[craig].
first[frank].
first[michael].
first[steven].
first[walter].

last[thompson].
last[williams].
last[smith].
last[lewis].
last[stewart].

high[264].
high[288].
high[276].
high[276].
high[273].
high[285].

points[32].
points[34].
points[28].
points[30].
points[36].'''

'''Sol=[[first(craig),last(Thompson), first(FrankWilliams)]]'''

Please help me
[Logic Diagram picture][1]


  [1]: https://i.sstatic.net/Wi5lE.png

Solution

  • This is a fairly simple but slow solution:

    go(Persons):-
        length(Persons, 5),
        permutation_persons(Persons),
    
        % Clue 1
        member(p(frank, FrankSur, FrankScore, 288), Persons),
        FrankSur \= thompson,
        FrankScore \= 36,
    
        % Clue 2
        member(p(_, smith, SmithScore, SmithHigh), Persons),
        member(p(_, _, 30, Bowler30High), Persons),
        SmithScore \= 30,
        SmithHigh is Bowler30High + 3,
    
        % Clue 3a
        member(p(steven, StevenSur, _, _), Persons),
        StevenSur \= stewart,
    
        % Clue 3b
        member(p(_, _, 36, OddHigh), Persons),
        1 is OddHigh mod 2,
    
        % Clue 4
        member(p(michael, _, MichaelScore, _), Persons),
        member(p(_, williams, WilliamsScore, _), Persons),
        MichaelScore is WilliamsScore - 6,
    
        % Clue 5
        member(p(_, _, Bowler273Score, 273), Persons),
        Bowler273Score is SmithScore + 2,
        member(p(craig, _, CraigScore, _), Persons),
        Bowler273Score is CraigScore - 2,
    
        % Clue 6b
        member(p(steven, lewis, StevenScore, _), Persons),
    
        % Clue 6a
        member(p(_, thompson, ThompsonScore, _), Persons),
        ThompsonScore > StevenScore,
        member(p(walter, _, WalterScore, _), Persons),
        ThompsonScore < WalterScore.
    
    
    permutation_persons(Persons) :-
        FirstNames = [craig, frank, michael, steven, walter],
        Surnames = [thompson, williams, smith, lewis, stewart],
        Points = [28, 30, 32, 34, 36],
        HighScores = [264, 288, 276, 273, 285],
        permute(FirstNames, FP),
        permute(Surnames, SP),
        permute(HighScores, HP),
        assign_persons(Persons, FP, SP, Points, HP).
    
    
    assign_persons([], _, _, _, _).
    assign_persons([H|T], [HF|TF], [HS|TS], [HP|TP], [HH|TH]) :-
        H = p(HF, HS, HP, HH),
        assign_persons(T, TF, TS, TP, TH).
    
    
    % Fast permutation (rearrangement)
    permute([], []).
    permute([X|Rest], L) :-
        permute(Rest, L1),
        select(X, L, L1).
    

    Result in swi-prolog:

    ?- time(findall(P, go(P), Ps)).
    % 27,505,015 inferences, 3.287 CPU in 3.247 seconds (101% CPU, 8367859 Lips)
    Ps = [[p(michael,smith,28,276),p(steven,lewis,30,273),p(craig,thompson,32,264),p(frank,williams,34,288),p(walter,stewart,36,285)]].