Мост-фонарик на Прологе

Прежде чем заявить об этом, я логически понимаю решение этого вопроса, просто мне трудно его кодировать. Семья из 4 человек пытается перейти мост ночью. Чтобы пересечь мост, нужен фонарик, и только два человека могут пересечь мост одновременно, двигаясь со скоростью более медленного из двух. Отец пересекает мост за 1 минуту, Мать — за 2 минуты, Ребенок — за 5 минут, а бабушка — за 10. Я пытаюсь написать программу на Прологе, которая сможет справиться с такими вопросами, но для семей любого размера, движущихся с любой скоростью. Общее время пересечения должно быть меньше максимального указанного времени. Нам даны семьи в фактической форме family(Name,[X1/T1,X2/T2...etc]). Нас просят определить предикат MoveFamily(FamilyName, MAxTime, Moves, Time), где familyName и Max 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: я поместил семейный факт в блок кода, я манекен и должен был понять, что вы имели в виду, лол


person Community    schedule 05.04.2018    source источник
comment
Я попытался запустить снова, закомментировав time=‹ max, но вместо этого я просто получил False   -  person    schedule 06.04.2018
comment
Кроме того, family/2 — это Family(two, [fred/1, george/2]), я объясню это в редактировании.   -  person    schedule 06.04.2018
comment
Как еще я мог бы убедиться, что ходы принимают правильные значения? Буду ли я использовать предикат добавления и создать новый список? Я пытался использовать append раньше, поэтому я не мог рекурсивно передавать ходы, но не мог понять, как это реализовать.   -  person    schedule 06.04.2018
comment
Я запутался в том, что вы имеете в виду :/   -  person    schedule 06.04.2018
comment
Я пытался понять ваш код, но сдался (это ужасно). Пожалуйста, используйте отладчик исходного кода (например, gtrace в SWI) и измените ошибку одну за другой. По крайней мере, вы должны использовать select/3 для члена (X / T1, Север), члена (Y / T2, Север) и обе стороны ' =‹' должно быть числом.   -  person Taku Koyahata    schedule 06.04.2018
comment
По сути, вы пытаетесь использовать арифметические функции из отдельной библиотеки C++, встроенной в большинство версий Prolog, не указывая, что вы хотите вычислить. UNKNOWN + 1 ничего не даст. Вы должны использовать числовые атомы для вычисления чего-либо в Прологе, вы не можете иметь неконкретные переменные во всем, что использует оценка.   -  person G_V    schedule 06.04.2018


Ответы (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).

Дополнение: когда вы говорите [X|Moves] в параметре #3 в рекурсивном вызове, это означает, что вы отделяете возвращаемое значение от вызова, но что вы хотите сделать, так это добавить к нему X, что и происходит, когда вы помещаете это в вместо этого глава предложения.

person Tomas By    schedule 06.04.2018
comment
Большое спасибо! благодаря этому я смог добавить окончательные модификации и решить проблему! Теперь я понимаю, что вы имеете в виду, говоря, что я разбирал список, а не добавлял его! - person ; 06.04.2018
comment
Ваш код, безусловно, заставляет меня задуматься, почему я еще не пробовал, ха-ха! - person ; 06.04.2018