?- A=B, C=B, B=D, D=123. A = 123, B = 123, C = 123, D = 123.
?- L=[A,B,C], L=[5,5|_], C=Q, Q=B. L = [5, 5, 5], A = 5, B = 5, C = 5, Q = 5.
?- length(L,3). L = [_G328, _G331, _G334].
?- length(L,3), nth0(0,L,aaa). L = [aaa, _G461, _G464].
aaa
. At the same time, the list itself was partially specified. ?- length(L,3), nth0(0,L,aaa), nth0(1,L,bbb). L = [aaa, bbb, _G594].
?- length(L,3), nth0(0,L,aaa), nth0(1,L,bbb), nth0(2,L,ccc). L = [aaa, bbb, ccc].
aaa
, the second is bbb
, and the third is ccc
. Which is equivalent to the usual: ?- L=[aaa,bbb,ccc]. L = [aaa, bbb, ccc].
L = [no, no, no]
L=[yes(aaa), no, no]
L=[yes(aaa), yes(bbb), yes(ccc)].
logic
module (mercury supports type classes, like haskell): :- module logic. :- interface. :- import_module list, maybe. :- typeclass unifiable(T) where [ func unify(T, T) = T is semidet ]. :- instance unifiable(maybe(T)). :- instance unifiable(list(T)) <= unifiable(T). :- pred unify(T, T, T) <= unifiable(T). :- mode unify(in, in, out) is semidet. :- pred member(T, T, list(T), list(T)) <= unifiable(T). :- mode member(in, out, in, out) is nondet. :- pred member(T, list(T), list(T)) <= unifiable(T). :- mode member(in, in, out) is nondet. :- implementation. :- import_module maybe, list. :- instance unifiable(maybe(T)) where [ func(unify/2) is unify_maybe ]. :- instance unifiable(list(T)) <= unifiable(T) where [ func(unify/2) is unify_lists ]. :- func unify_maybe(maybe(T), maybe(T)) = maybe(T) is semidet. unify_maybe(no, yes(E)) = yes(E). unify_maybe(yes(E), no) = yes(E). unify_maybe(no, no) = no. unify_maybe(yes(E), yes(E)) = yes(E). :- func unify_lists(list(T), list(T)) = list(T) is semidet <= unifiable(T). unify_lists([], []) = []. unify_lists([H|T], [H1|T1]) = [unify(H, H1) | unify_lists(T, T1)]. :- pred unify_lists(list(T), list(T), list(T)) <= unifiable(T). :- mode unify_lists(in, in, out) is semidet. unify_lists(L1, L2, unify_lists(L1, L2)). unify(A, B, unify(A, B)). member(E, E, [], []) :- fail. member(E0, E1, [H | T], [H1 | T1]) :- ( H0 = unify(E0, H), H1 = H0, E1 = H0, T=T1 ; H1 = H, member(E0, E1, T, T1) ). member(E, !L) :- member(E,_,!L).
:- module einstein. :- interface. :- import_module io. :- pred main(io::di, io::uo) is det. :- implementation. :- import_module maybe, list, solutions, logic. :- type house ---> house(maybe(nationality), maybe(color), maybe(pet), maybe(cigarettes), maybe(drink)). :- type nationality ---> englishman; spaniard; norwegian; ukrainian; japanese. :- type color ---> red; yellow; blue; green; ivory. :- type pet ---> dog; snails; fox; horse; zebra. :- type cigarettes ---> kools; chesterfields; winston; lucky_strike; parliaments. :- type drink ---> orange_juice; tea; coffee; milk; water. :- instance unifiable(house) where [ unify( house(N, C, P, S, D), house(N1, C1, P1, S1, D1)) = house(unify(N, N1), unify(C, C1), unify(P, P1), unify(S, S1), unify(D, D1)) ]. unknown_house = house(no,no,no,no,no). solve(!Street):- % The Englishman lives in the red house logic.member(house(yes(englishman),yes(red),no,no,no), !Street), % The Spaniard owns the dog logic.member(house(yes(spaniard),no,yes(dog),no,no), !Street), % The Norwegian lives in the first house on the left unify([house(yes(norwegian),no,no,no,no),unknown_house,unknown_house,unknown_house,unknown_house], !Street), % Kools are smoked in the yellow house. logic.member(house(no,yes(yellow),no,yes(kools),no), !Street), % The man who smokes Chesterfields lives in the house % next to the man with the fox. next(house(no,no,yes(fox),no,no), house(no,no,no,yes(chesterfields),no), !Street), % The Norwegian lives next to the blue house next(house(yes(norwegian),no,no,no,no), house(no,yes(blue),no,no,no), !Street), % The Winston smoker owns snails. logic.member(house(no,no,yes(snails),yes(winston),no), !Street), % The lucky strike smoker drinks orange juice logic.member(house(no,no,no,yes(lucky_strike),yes(orange_juice)), !Street), % The Ukrainian drinks tea logic.member(house(yes(ukrainian),no,no,no,yes(tea)), !Street), % The Japanese smokes parliaments logic.member(house(yes(japanese),no,no,yes(parliaments),no), !Street), % Kools are smoked in the house next to the house where the horse is kept. next(house(no,no,yes(horse),no,no), house(no,no,no,yes(kools),no), !Street), % Coffee is drunk in the green house logic.member(house(no,yes(green),no,no,yes(coffee)), !Street), % The green house is immediately to the right (your right) of the ivory house left(house(no,yes(ivory),no,no,no), house(no,yes(green),no,no,no), !Street), % Milk is drunk in the middle house. unify([unknown_house,unknown_house,house(no,no,no,no,yes(milk)),unknown_house,unknown_house], !Street), % And, finally, zebra and water :) logic.member(house(no,no,yes(zebra),no,no), !Street), logic.member(house(no,no,no,no,yes(water)), !Street). next(H1, H2, !Street):- left(H1, H2, !Street); left(H2, H1, !Street). left(H1, H2, !Street):- unify([H1,H2,unknown_house,unknown_house,unknown_house], !Street); unify([unknown_house,H1,H2,unknown_house,unknown_house], !Street); unify([unknown_house,unknown_house,H1,H2,unknown_house], !Street); unify([unknown_house,unknown_house,unknown_house,H1,H2], !Street). main --> { solutions(pred(S::out) is nondet :- solve([unknown_house,unknown_house,unknown_house,unknown_house,unknown_house], S), L)}, print_solutions(L). print_solutions(L) --> write_string("Total solutions: "), write_int(length(L)), nl, nl, print_every_sol(L). print_every_sol([]) --> []. print_every_sol([S|SS]) --> print_sol(S), print_every_sol(SS). print_sol([]) --> []. print_sol([H|HH]) --> print_house(H), nl, print_sol(HH). print_maybe(no) --> write_string("unknown"). print_maybe(yes(T)) --> write(T). print_house(house(N, C, P, S, D)) --> write_string("house("), print_maybe(N), write_string(", "), print_maybe(C), write_string(", "), print_maybe(P), write_string(", "), print_maybe(S), write_string(", "), print_maybe(D), write_string(")").
$ time ./einstein
Total solutions: 1
house(norwegian, yellow, fox, kools, water)
house(ukrainian, blue, horse, chesterfields, tea)
house(englishman, red, snails, winston, milk)
house(spaniard, ivory, dog, lucky_strike, orange_juice)
house(japanese, green, zebra, parliaments, coffee)
real 0m0.031s
user 0m0.015s
sys 0m0.015s
Source: https://habr.com/ru/post/122147/
All Articles