Пятеро ребят. Кто где стоит?

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

В этой теме 1 ответ, 2 участника, последнее обновление  Васильев Владимир Сергеевич 1 год, 11 мес. назад.

  • Автор
    Сообщения
  • #1850

    questioner
    Участник

    Вот пятеро ребят.

    Одного из них зовут Колей — он стоит с краю.
    Если бы Нюра стояла рядом с Володей, то Петя очутился бы рядом со своим тезкой.

    Определите, кто где стоит.

  • #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.

Для ответа в этой теме необходимо авторизоваться.