Prolog — задача 80 кто украл поваренную книгу

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

      Задача:

      Кто украл поваренную книгу?
      — Вот тебе сковорода,—сказал Король.— Испечешь мне наконец кренделей или нет?
      — Без рецепта?—спросила Королева.
      — Воспользуйся своим обычным рецептом,— закричал нетерпеливо Король.—В прошлый раз крендели у тебя удались на славу!
      — Не могу,—ответила Королева.—В прошлый раз я испекла крендели по рецепту из моей поваренной книги, а ее-то и украли!

      Наибольшие подозрения пали на кухарку Герцогини. Поваренную книгу действительно нашли на кухне у Герцогини.
      Похитить ее могли только кухарка, Герцогиня и Чеширский Кот.
      — Поваренную книгу украл Чеширский Кот! — заявила Герцогиня на суде.
      — О да, поваренную книгу украл я!—согласился Чеширский Кот с улыбкой.
      — Я не крала поваренную книгу!—утверждала кухарка.

      Выяснилось, что лгал тот, кто украл поваренную книгу, и что по крайней мере один из остальных обвиняемых сказал правду.
      Кто украл поваренную книгу?

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

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

      Решение 1

      DOMAINS 
      	имя = кухарка; герцогиня; кот
      	тип_высказывания = истина;ложь
      	роль = вор; невинный
      	
      	структура_гипотезы = персонаж(имя, роль, тип_высказывания)
      	гипотеза = структура_гипотезы*
      	
      	структура_высказывания = высказывание(имя, роль)
      	имена = имя*
      PREDICATES      
             nondeterm возможное_имя(имя)
             nondeterm возможный_тип_высказывания(тип_высказывания)
             nondeterm возможная_роль(роль)
             nondeterm генерация_гипотезы(гипотеза)
             
             nondeterm сказал(имя, структура_высказывания)
             nondeterm только_один_вор(гипотеза)
             nondeterm проверка_высказвания(имя, гипотеза)
             nondeterm проверка_гипотезы(гипотеза)
             
             nondeterm входит_в(структура_гипотезы, гипотеза)
            
      CLAUSES 
      	возможное_имя(кухарка).
      	возможное_имя(герцогиня).
      	возможное_имя(кот).
      	
      	возможный_тип_высказывания(истина).
      	возможный_тип_высказывания(ложь).
      	
      	возможная_роль(вор).
      	возможная_роль(невинный).
      	
      	генерация_гипотезы([
      		персонаж(кухарка, РольКухарки, ИстинностьКухарки),
      		персонаж(герцогиня, РольГерцогини, ИстинностьГерцогини),
      		персонаж(кот, РольКота, ИстинностьКота)
      	]):-
      		возможная_роль(РольКухарки),
      		возможная_роль(РольГерцогини),
      		возможная_роль(РольКота),
      		
      		возможный_тип_высказывания(ИстинностьКухарки),
      		возможный_тип_высказывания(ИстинностьГерцогини),
      		возможный_тип_высказывания(ИстинностьКота).
      		
      	сказал(герцогиня, высказывание(кот, вор)).
      	сказал(кот, высказывание(кот, вор)).
      	сказал(кухарка, высказывание(кухарка, невинный)).
      	
      	только_один_вор([персонаж(_, вор,_), персонаж(_, невинный,_), персонаж(_, невинный,_)]).
      	только_один_вор([персонаж(_, невинный,_), персонаж(_, вор,_), персонаж(_, невинный,_)]).
      	только_один_вор([персонаж(_, невинный,_), персонаж(_, невинный,_), персонаж(_, вор,_)]).
      	
      	проверка_высказвания(Имя, Гипотеза):-
      		входит_в(персонаж(Имя, _Роль, истина), Гипотеза),
      		сказал(Имя, высказывание(Кто, Какой)),
      		входит_в(персонаж(Кто, Какой, _), Гипотеза);
      		
      		входит_в(персонаж(Имя, _Роль, ложь), Гипотеза),
      		сказал(Имя, высказывание(Кто, Какой)),
      		входит_в(персонаж(Кто, Другой, _), Гипотеза),
      		NOT(Какой = Другой).
      		
      	входит_в(Элемент, [Элемент|_ОстальныеЭлементы]).
      	входит_в(Элемент, [_ПервыйЭлемент|ОстальныеЭлементы]):-
      		входит_в(Элемент, ОстальныеЭлементы).
      		
      	проверка_гипотезы(Гипотеза):-
      		только_один_вор(Гипотеза), 
      		
      		% лгал тот, кто украл: 
      		входит_в(персонаж(Вор, вор, ложь), Гипотеза), 
      		NOT(проверка_высказвания(Вор, Гипотеза)),
      		
      		% по крайней мере один сказал правду:
      		входит_в(персонаж(СказалПравду, _Роль, истина), Гипотеза),
      		проверка_высказвания(СказалПравду, Гипотеза).
      		
      		
      		
      GOAL    
              генерация_гипотезы(Гипотеза),
              проверка_гипотезы(Гипотеза).
      

      Решение 2

      DOMAINS 
      	имя = кухарка; герцогиня; кот
      	тип_высказывания = истина;ложь
      	роль = вор; невинный
      	
      	структура_гипотезы = персонаж(имя, роль, тип_высказывания)
      	гипотеза = структура_гипотезы*
      	
      	структура_высказывания = высказывание(имя, роль)
      	имена = имя*
      	
      	ответ = вор(имя)
      	ответы = ответ*
      	решения = гипотеза*
      PREDICATES      
             nondeterm возможное_имя(имя)
             nondeterm возможный_тип_высказывания(тип_высказывания)
             nondeterm возможная_роль(роль)
             nondeterm генерация_гипотезы(гипотеза)
             
             nondeterm сказал(имя, структура_высказывания)
             nondeterm только_один_вор(гипотеза)
             nondeterm проверка_высказвания(имя, гипотеза)
             nondeterm проверка_гипотезы(гипотеза)
             
             nondeterm входит_в(структура_гипотезы, гипотеза)
             nondeterm входит_в(ответ, ответы)
             
             nondeterm поиск_ответа(ответ)
             nondeterm выбрать_разные_ответы(ответы, ответы)
             nondeterm поиск_разных_ответов(ответы)
       
            
      CLAUSES 
      	возможное_имя(кухарка).
      	возможное_имя(герцогиня).
      	возможное_имя(кот).
      	
      	возможный_тип_высказывания(истина).
      	возможный_тип_высказывания(ложь).
      	
      	возможная_роль(вор).
      	возможная_роль(невинный).
      	
      	генерация_гипотезы([
      		персонаж(кухарка, РольКухарки, ИстинностьКухарки),
      		персонаж(герцогиня, РольГерцогини, ИстинностьГерцогини),
      		персонаж(кот, РольКота, ИстинностьКота)
      	]):-
      		возможная_роль(РольКухарки),
      		возможная_роль(РольГерцогини),
      		возможная_роль(РольКота),
      		
      		возможный_тип_высказывания(ИстинностьКухарки),
      		возможный_тип_высказывания(ИстинностьГерцогини),
      		возможный_тип_высказывания(ИстинностьКота).
      		
      	сказал(герцогиня, высказывание(кот, вор)).
      	сказал(кот, высказывание(кот, вор)).
      	сказал(кухарка, высказывание(кухарка, невинный)).
      	
      	только_один_вор([персонаж(_, вор,_), персонаж(_, невинный,_), персонаж(_, невинный,_)]).
      	только_один_вор([персонаж(_, невинный,_), персонаж(_, вор,_), персонаж(_, невинный,_)]).
      	только_один_вор([персонаж(_, невинный,_), персонаж(_, невинный,_), персонаж(_, вор,_)]).
      	
      	проверка_высказвания(Имя, Гипотеза):-
      		входит_в(персонаж(Имя, _Роль, истина), Гипотеза),
      		сказал(Имя, высказывание(Кто, Какой)),
      		входит_в(персонаж(Кто, Какой, _), Гипотеза);
      		
      		входит_в(персонаж(Имя, _Роль, ложь), Гипотеза),
      		сказал(Имя, высказывание(Кто, Какой)),
      		входит_в(персонаж(Кто, Другой, _), Гипотеза),
      		NOT(Какой = Другой).
      		
      	входит_в(Элемент, [Элемент|_ОстальныеЭлементы]).
      	входит_в(Элемент, [_ПервыйЭлемент|ОстальныеЭлементы]):-
      		входит_в(Элемент, ОстальныеЭлементы).
      		
      	проверка_гипотезы(Гипотеза):-
      		только_один_вор(Гипотеза), 
      		
      		% лгал тот, кто украл: 
      		входит_в(персонаж(Вор, вор, ложь), Гипотеза), 
      		NOT(проверка_высказвания(Вор, Гипотеза)),
      		
      		% по крайней мере один сказал правду:
      		входит_в(персонаж(СказалПравду, _Роль, истина), Гипотеза), %%%
      		проверка_высказвания(СказалПравду, Гипотеза).
      		
      	поиск_ответа(вор(Вор)):-
      		генерация_гипотезы(Гипотеза),
              	проверка_гипотезы(Гипотеза), 
              	входит_в(персонаж(Вор, вор, _), Гипотеза).
      		
      	/*
      	A = [1,2,3,2],
      	A = [H|T]. => H = 1, T = [2,3]
      	*/
      	выбрать_разные_ответы([], []).
      	выбрать_разные_ответы([Ответ|ОстальныеОтветы], [Ответ|ОстальныеРазныеОтветы]):-
      		NOT(входит_в(Ответ, ОстальныеОтветы)),
      		выбрать_разные_ответы(ОстальныеОтветы, ОстальныеРазныеОтветы).
      	% [1,1,1,1]
      	выбрать_разные_ответы([Ответ|ОстальныеОтветы], ОстальныеРазныеОтветы):-
      		NOT(NOT(входит_в(Ответ, ОстальныеОтветы))), 
      		% если не исопльзовать NOT NOT, то многократно выведется один и тот же ответ,
      		% т.к. праивльный ответ среди остальных можно выбрать несколькими разными способами
      		% NOT же вернет единственное решение, как и NOT(NOT(...))
      		выбрать_разные_ответы(ОстальныеОтветы, ОстальныеРазныеОтветы).
      		
      	поиск_разных_ответов(РазныеОтветы):-
      		findall(Ответ, поиск_ответа(Ответ), ВсеОтветы),
      		выбрать_разные_ответы(ВсеОтветы, РазныеОтветы).
      		
      GOAL    
      	/*генерация_гипотезы(Гипотеза),
      	проверка_гипотезы(Гипотеза).*/
              %поиск_ответа(Решение).
              %findall(Ответ, поиск_ответа(Ответ), ВсеОтветы).
              поиск_разных_ответов(РазныеОтветы).
      

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