简体   繁体   中英

Beginner Prolog Logic Puzzle

Bear with me, I know this is obviously super simple. I just can't seem to wrap my head around prolog. I have this logic problem:

At the recent festival, the 100 metres heats were closely monitored.

Each contestant had to run in two races so that the average place could be determined..

Only one runner finished in the same place in both races.

Alan was never last. Charles always beat Darren. Brian had at least one first place. Alan finished third in at least one of the races. Both Darren and Charles had a second place. What were the two results?

Answer: Race 1: Brian, Charles, Alan, Darren. Race 2: Charles, Darren, Alan, Brian.

This is what I have come up with so far, but I can't figure out the "at least" and other more complex conditions.

place(one).
place(two).
place(three).
place(four).

/* Place (constants): one, two, three, four.

Names (variables): Alan_1, Brian_1, Charles_1, Darren_1
Names (variables): Alan_2, Brian_2, Charles_2, Darren_2
*/

higher(one,two).
higher(one,three).
higher(one,four).
higher(two,three).
higher(two,four).
higher(three,four).

is_higher(X,Y):- higher(X,Y).
is_higher(X,Y):- higher(X,Z), is_higher(Z,Y).


is_different(S,T,U,V,W,X,Y,Z):- W\=X,W\=Y,W\=Z,X\=Y,X\=Z,Y\=Z,W\=S,W\=T,
            W\=U,W\=V,S\=T,T\=U,U\=V,S\=U,S\=V,T\=V,
            T\=W,T\=X,T\=Y,T\=Z,U\=W,U\=X,U\=Y,U\=Z,
            V\=X,V\=Y,V\=Z.


solution(Alan_1, Brian_1, Charles_1, Darren_1, Alan_2, Brian_2, Charles_2, 
Darren_2):-
place(Alan_1), place(Brian_1), place(Charles_1), place(Darren_1), 
place(Alan_2), place(Brian_2), place(Charles_2), place(Darren_2),
Alan_1\=four, Alan_2\=four, higher(Charles_1, Darren_1), higher(Charles_2, 
Darren_2),

is_different(Alan_1, Brian_1, Charles_1, Darren_1, Alan_2, Brian_2, 
Charles_2, Darren_2).

/*  Query */

% solution(Alan_1, Brian_1, Charles_1, Darren_1, Alan_2, Brian_2, Charles_2, 
Darren_2).

Any help or words of wisdom would be super appreciated.

I solved with SWI + CLPFD. For representing "at least", I used #\\/ .

:-use_module(library(clpfd)). solve(RaceResult):- RaceResult = [Alan1,Alan2,Chales1,Chales2,Brian1,Brian2,Darren1,Darren2], RaceResult ins 1..4, all_different([Alan1,Chales1,Brian1,Darren1]), all_different([Alan2,Chales2,Brian2,Darren2]), % Only one runner finished in the same place in both races. (Alan1 #= Alan2) #<==> AlanSame, (Chales1 #= Chales2) #<==> ChalesSame, (Brian1 #= Brian2) #<==> BrianSame, (Darren1 #= Darren2) #<==> DarrenSame, sum([AlanSame,ChalesSame,BrianSame,DarrenSame], #=, 1), % Alan was never last. Alan1 #\= 4, Alan2 #\= 4, % Alan finished third in at least one of the races. (Alan1 #= 3 ) #\/ (Alan2 #= 3), % Charles always beat Darren. Chales1 #< Darren1, Chales2 #< Darren2, % Brian had at least one first place. (Brian1 #= 1 ) #\/ (Brian2 #= 1), % Both Darren and Charles had a second place. (Darren1 #= 2) #\/ (Darren2 #= 2), (Chales1 #= 2) #\/ (Chales2 #= 2), labeling([ffc],RaceResult). ?- solve([Alan1,Alan2,Chales1,Chales2,Brian1,Brian2,Darren1,Darren2]). Alan1 = Alan2, Alan2 = 3, Chales1 = Brian2, Brian2 = 1, Chales2 = Darren1, Darren1 = 2, Brian1 = Darren2, Darren2 = 4 ; Alan1 = Alan2, Alan2 = 3, Chales1 = Darren2, Darren2 = 2, Chales2 = Brian1, Brian1 = 1, Brian2 = Darren1, Darren1 = 4.

Maybe there is another solution?

Race1: Chales Darren Alan Brian

Race2: Brian Chales Alan Darren

... Sorry just replacing race1 and race2.

I did it this way:

puzzle :-
    Races = [[_,_,_,_],[_,_,_,_]],
    Races = [R1,R2],
    (first(brian,R1);first(brian,R2);(first(brian,R1),first(brian,R2))),
    (third(alan,R1);third(alan,R2);(third(alan,R1),third(alan,R2))),
    ((second(darren,R1),second(charles,R2));(second(darren,R2),second(charles,R1))),
    member(brian,R1),
    member(charles,R1),
    member(brian,R2),
    member(charles,R2),
    member(alan,R1),
    member(darren,R1),
    member(alan,R2),
    member(darren,R2),
    before(charles,darren,R1),
    before(charles,darren,R2),
    never_last(alan,Races),
    only_one_same(Races),
    write(Races),nl.

zip_equal([],[],[]).
zip_equal([R|R1s],[R|R2s],[R|Rs]) :- !, zip_equal(R1s,R2s,Rs).
zip_equal([_|R1s],[_|R2s],Rs) :- !, zip_equal(R1s,R2s,Rs).

never_last(X,[[A1,B1,C1,_],[A2,B2,C2,_]]) :- member(X,[A1,B1,C1]), member(X,[A2,B2,C2]).

before(X,Y,[X|Rs]) :- !, member(Y,Rs).
before(X,Y,[_|Rs]) :- before(X,Y,Rs).

first(X,[X,_,_,_]).
second(X,[_,X,_,_]).
third(X,[_,_,X,_]).

only_one_same([R1s,R2s]) :- zip_equal(R1s,R2s,[_]).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM