Prolog — задача 154 Разговоры гномов

  • В этой теме 0 ответов, 1 участник, последнее обновление 2 недели назад сделано Васильев Владимир Сергеевич.
Просмотр 0 веток ответов
  • Автор
    Сообщения
    • #6736
      @admin

      Задача:

      Каждый из четырех гномов – Балин, Двалин, Кили и Фили –
      либо всегда говорит правду, либо всегда врет.

      Однажды хоббит Бильбо Бэггинс услышал такой разговор:
      Балин (обращаясь к Двалину): Ты врун!
      Кили (обращаясь к Балину): Сам ты врун!
      Фили (обращаясь к Кили): Да оба они вруны, ? и, подумав, ? впрочем, ты тоже.
      Кто из этих гномов говорит правду?

      Приведенные тут варианты решения очень легко читаются — я думаю, к ним не нужны дополнительные пояснения. Если что-то не понятно — спрашивайте. Наиболее сложные предикаты — входит_в, без_повторов и убрать_повторы подробно разобраны тут. Там же, объясняется как понять findall. Также, понять решение может помочь статья «Решение логических задач на Prolog«.

      Тут приводится несколько решений, чаще всего каждое следующее решение получено незначительной доработкой предыдущего. Например, первая программа может выводить множество повторяющихся вариантов решений, а следующая — убирает повторы. Наиболее правильным всегда является последний варианты, однако первые варианты обычно проще (их проще понять, изучение кода стоит начать с них).

      Решение 1

      domains
      	имя = балин; двалин; кили; фили
      	тип = правдивый; врун
      	
      	структура_гипотезы = гном(имя, тип)
      	гипотеза = структура_гипотезы*
      	
      	имена = имя*
      	типы = тип*
      	
      	решение = говорит_правду(имя)
      constants
      	все_имена = [балин, двалин, кли, фили]
      	все_типы = [правдивый, врун]
      PREDICATES
        	nondeterm входит_в(имя, имена)
        	nondeterm входит_в(тип, типы)
        	nondeterm входит_в(структура_гипотезы, гипотеза)
        	
        	nondeterm генерация_гипотезы(гипотеза)
        	nondeterm сказал(имя, гипотеза)
        	nondeterm проверка_высказываний_и_типа(имя, гипотеза)
        	nondeterm проверка_гипотезы(гипотеза)
        	
        	nondeterm поиск_решения(решение)
      CLAUSES
        входит_в(Элемент, [Элемент|_ОстальныеЭлементы]).
        входит_в(Элемент, [_ПервыйЭлемент|ОстальныеЭлементы]):-
          	входит_в(Элемент, ОстальныеЭлементы).
          
        генерация_гипотезы(Гипотеза):-
        	входит_в(ТипБалина, все_типы),
        	входит_в(ТипДвалина, все_типы),
        	входит_в(ТипКли, все_типы),
        	входит_в(ТипФили, все_типы),
        	
        	Гипотеза = [
        		гном(балин, ТипБалина),
        		гном(двалин, ТипДвалина),
        		гном(кили, ТипКли),
        		гном(фили, ТипФили)
        	].
        	
      %Балин (обращаясь к Двалину): Ты врун!
      	сказал(балин, Гипотеза):-
      		входит_в(гном(двалин, врун), Гипотеза).
      %Кили (обращаясь к Балину): Сам ты врун!
      	сказал(кили, Гипотеза):-
      		входит_в(гном(балин, врун), Гипотеза).
      %Фили (обращаясь к Кили): Да оба они вруны, ? и, подумав, ? впрочем, ты тоже.
      	сказал(фили, Гипотеза):-
      		входит_в(гном(двалин, врун), Гипотеза),
      		входит_в(гном(балин, врун), Гипотеза),
      		входит_в(гном(кили, врун), Гипотеза).
      		
      	проверка_высказываний_и_типа(Имя, Гипотеза):-
      		входит_в(гном(Имя, правдивый), Гипотеза),
      		сказал(Имя, Гипотеза).
      	проверка_высказываний_и_типа(Имя, Гипотеза):-
      		входит_в(гном(Имя, врун), Гипотеза),
      		NOT(сказал(Имя, Гипотеза)).
        	
        	проверка_гипотезы(Гипотеза):-
        		проверка_высказываний_и_типа(балин, Гипотеза),
        		проверка_высказываний_и_типа(кили, Гипотеза),
        		проверка_высказываний_и_типа(фили, Гипотеза).
        		
        	поиск_решения(говорит_правду(Имя)):-
        		генерация_гипотезы(Гипотеза),
      		проверка_гипотезы(Гипотеза),
      		входит_в(гном(Имя, правдивый), Гипотеза).
      GOAL 
      	генерация_гипотезы(Гипотеза),
      	проверка_гипотезы(Гипотеза).
      	%поиск_решения(Решение).
      

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