Ответ в теме: Пятеро ребят. Кто где стоит?

      Комментарии к записи Ответ в теме: Пятеро ребят. Кто где стоит? отключены
#1851

Это задача на установление соответствия, решается также, как и другие задачи такого типа.

Информацию обо всех имена внесем в базу пролога:

имя(коля).
имя(нюра).
имя(петя).
имя(володя).

Теперь мы можем запустить генерацию всех вариантов имен и схематично описать решение задачи:

решение(Ответ):-
  Ответ = [Ч1, Ч2, Ч3, Ч4, Ч5],
  имя(Ч1), имя(Ч2), имя(Ч3), имя(Ч4), имя(Ч5), 
  проверка_имен(Ответ),
  коля_с_краю(Ответ),
  нюра_петя(Ответ). 

Тут сначала формируется список из пяти анонимных переменных, затем, посредством обращения к именам базы, переменные инициализируются. Механизм перебора с возвратами обеспечит генерацию всех возможных вариантов списков имен. Всю остальную проверку я разделил на 3 части:

  1. проверка_имен(Имена):-
        ord_del_element(Имена, петя, Имена_без_пети),
        unique(Имена_без_пети), !.

    Проверяет тот факт, что в исходном списке у Пети есть тезка, остальные имена не повторяются. Для этого из исходного списка удаляется имя Пети, а для остальной части вызывается правило unique, завершающееся удачей если ни один элемент не входит в список дважды. Для удаления имени используется стандартный предикат ord_del_element.

  2. коля_с_краю(Имена):-
        ([коля, _] = Имена; last(Имена, коля)), !.

    Означает, что Коля либо находится в начале списка, либо в конце. Для получения последнего элемента списка используется стандартная функция last.

  3. нюра_петя(Имена):-
        нюра_с_володей(Имена), !, петя_с_тезкой(Имена);
        !.

    Если Нюра с Володей, то Петя должен быть с тезкой, об других случаях информации нет, поэтому правило завершается удачей.

    • нюра_с_володей(Имена):-
          Нюра_володя = [нюра, володя],
          (Имена = Нюра_володя; reverse(Нюра_володя, Имена)), !.
           
      проверка_нюра_володя(Имена):-
          нюра_с_володей(Нюра_с_володей),
          ord_subset(Нюра_с_володей, Имена), !.

      При проверке того, что Нюра стоит с Володей — формируем 2 списка ([нюра, володя] и перевернутый) и передаем их стандартному предикату ord_subset для поиска. Стандартный subset работает не со списками, а с множествами (порядок следования элементов в них не важен) — поэтому он не подходит.

    • петя_с_тезкой(Имена):-
          Пети = [петя, петя],
          ord_subset(Пети, Имена), !.

      Аналогично предыдущей проверке, формируется список из двух имен и обрабатывается стандартным ord_subset.