1
votes

I am new to prolog and I am trying to solve the following question. I am having difficulty trying to understand the logic to solve the problem. I know its similar to zebra problem but, I am unsure how to approach. Any help would be greatly appreciated.

The answers submitted by five students to a T/F quiz are as follows.

Teresa: T T F T F
Tim:    F T T T F
Tania:  T F T T F
Tom:    F T T F T
Tony:   T F T F T
  1. Tania got more answers right than Teresa did.
  2. Tom got more right than Tim.
  3. Tony did not get all the answers right, nor did he get them all wrong.

Write a Prolog program quiz(Answer) that asserts Answer is the list of t and f constants that is the correct answer to the quiz..

2
Sounds like a fun puzzle. Why do you want to ruin it for yourself by cheating by asking for the solution here?wvdz
Looks like it has two possible answers..Eugene Sh.
I am not looking for the solution, I just need help to figure out the logic for it. A flow of steps that i could potentially use.mayak
Think about what facts are being stated first (each student with their answers) and decide how you want to represent them. For example, answers(teresa, [t,t,f,t,f])., etc. You could create a predicate to generate possible correct answer sets and compute each person's score against it. Backtrack when the conditions for score comparisons don't match. There really is only one result.lurker

2 Answers

1
votes

If you use SWI-Prolog, you can use library clpfd to solve the puzzle :, I get only one solution (f,f,t,f,t).

You have a solution [A,B,C,D,E]. You initialize the possibles solutions with

[A,B,C,D,E] ins 0..1,

You reify all the answers for teresa for example

teresea([1,1,0,1,0]).
A #= 1 #<==> TA
B #= 1 #<==> TB
.....

you compute the sum of Tis

sum([TA, TB, ...], #= , Steresa),

and later you will have for Tania got more answers right than Teresa did.

Stania #> Steresa

You get the solution with

label([A,B,C,D,E]).

Hope this helps

0
votes

small puzzles like this can be solved by generate-and-test

solve(L) :-
    % generator
    length(L, 5), maplist(tf, L),

    % Tania got more answers right than Teresa did.
    matches(L, tania, Tania),
    matches(L, teresa, Teresa), Tania > Teresa,
...

tf(t).
tf(f).

teresa(t, t, f, t, f).
tim(f, t, t, t, f).
...

Of course, matches(L, tania, Tania) counts correct Tania' answers.

But, I don't find a solution. The only tuple that 'get thru' Tony, it's its exact result. So, this condition

Tony did not get all the answers right

cannot be solved...

edit I had a bug in matches/3. Of course there is a solution.

edit well, the CLP(FD) version can be very compact, while being more general...

teresa(t, t, f, t, f).
...

matches(L, P, N) :-
    call(P, A,B,C,D,E),
    foldl(eqsum, [A,B,C,D,E], L, 0, N).
eqsum(t,Ls,Acc,N) :-    N #= Acc + (° #<==> Ls #= 1).
eqsum(f,Ls,Acc,N) :-    N #= Acc + (° #<==> Ls #= 0).

solve(L) :-
    length(°L, 5) ins 0..1,
    % Tania got more answers right than Teresa did.
    matches(L, tania, °) #> matches(L, teresa, °),
    % Tom got more right than Tim.
    matches(L, tom, °) #> matches(L, tim, °),
    % Tony did not get all the answers right, nor did he get them all wrong.
    matches(L, tony, °Tony) #> 0, Tony #< 5.

I used my lifter here.