Это шестой пост из серии о кодировании головоломок LSAT на языке программирования Ergo Lite. Чтобы начать сначала, перейдите к вступительному посту.

В этом посте мы закодируем Вопрос 8. Он гласит:

8. Если «В центре внимания» больше никогда не покажут во время фестиваля после того, как будет показан «Жадность», то какое из следующего является максимальным количеством показов фильмов, которое может состояться во время фестиваля?

(А) три

(В) четыре

(С) пять

(Д) шесть

(Э) семь

Чтобы ответить на этот вопрос, мы должны иметь возможность сказать, что центр внимания не был показан после Жадности в данном расписании, и ограничить наши ответы расписаниями, где это верно.

Но прежде чем мы сможем добраться до этого, нам нужно разобраться со словом «после». Мы знаем, что такое «после» для слотов, потому что, например, мы сказали First[after->Second]. Но мы не знаем, что означает «после», если мы говорим о позже в тот же день или позже во время фестиваля.

Итак, чтобы понять это, нам нужно определить «после» для дней, а не только для слотов. Как мы вскоре увидим, нам также нужно определить «до» для дней. Итак, мы вернемся к коду, который мы использовали для определения дней и слотов, и заменим его следующим:

Day[|after=>Day,before=>Day|].
Thursday:Day[before->{Friday,Saturday}].
Friday:Day[after->Thursday, before->Saturday].
Saturday:Day[after->{Thursday,Friday}].
Slot[|after=>Slot|].
First:Slot.
Second:Slot[after->First].
Third:Slot[after->{First,Second}].

Ответы на вопрос 8 также касаются общего количества просмотров в расписании. Мы можем упростить процесс обращения к общему количеству просмотров, создав правило, которое подсчитывает просмотры и устанавливает число в атрибут screening_count.

?x[screening_count->?C] :-
    ?x:ValidSchedule,
    ?C = count{?s|?x[screenings->?s]}.

count{x|y} — это агрегатная функция, представленная в Ergo Lite. Так что теперь, если что-то является действительным расписанием, оно будет иметь атрибут screening_count, равный количеству просмотров в этом расписании.

Теперь мы можем создать правило, подтверждающее, что после жадности внимание не показывалось. Это будет верно, если объект является действительным расписанием, и мы узнаем, в какой день и в каком слоте был показан Greed (поскольку это действительное расписание, мы знаем, что оно было показано хотя бы один раз), и мы можем подтвердить, что Limelight не был показан позже в тот же день, а Limelight позже не показывали.

Это казалось правильным? Это не так. Близко, но не совсем. Вот почему:

Что, если в расписании есть Greed, а затем Limelight, а затем Greed, и показов Limelight больше нет? Проблема в том, что наш поиск найдет расписание и найдет два разных показа Greed. Основываясь на определении, которое мы только что дали, мы бы случайно пометили расписание как соответствующее на основе второй проверки Жадности, тогда как первая проверка должна была сделать его несоответствующим.

Поэтому нам нужно быть уверенными в том, что после первого показа Greed больше не будет показов Limelight.

Таким образом, наш тест должен быть таким: это правильный график, есть проявление жадности, нет других проявлений жадности за несколько дней до этого, нет других проявлений Limelight позже в тот же день, что и жадность, и есть никаких других показов Limelight в более поздние дни.

Мы знаем, что не может быть другого показа Жадности перед данным показом в тот же день, поэтому нам нужно определить «до» только для дней, а не для слотов.

Теперь мы готовы кодировать.

?x[limelight_not_after_greed->\true] :-
    ?x:ValidSchedule,
    ?x[screenings->?_s[film->Greed,day->?_day,slot->?_slot]],
    \naf exists(?_os)^?x[screenings->?_os[day->?_[before->?_day],film->Greed]],
    \naf exists(?_os)^?x[screenings->?_os[day->?_day,film->Limelight,slot->?_[after->?_slot]]],
    \naf exists(?_os)^?x[screenings->?_os[day->?_[after->?_day],film->Limelight]].

Таким образом, этот код гласит: «Это правда, что центр внимания не преследует жадность в отношении объекта X, если верно, что X является действительным расписанием, есть отсеивание жадности, нет другого отсеивания жадности в более ранний день, нет другого показа Limelight позже в тот же день, и нет другого показа Limelight в более поздний день ».

Теперь мы можем ограничить расписания, о которых мы говорим, ссылаясь на действительные расписания, для которых верно внимание не после жадности.

В дополнение к агрегатной функции count{a|b}, предоставляемой Ergo Lite, существует также функция max{a|b}, которую можно использовать для поиска наибольшего из ряда значений. Таким образом, для каждого из 5 возможных ответов мы спросим, ​​равно ли максимальное значение счетчика просмотров для всех допустимых расписаний, где центр внимания не отображается после жадности, заданному числу.

Наш код для ответов выглядит так:

question(8,a) :-
    max{?sc|?_x:ValidSchedule[limelight_not_after_greed->\true,screening_count->?sc]} == 3.
    
question(8,b) :-
    max{?sc|?_x:ValidSchedule[limelight_not_after_greed->\true,screening_count->?sc]} == 4.
question(8,c) :-
    max{?sc|?_x:ValidSchedule[limelight_not_after_greed->\true,screening_count->?sc]} == 5.
question(8,d) :-
    max{?sc|?_x:ValidSchedule[limelight_not_after_greed->\true,screening_count->?sc]} == 6.
question(8,e) :-
    max{?sc|?_x:ValidSchedule[limelight_not_after_greed->\true,screening_count->?sc]} == 7.

Теперь, по нашему обычному шаблону, мы можем спросить, каков правильный ответ на вопрос 8, используя запрос question(8,?x). И получаем ответ:

?x = d

Мы можем увидеть это конкретное расписание, выполнив другой запрос, который говорит: «покажите мне действительные расписания, в которых количество просмотров равно 6, а центр внимания не отображается после жадности»:

?- ?x:ValidSchedule[limelight_not_after_greed->\true,screening_count->6].
?x = test_sched(pd2(Limelight,Harvest),pd2(Harvest,Limelight),pd2(Limelight,Greed))
?x = test_sched(pd3(Limelight,Greed,Harvest),pd2(Harvest,Greed),pd1(Greed))
?x = test_sched(pd3(Limelight,Greed,Harvest),pd2(Harvest,Greed),pd1(Harvest))
3 solution(s) in 0.046 seconds; elapsed time = 0.041
Yes

Таким образом, вы можете видеть, что есть три действительных расписания тестов, в которых Limelight не появляется после Greed в расписании, и которые имеют в общей сложности 6 просмотров.

Это три вопроса вниз. В вопросе 9 мы собираемся изменить правила, а затем попытаться выяснить, что всегда должно быть правдой.

Джейсон Моррис — кандидат юридических наук в области вычислительного права на юридическом факультете Университета Альберты, оператор Round Table Law и соучредитель Lemma Legal Consulting. С ним можно связаться по адресу @RoundTableLaw в Твиттере. Если вам нужна помощь в том, чтобы заставить компьютеры заниматься юриспруденцией, не стесняйтесь обращаться к нам.