Prolog中的桥 - 手电筒拼图

时间:2018-04-05 20:56:43

标签: prolog river-crossing-puzzle

在我说明这一点之前,我从逻辑上理解了这个问题的解决方案,我只是很难编码。一家四口正试图在晚上过桥。人们需要一个手电筒穿过桥梁,只有两个人可以同时穿过桥梁,以两者中较慢的速度移动。父亲在1分钟内穿过桥,母亲在2分钟内穿过,5分钟穿过儿童,在10分钟穿过奶奶。我正在尝试编写一个可以处理这类问题的Prolog程序,但适用于任何速度的家庭。总交叉时间必须小于最大指定时间。我们以family(Name,[X1/T1,X2/T2...etc])的事实形式给予家庭。我们被要求定义谓词MoveFamily(FamilyName, MAxTime, Moves, Time),其中familyNameMax time是绑定变量,移动绑定到从一侧到另一侧跨越每个人的移动,时间绑定到它的总时间需要。以下是我到目前为止的情况:

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]).

当我在事实family(two, [fred/1, george/2])上运行时。 我明白了:

[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

有谁知道为什么这不起作用?

编辑:当他们一次穿过两个时,他们以较慢成员的速度移动

edit2:家庭“两个”是family(two, [fred/1, george/2])

edit3:查询moveFamily(two,20,Moves,Time)的所需输出应为

  Moves = [fred+george],
  Time = 2 

edit4:我把家庭事实放在代码块中,我是个假人,应该意识到这就是你的意思大声笑

1 个答案:

答案 0 :(得分:1)

一夜之间出现了一些奇怪的评论。

这似乎有效:

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).

添加:当您在递归调用中在参数#3中说[X|Moves]时,这意味着您要从调用中分离返回值,但您要做的是向其中添加X ,当你把它放在条款的头部时会发生这种情况。