This is yet another solution using DNF (Disjunctive Normal Form). Idea is simple: Given the lion-unicorn puzzle in English, translate it to a propositional logic. Then build a DNF of the formula, which is the set of solutions of the puzzle. I don’t know generality of this simple minded approach. In fact, I should doubt its generality because of the possible huge DNF on the way of getting the final one. Solving methods posted by others in this thread should be much better than mine here. Fortunately, as for the lion-unicorn puzzle only small DNF is needed with care with basics of propositional logic, which was obtained with zdd library. Anyway it was a good exercise for me on using the zdd library.
Prolog codes using zdd library
:-module(lion_unicorn, []).
:- use_module(pac(basic)).
:- use_module(zdd('zdd-array')).
:- use_module(zdd(zdd)).
:- use_module(pac(op)).
solve_lion_uncorn_puzzle_in_dnf(Ans):-
build_puzzle_prop(Prop),
( zdd X<< dnf(Prop), zmod:zdd_find(=(today(_)), X, Ans) ).
%
day_of_week([mon, tue, wed, thu, fri, sat, sun]).
%
liar_mode_list(unicorn, [1, 1, 1, 0, 0, 0, 1]).
liar_mode_list(lion, [0, 0, 0, 1, 1, 1, 1]).
%
today(D):- day_of_week(Ds), member(D, Ds).
% ?- yesterday(Y,T).
yesterday(Y, T):- day_of_week(Ds),
between(0, 6, J),
between(0, 6, I),
I is (J-1) mod 7,
nth0(J, Ds, T),
nth0(I, Ds, Y).
% ?- liar(W, D).
liar(Who, D):- day_of_week(Ds),
liar_mode_list(Who, M),
between(0, 6, I),
nth0(I, M, 0),
nth0(I, Ds, D).
% ?- build_puzzle_prop(_Prop), (zdd X<< dnf(_Prop), sets(X, _S), {length(_S, C0)}, card(X, C), psa(X)).
build_puzzle_prop(Props):-
prop_group(today, Tod),
prop_group(day_dependent_truth, Deps),
prop_group(liar, Liar),
Props = (*(Deps) * +(Tod) * *(Liar)).
% ?- prop_group(today, T).
prop_group(today, TDs):-!, findall(today(D), today(D), TDs).
% ?- prop_group(yesterday, Y), length(Y, N).
prop_group(yesterday, YDay):-!, findall(yesterday(Y, T), yesterday(Y, T), YDay).
% ?- prop_group(liar, Y), length(Y, N), maplist(writeln, Y).
prop_group(liar, LiarProps):-!,
findall(X,
( today(D),
member(Who, [lion, unicorn]),
( liar(Who, D), X = liar(Who, D)
; \+ liar(Who, D), X = -liar(Who, D)
)
),
LiarProps).
% ?- prop_group(day_dependent_truth, _Deps), maplist(writeln, _Deps).
%@ today(tue)->liar(lion,tue)== -liar(lion,mon)
%@ today(tue)->liar(unicorn,tue)== -liar(unicorn,mon)
%@ today(wed)->liar(lion,wed)== -liar(lion,tue)
%@ today(wed)->liar(unicorn,wed)== -liar(unicorn,tue)
%@ today(thu)->liar(lion,thu)== -liar(lion,wed)
%@ today(thu)->liar(unicorn,thu)== -liar(unicorn,wed)
%@ today(fri)->liar(lion,fri)== -liar(lion,thu)
%@ today(fri)->liar(unicorn,fri)== -liar(unicorn,thu)
%@ today(sat)->liar(lion,sat)== -liar(lion,fri)
%@ today(sat)->liar(unicorn,sat)== -liar(unicorn,fri)
%@ today(sun)->liar(lion,sun)== -liar(lion,sat)
%@ today(sun)->liar(unicorn,sun)== -liar(unicorn,sat)
%@ today(mon)->liar(lion,mon)== -liar(lion,sun)
%@ today(mon)->liar(unicorn,mon)== -liar(unicorn,sun)
%@ true.
prop_group(day_dependent_truth, Deps):-
findall( today(D)->(liar(Who, D) == -liar(Who, Y)),
( yesterday(Y, D),
member(Who, [lion, unicorn])
),
Deps).