Почему я не могу получить ответ на Корабельную Головоломку с Прологом?
Мне нужно решить проблему Корабельной Головоломки с использованием Пролога. Вот факты.
Есть 5 кораблей.
- Греческий корабль уходит в шесть и несет кофе.
- Корабль посередине имеет черный дымоход.
- Английский корабль отправляется в девять.
- Французский корабль с голубой дымовой трубой находится слева от корабля, который несет кофе.
- Справа от корабля с какао стоит корабль, идущий в Марсель.
- Бразильский корабль направляется в Манилу.
- Рядом с кораблем, несущим рис, стоит корабль с зеленой трубой.
- Корабль, идущий в Геную, уходит в пять.
- Испанский корабль уходит в семь и находится справа от корабля, идущего в Марсель.
- Корабль с красной трубой идет в Гамбург.
- Рядом с кораблем, выходящим в семь, стоит корабль с белой трубой.
- Корабль на границе несет кукурузу.
- Корабль с черной трубой уходит в восемь.
- Корабль с зерном стоит на якоре рядом с кораблем с рисом.
- Корабль в Гамбург отправляется в шесть.
Какой корабль идет в Порт-Саид? Какой корабль несет чай?
Я ищу ответы в Интернете, но не могу найти ни одного. Поэтому я ссылаюсь на "Загадку зебры" и, соответственно, составил код для этой проблемы. Так что это мой код Пролога проблема.
exists(A,(A,_,_,_,_)).
exists(A,(_,A,_,_,_)).
exists(A,(_,_,A,_,_)).
exists(A,(_,_,_,A,_)).
exists(A,(_,_,_,_,A)).
rightOf(A,B,(B,A,_,_,_)).
rightOf(A,B,(_,B,A,_,_)).
rightOf(A,B,(_,_,B,A,_)).
rightOf(A,B,(_,_,_,B,A)).
middleShip(A,(_,_,A,_,_)).
lastShip(A,(_,_,_,_,A)).
nextTo(A,B,(B,A,_,_,_)).
nextTo(A,B,(_,B,A,_,_)).
nextTo(A,B,(_,_,B,A,_)).
nextTo(A,B,(_,_,_,B,A)).
nextTo(A,B,(A,B,_,_,_)).
nextTo(A,B,(_,A,B,_,_)).
nextTo(A,B,(_,_,A,B,_)).
nextTo(A,B,(_,_,_,A,B)).
solution(PortSaidShip, TeaCarrier) :-
Shipes = (ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_)),
exists(ship('Greek',6,'Coffee',_,_),Shipes),
middleShip(ship(_,_,_,_,'Black',_),Shipes),
exists(ship('English',9,_,_,_),Shipes),
rightOf(ship(_,_,'Coffee',_,_),ship('French',_,_,'Blue',_),Shipes),
rightOf(ship(_,_,_,_,'Marseille'),ship(_,_,'Cocoa',_,_),Shipes),
exists(ship('Brazilian',_,_,_,'Manila'),Shipes),
nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_),Shipes),
exists(ship(_,5,_,_,'Genoa'),Shipes),
rightOf(ship('Spanish',7,_,_,_),ship(_,_,_,_,'Marseille'),Shipes),
exists(ship(_,_,_,'Red','Hamburg'),Shipes),
nextTo(ship(_,_,_,'White',_),ship(_,7,_,_,_),Shipes),
lastShip(ship(_,_,'Corn',_,_),Shipes),
exists(ship(_,8,_,'Black',_),Shipes),
nextTo(ship(_,_,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes),
exists(ship(_,6,_,_,'Hamburg'),Shipes),
exists(ship(PortSaidShip,_,_,_,'Port Said'),Shipes),
exists(ship(TeaCarrier,_,'Tea',_,_),Shipes).
Но когда я запускаю программу, она говорит "ложь".
Так как я могу решить это?
благодарю вас
2 ответа
Вы спрашивали:
Так как я могу решить это?
Ниже приведена общая методология, которая всегда работает для чистых монотонных программ Prolog, подобных вашей. Ваша настоящая проблема заключается в том, что конкретная цель должна быть успешной, но она проваливается. Таким образом, вы получили неожиданный сбой. Чтобы локализовать ответственную часть вашей программы, теперь мы будем систематически обобщать вашу программу. Шаг за шагом. Пока у нас нет крошечного фрагмента программы. Эту технику иногда называют программной нарезкой, а иногда программной модификацией.
Прежде всего, добавьте следующее в ваш код:
:- op(950, fy, *).
*_.
:- initialization(solution(_Port, _Carrier)).
Теперь мы удалим одну цель за другой, добавив *
перед ним, а затем перезапустите вашу программу. Так что будьте готовы, что вы перезапустите свою программу пару раз. Для загрузки программы введите на верхнем уровне:
?- [shipes].
Это работает практически везде, как в SICStus, GNU, SWI, YAP. Теперь вы получите предупреждение о "неудачной директиве" или подобном. Так что - будьте счастливы - ведь теперь вы можете легко воспроизвести проблему!
Начните добавлять *
на последней цели. Вы можете попробовать несколько одновременно. Чтобы перезагрузить после модификации, вы можете повторно ввести эту цель, или
в SICStus, лучшее состояние
ensure_loaded(shipes).
Это проверяет, был ли файл изменен, и перезапускает его, только если он был перезагруженв SWI введите
make.
Наконец, я получил следующий фрагмент программы:
middleShip (А, (_, _, А,_,_)). решение (PortSaidShip, TeaCarrier):- Shipes = (корабль (_, _, _, _, _), корабль (_, _, _, _, _), корабль (_, _, _, _, _), корабль (_, _, _, _,_),корабль(_,_,_,_,_)), *существует (корабль ("Греческий",6, "Кофе", _, _), Корабли), middleShip (корабль (_, _, _, _, 'черный', _), Shipes), *существует (корабль ("английский",9,_,_,_), корабль), *rightOf (ship (_, _, 'Coffee', _, _), ship ('French', _, _, 'Blue', _), Shipes), *rightOf (корабль (_, _, _, _, "Марсель"), корабль (_, _, "Какао", _, _), корабли), *существует (корабль ("бразилец", _, _, _, "Манила"), корабли), *nextTo (корабль (_, _, _, 'Зеленый', _), корабль (_, _, 'Рис', _, _), Корабли), *существует (корабль (_,5,_,_,'Генуя'), корабли), *rightOf (корабль ("Испанский",7,_,_,_), корабль (_, _, _, _, "Марсель"), Корабли), *существует (корабль (_, _, _, 'Красный', 'Гамбург'), Корабли), *nextTo (корабль (_, _, _, 'Белый', _), корабль (_,7,_,_,_), Корабли), *lastShip (ship (_, _, 'Corn', _, _), Shipes), *существует (корабль (_,8,_, "черный", _), корабли), *nextTo (корабль (_, _, 'Кукуруза', _, _), корабль (_, _, 'Рис', _, _), Корабли), *существует (корабль (_,6,_,_,'Гамбург'), корабли), *существует (корабль (PortSaidShip,_,_,_,'Port Said'), корабль), *существует (корабль (TeaCarrier, _, 'Tea', _, _), Shipes).
Таким образом, вам нужно понять четыре строки кода, чтобы понять вашу проблему!
Как уже указывали другие, проблема в том, что, как только вы используете ship/6
и в других ситуациях ship/5
,
Еще одно замечание: вместо (_,_,_,A,B)
лучше напиши [_,_,_,A,B]
что является общим обозначением списка.
Количество аргументов на срок ship(...)
во второй строке (после предиката решения) неверно. Это:
middleShip(ship(_,_,_,_,'Black',_),Shipes),
пока должно быть:
middleShip(ship(_,_,_,'Black',_),Shipes),
Я не проверял, работает ли это, но это приводит к сбою вашего решателя наверняка.