Решение логической головоломки в Prolog

Я читаю "Изучите Пролог сейчас", и одно из упражнений, которое я не смог решить самостоятельно, заключается в следующем:

Есть улица с тремя соседними домами, которые имеют разный цвет. Они красные, синие и зеленые. Люди разных национальностей живут в разных домах, и у них у всех разное домашнее животное. Вот еще несколько фактов о них:

  • Англичанин живет в красном доме.
  • Ягуар - домашнее животное испанской семьи.
  • Японец живет справа от хранителя улитки.
  • Хранитель улитки живет слева от голубого дома.

Кто держит зебру?

Определите предикат zebra/1 который сообщает вам национальность владельца зебры.

Подсказка: подумайте о представлении домов и улиц. Запишите четыре ограничения в Прологе. member и sublist могут быть полезными предикатами.

Любые идеи, как кодировать его под Пролог? Благодарю.

Ответ 1

neigh(Left, Right, List) :- 
        List = [Left | [Right | _]];
        List = [_ | [Left | [Right]]].

zebraowner(Houses, ZebraOwner):-
        member([englishman, _, red], Houses),
        member([spanish, jaguar, _], Houses),
        neigh([_, snail, _], [japanese, _, _], Houses),
        neigh([_, snail, _], [_, _, blue], Houses),
        member([ZebraOwner, zebra, _], Houses),
        member([_, _, green], Houses).


zebra(X) :- zebraowner([_, _, _], X).

Ответ 2

Я новичок в Prolog, но я считаю, что определение рз не совсем правильно. Попробуйте:

   neigh(2,3,[1,2,3]).

Вы избегаете этого, не совсем работая, потому что есть два решения: один с японской зеброй во втором доме и один с зеброй в третьем доме, и ваш код только находит один (этого достаточно, чтобы ответить на вопрос:-). Этот код дает правильные ответы для рс и, следовательно, оба ответа на проблему:

neigh(Left, Right, List) :- 
        List = [Left, Right ,_];
        List = [_, Left, Right]].

но затем работает только на три дома. Более общая реализация:

neigh(Left, Right, List) :- 
        List = [Left , Right | _].
neigh(Left, Right, [_|Tail]) :- 
        neigh(Left, Right, Tail).