Toggle navigation
?
users online
Logout
Open hangout
Open chat for current file
%% An example of a "Professort Layton" puzzle with Prolog. %% From Pablo Meier's post https://morepablo.com/2010/09/some-professor-layton-prolog.html %% A question is a [[question number,answer], correctness]. %% Example: %% [[1,a], correct] %% A test is a list of questions. %% We create a rule that every correct answer is 10 points. points([_, correct], 10). points([_, incorrect], 0). %% Create rules flip solutions and whether or not they are incorrect. flip(a, b). flip(correct, incorrect). flip(b, a). flip(incorrect, correct). %% Given a test, calculates the score based on the correctness. test_score([], 0). test_score([H|T], Score) :- points(H, These_Points), test_score(T, Rest_of_Points), Score is These_Points + Rest_of_Points. %% This is the critical rule: it ensures that all tests are scored %% by the same answer key. This way, Prolog won't find a binding that %% works for each individual test, but for all tests that get bound. %% Two empty tests naturally follow the same grading criteria: sensible_scores([], []). %% We investigate tests recursively: if both tests have identical heads %% (e.g. they agree on an answer and its correctness) then the test is %% 'sensible' (follows a common rubric) as long as the rest of the test does. sensible_scores([A|T1], [A|T2]) :- sensible_scores(T1, T2). %% If they have the same number but differ in answer, they must also differ %% in correctness. sensible_scores([[[A,B],Aye]|T1], [[[A,C],Nay]|T2]) :- flip(B, C), flip(Aye, Nay), sensible_scores(T1, T2). %% A cheap rule that binds X to Mary's score sheet. Correctness %% is automagically bound by Prolog! mary_test(X) :- X = [ [[1, b], _], [[2, b], _], [[3, a], _], [[4, b], _], [[5, a], _], [[6, b], _], [[7, b], _], [[8, a], _], [[9, b], _], [[10, b], _]]. %% Dan's score sheet. dan_test(X) :- X = [ [[1, b], _], [[2, a], _], [[3, a], _], [[4, a], _], [[5, b], _], [[6, a], _], [[7, b], _], [[8, a], _], [[9, a], _], [[10, a], _]]. %% Lisa's score sheet. lisa_test(X) :- X = [ [[1, b], _], [[2, a], _], [[3, a], _], [[4, a], _], [[5, b], _], [[6, b], _], [[7, b], _], [[8, a], _], [[9, b], _], [[10, a], _]]. %% And Colin's, whose score we don't know. colin_test(X) :- X = [ [[1, b], _], [[2, b], _], [[3, a], _], [[4, a], _], [[5, a], _], [[6, b], _], [[7, b], _], [[8, a], _], [[9, a], _], [[10, a], _]]. %% Finally, the meat! We bind Lisa, Dan, and Mary to their score sheets. %% We then use sensible_scores to ensure that their sheets follow the same %% grading rubric. Finally, we ensure that this rubric adheres to the scores %% that Mary, Dan, and Lisa obtained. test_integrity(X) :- lisa_test(Lisa), dan_test(Dan), mary_test(Mary), sensible_scores(Lisa, Dan), sensible_scores(Dan, Mary), sensible_scores(Mary, X), test_score(Mary, 70), test_score(Dan, 50), test_score(Lisa, 30). %% Finally, we bind Score to what Colin's score is by setting %% it to his test results, ensuring that his score has the same %% answer key as his peers, then calculating the score with that %% answer key. colin_score(Score) :- colin_test(X), test_integrity(X), test_score(X, Score). /** <examples> Your example queries go here, e.g. ?- colin_score(Score). */