Before I state this, I logically understand the solution to this question, am just having a hard time coding it. A family of 4 is trying to cross a bridge at night. One needs a flashlight to cross the bridge,and only two persons can cross the bridge at the same time, moving at the speed of the slower of the two. Father crosses the bridge in 1 minute, Mother in 2 minutes, Child in 5 minutes and Granny in 10. I am trying to write a Prolog program that can handle this kind of question, but for families of any size moving at any speed. The total crossing time must be less than a maximum specified time. We are given the families in a fact form family(Name,[X1/T1,X2/T2...etc])
. We are asked to define a predicate MoveFamily(FamilyName, MAxTime, Moves, Time)
where familyName
and Max time
are bound variables and moves binds to the moves taken to cross everyone from one side to another, time binds to the total time it takes. Here is what I have so far:
moveSouth(North,South,Moves,Time):-
member(X/T1,North), % x is a member of the north list
member(Y/T2,North), %y is a member of the north list
X \= Y,
Big is max(T1,T2),
select(X/T1, North, List2), %List2 is North with x removed
select(Y/T2, List2, NewNorth), %newNorth is north with x and y removed
New is Time+Big, %new time is old time plus maximum time
moveNorth(NewNorth, [X/T1,Y/T2|South], [X+Y|Moves], New).
moveNorth([],_,[],_,_). %this will be the last move
moveNorth(North,South,Moves,Time):-
member(X/T1,South),
select(X/T1, South, NewSouth),
New is Time + T1,
moveSouth([X/T1|North], NewSouth, [X|Moves], New).
getList(Name,List):-
family(Name,List).
moveFamily(Name, Max, Moves, Time):-
getList(Name,People),
Time =< Max,
moveSouth(People, [], Moves, Time).
family(two, [fred/1, george/2]).
When I run this on the fact family(two, [fred/1, george/2])
.
I get :
[debug] ?- moveFamily(two,20,Moves,Time).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _10170=<20
ERROR: [8] moveFamily(two,20,_10200,_10202)
ERROR: [7] <user>
Exception: (9) _9500=<20 ? creep
Exception: (8) moveFamily(two, 20, _9498, _9500) ? creep
Does anyone know why this will not work?
edit: When crossing two at a time they move at the speed of the slower member
edit2: family "Two" is family(two, [fred/1, george/2])
.
edit3: The desired output from the query moveFamily(two,20,Moves,Time)
should be
Moves = [fred+george],
Time = 2
edit4: I put the family fact in the code block, I'm a dummy and should have realized that's what you meant lol
Some strange comments appeared overnight.
This seems to work:
moveFamily(Name,Max,Moves,Time) :-
getList(Name,People),
moveSouth(People,[],Moves,Time),
Time =< Max.
getList(Name,List) :-
family(Name,List).
moveSouth(North,South,[X+Y|Moves],New) :-
member(X/T1,North), member(Y/T2,North), X \= Y,
Big is max(T1,T2),
select(X/T1,North,List2), select(Y/T2,List2,NewNorth),
moveNorth(NewNorth,[X/T1,Y/T2|South],Moves,Time), New is Time + Big.
moveSouth([],_,[],0).
moveNorth(North,South,[X|Moves],New) :-
member(X/T1,South), select(X/T1,South,NewSouth),
moveSouth([X/T1|North],NewSouth,Moves,Time), New is Time + T1.
moveNorth([],_,[],0).
Addition: when you say [X|Moves]
in parameter #3 in the recursive call, that means you are taking apart the return value from the call, but what you want to do is add X
to it, which is what happens when you put that in the head of the clause instead.