Prolog — задача 152 Близнецы — лгуны

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

      Задача:

      В лицее учатся два брата-близнеца – Вася и Дима. Вася совершенно не может говорить правду по понедельникам, вторникам и средам,
      хотя в остальные дни он неизменно правдив. А Дима врет по вторникам, четвергам и субботам,
      но в другие дни он говорит только правду. Как-то я повстречал братьев и спросил одного из них:

      -Скажи, пожалуйста, как тебя зовут?
      Тот без малейшего колебания ответил:
      -Вася.
      -А какой сегодня день недели? – продолжал я расспросы.
      -Вчера было воскресенье, — сказал мой собеседник.

      -А завтра будет пятница, — добавил его брат.
      -Подожди, как же так? – изумился я, обращаясь к брату моего собеседника. – Ты уверен, что говоришь правду?
      -Я всегда говорю правду по средам, — услышал я в ответ.
      Решив, что говорить больше не о чем, братья пошли дальше, оставив меня в полном недоумении.
      Но, подумав, я все-таки сообразил, кто из двух братьев был Вася, а кто – Дима.
      Между прочим, по разговору можно установить и день недели, в который я встретился с ними. Попробуйте сообразить и вы.

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

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

      Решение 1

      DOMAINS
      	имя = дима; вася
      	когда = вчера;сегодня;завтра
      	
      	день_недели = понедельник; вторник; среда; четверг; пятница; суббота; воскресенье
      	структура_день_недели = структура_день(когда, день_недели)
      	дни_недели = структура_день_недели*
      	
      	номер_брата = integer
      	
      	структура_брат = кто(номер_брата, имя)
      	
      	структура_гипотезы = день(дни_недели); кто(номер_брата, имя)
      	гипотеза = структура_гипотезы*
      PREDICATES
      	nondeterm возможный_день_недели(дни_недели)
      	nondeterm возможное_имя(имя)
      	
      	nondeterm входит_в(структура_день_недели, дни_недели)
      	nondeterm входит_в(структура_гипотезы, гипотеза)
      	
      	nondeterm говорит_правду(имя, день_недели)
      	
      	nondeterm сказал(номер_брата, гипотеза)
      	
      	nondeterm генерация_гипотезы(гипотеза)
      CLAUSES
      	возможный_день_недели([структура_день(вчера,воскресенье),структура_день(сегодня,понедельник),структура_день(завтра,вторник)]).
          	возможный_день_недели([структура_день(вчера,понедельник),структура_день(сегодня,вторник),структура_день(завтра,среда)]).
          	возможный_день_недели([структура_день(вчера,вторник),структура_день(сегодня,среда),структура_день(завтра, четверг)]).
         	возможный_день_недели([структура_день(вчера,среда),структура_день(сегодня,четверг),структура_день(завтра,пятница)]).
          	возможный_день_недели([структура_день(вчера,четверг),структура_день(сегодня,пятница),структура_день(завтра,суббота)]).
          	возможный_день_недели([структура_день(вчера,пятница),структура_день(сегодня,суббота),структура_день(завтра,воскресенье)]).
          	возможный_день_недели([структура_день(вчера,суббота),структура_день(сегодня,воскресенье),структура_день(завтра,понедельник)]).
          	
          	% Вася совершенно не может говорить правду по понедельникам, вторникам и средам, 
              % хотя в остальные дни он неизменно правдив. А Дима врет по вторникам, четвергам и субботам, 
          	говорит_правду(вася, четверг).
          	говорит_правду(вася, пятница).
          	говорит_правду(вася, суббота).
          	говорит_правду(вася, воскресенье).
          	
          	говорит_правду(дима, понедельник).
          	говорит_правду(дима, среда).
          	говорит_правду(дима, пятница).
          	говорит_правду(дима, воскресенье).
      	
      	возможное_имя(дима).
      	возможное_имя(вася).
      	
      	сказал(1, Гипотеза):-
      		входит_в(кто(1, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		говорит_правду(Имя, Сегодня), % первый говорит правду
      		Имя = вася, % -Вася.
      		входит_в(структура_день(вчера, воскресенье), ДеньНедели). % Вчера было воскресенье, - сказал мой собеседник.
      	сказал(1, Гипотеза):-
      		входит_в(кто(1, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		NOT(говорит_правду(Имя, Сегодня)), % первый говорит ложь
      		NOT(Имя = вася), % -Вася.
      		NOT(входит_в(структура_день(вчера, воскресенье), ДеньНедели)). % Вчера было воскресенье, - сказал мой собеседник.
      	
      	сказал(2, Гипотеза):-
      		входит_в(кто(2, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		говорит_правду(Имя, Сегодня), % второй говорит правду
      		входит_в(структура_день(завтра, пятница), ДеньНедели), % -А завтра будет пятница, - добавил его брат.
      		говорит_правду(Имя, среда). % -Я всегда говорю правду по средам, - услышал я в ответ.
      	сказал(2, Гипотеза):-
      		входит_в(кто(2, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		NOT(говорит_правду(Имя, Сегодня)), % второй говорит ложь
      		NOT(входит_в(структура_день(завтра, пятница), ДеньНедели)), % -А завтра будет пятница, - добавил его брат.
      		NOT(говорит_правду(Имя, среда)). % -Я всегда говорю правду по средам, - услышал я в ответ.
      	
      	входит_в(День_недели,[День_недели|_]).
      	входит_в(День_недели,[_|Хвост_Списка]):-
      		входит_в(День_недели,Хвост_Списка).
      		
      	генерация_гипотезы([
      		день(День), кто(1, Имя1),  кто(2, Имя2)
      	]):-
      		возможное_имя(Имя1), возможное_имя(Имя2), NOT(Имя1 = Имя2),
      		возможный_день_недели(День).
      	
      goal
      	генерация_гипотезы(Гипотеза),
      	сказал(1, Гипотеза), сказал(2, Гипотеза).
      

      Решение 2

      DOMAINS
      	имя = дима; вася
      	когда = вчера;сегодня;завтра
      	
      	день_недели = понедельник; вторник; среда; четверг; пятница; суббота; воскресенье
      	структура_день_недели = структура_день(когда, день_недели)
      	дни_недели = структура_день_недели*
      	
      	номер_брата = integer
      	
      	структура_брат = кто(номер_брата, имя)
      	
      	структура_гипотезы = день(дни_недели); кто(номер_брата, имя)
      	гипотеза = структура_гипотезы*
      PREDICATES
      	nondeterm возможный_день_недели(дни_недели)
      	nondeterm возможное_имя(имя)
      	
      	nondeterm входит_в(структура_день_недели, дни_недели)
      	nondeterm входит_в(структура_гипотезы, гипотеза)
      	
      	nondeterm говорит_правду(имя, день_недели)
      	
      	nondeterm сказал(номер_брата, гипотеза)
      	
      	nondeterm генерация_гипотезы(гипотеза)
      	nondeterm поиск_решения(структура_день_недели)
      CLAUSES
      	возможный_день_недели([структура_день(вчера,воскресенье),структура_день(сегодня,понедельник),структура_день(завтра,вторник)]).
          	возможный_день_недели([структура_день(вчера,понедельник),структура_день(сегодня,вторник),структура_день(завтра,среда)]).
          	возможный_день_недели([структура_день(вчера,вторник),структура_день(сегодня,среда),структура_день(завтра, четверг)]).
         	возможный_день_недели([структура_день(вчера,среда),структура_день(сегодня,четверг),структура_день(завтра,пятница)]).
          	возможный_день_недели([структура_день(вчера,четверг),структура_день(сегодня,пятница),структура_день(завтра,суббота)]).
          	возможный_день_недели([структура_день(вчера,пятница),структура_день(сегодня,суббота),структура_день(завтра,воскресенье)]).
          	возможный_день_недели([структура_день(вчера,суббота),структура_день(сегодня,воскресенье),структура_день(завтра,понедельник)]).
          	
          	% Вася совершенно не может говорить правду по понедельникам, вторникам и средам, 
              % хотя в остальные дни он неизменно правдив. А Дима врет по вторникам, четвергам и субботам, 
          	говорит_правду(вася, четверг).
          	говорит_правду(вася, пятница).
          	говорит_правду(вася, суббота).
          	говорит_правду(вася, воскресенье).
          	
          	говорит_правду(дима, понедельник).
          	говорит_правду(дима, среда).
          	говорит_правду(дима, пятница).
          	говорит_правду(дима, воскресенье).
      	
      	возможное_имя(дима).
      	возможное_имя(вася).
      	
      	сказал(1, Гипотеза):-
      		входит_в(кто(1, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		говорит_правду(Имя, Сегодня), % первый говорит правду
      		Имя = вася, % -Вася.
      		входит_в(структура_день(вчера, воскресенье), ДеньНедели). % Вчера было воскресенье, - сказал мой собеседник.
      	сказал(1, Гипотеза):-
      		входит_в(кто(1, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		NOT(говорит_правду(Имя, Сегодня)), % первый говорит ложь
      		NOT(Имя = вася), % -Вася.
      		NOT(входит_в(структура_день(вчера, воскресенье), ДеньНедели)). % Вчера было воскресенье, - сказал мой собеседник.
      	
      	сказал(2, Гипотеза):-
      		входит_в(кто(2, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		говорит_правду(Имя, Сегодня), % второй говорит правду
      		входит_в(структура_день(завтра, пятница), ДеньНедели), % -А завтра будет пятница, - добавил его брат.
      		говорит_правду(Имя, среда). % -Я всегда говорю правду по средам, - услышал я в ответ.
      	сказал(2, Гипотеза):-
      		входит_в(кто(2, Имя), Гипотеза),
      		входит_в(день(ДеньНедели), Гипотеза),
      		входит_в(структура_день(сегодня, Сегодня), ДеньНедели),
      		NOT(говорит_правду(Имя, Сегодня)), % второй говорит ложь
      		NOT(входит_в(структура_день(завтра, пятница), ДеньНедели)), % -А завтра будет пятница, - добавил его брат.
      		NOT(говорит_правду(Имя, среда)). % -Я всегда говорю правду по средам, - услышал я в ответ.
      	
      	входит_в(День_недели,[День_недели|_]).
      	входит_в(День_недели,[_|Хвост_Списка]):-
      		входит_в(День_недели,Хвост_Списка).
      		
      	генерация_гипотезы([
      		день(День), кто(1, Имя1),  кто(2, Имя2)
      	]):-
      		возможное_имя(Имя1), возможное_имя(Имя2), NOT(Имя1 = Имя2),
      		возможный_день_недели(День).
      		
      	поиск_решения(СегодняДень):-
      		генерация_гипотезы(Гипотеза),
      		сказал(1, Гипотеза), сказал(2, Гипотеза),
      		Гипотеза = [День, _Кто1,  _Кто2],
      		День = день([_Вчера, СегодняДень, _Завтра]).
      	
      goal
      	поиск_решения(День).
      

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