Prolog 翻译可以是直接的、逐条规则的,仍然遵循通过从中选择域来实例化域的范式。这里是房屋属性的域;在链接的答案中,房屋属性由人类程序员固定,域是实际有人居住的房屋,这允许非常简洁的编码。
换句话说,区别在于符号:一个复杂的符号已经把我们带到了一半,但它是一个人发明并遵循它(就像程序员norwegian
必须在适当的参数处直接写下第一所房子的规范一样位置)——不是电脑。
在这里,我们尝试在代码中注入尽可能少的人类知识,遵循作业的约束。(当然,任何事情都是值得商榷的,避免人为干扰的最终方法是一个以英文文本作为输入的计算机程序......这将再次受到批评,即该程序是如何专门定制的,以寻找解决方案特定谜题或谜题类型等)
我们以自上而下的方式对其进行编码。显然,这个问题不见了。应该是“谁喝水?谁拥有斑马?” :
zebra( Z, W ,HS) :-
length( HS, 5), % nation? color? what's that? define it later...
member( H1, HS), nation( H1, eng ), color( H1, red ),
member( H2, HS), nation( H2, spa ), owns( H2, dog ),
member( H3, HS), drink( H3, coffee ), color( H3, green ),
member( H4, HS), nation( H4, ukr ), drink( H4, tea ),
right_of(B, A, HS), color( A , ivory ), color( B , green ),
member( H5, HS), smoke( H5, oldgold), owns( H5, snails ),
member( H6, HS), smoke( H6, kools ), color( H6, yellow ),
middle( C, HS), drink( C , milk ),
first( D, HS), nation( D , nor ),
next_to( E, F, HS), smoke( E , chester), owns( F , fox ),
next_to( G, H, HS), smoke( G , kools ), owns( H , horse ),
member( H7, HS), smoke( H7, lucky ), drink( H7, orange ),
member( H8, HS), nation( H8, jpn ), smoke( H8, parlamt),
next_to( I, J, HS), nation( I , nor ), color( J , blue ),
member( W, HS), drink( W , water ),
member( Z, HS), owns( Z , zebra ).
right_of( B, A, HS) :- append( _, [A, B | _], HS).
next_to( A, B, HS) :- right_of( B, A, HS) ; right_of( A, B, HS).
middle( A, [_,_,A,_,_]).
first( A, [A | _]).
nation(H, V) :- attr( H, nation-V).
owns( H, V) :- attr( H, owns-V). % select an attribute
smoke( H, V) :- attr( H, smoke-V). % from an extensible record H
color( H, V) :- attr( H, color-V). % of house attributes
drink( H, V) :- attr( H, drink-V). % which *is* a house
attr(House, Attr-Value) :-
memberchk( Attr-X, House), % unique attribute names
X = Value.
测试,使用失败驱动的循环执行穷举搜索,
3 ?- time((zebra(Z,W,_), maplist(nation,[Z,W],R), writeln(R), false ; true)).
[jpn,nor]
% 180,974 inferences, 0.016 CPU in 0.020 seconds (78% CPU, 11600823 Lips)
true.
以下是房屋的最终定义方式:
5 ?- zebra(_, _, HS), maplist( writeln, HS),
false.
[smoke-kools, color-yellow, nation-nor, owns-fox, drink-water |_G859]
[nation-ukr, drink-tea, smoke-chester, owns-horse, color-blue |_G853]
[nation-eng, color-red, smoke-oldgold, owns-snails, drink-milk |_G775]
[nation-spa, owns-dog, color-ivory, smoke-lucky, drink-orange|_G826]
[drink-coffee, color-green, nation-jpn, smoke-parlamt, owns-zebra |_G865]
false.
或者,通过固定长度来“冻结”属性列表,然后排序,
7 ?- zebra( _, _, HS), maplist( length, HS, _), !, maplist( sort, HS, S),
maplist( writeln, S), false.
[color-yellow, drink-water, nation-nor, owns-fox, smoke-kools ]
[color-blue, drink-tea, nation-ukr, owns-horse, smoke-chester]
[color-red, drink-milk, nation-eng, owns-snails, smoke-oldgold]
[color-ivory, drink-orange, nation-spa, owns-dog, smoke-lucky ]
[color-green, drink-coffee, nation-jpn, owns-zebra, smoke-parlamt]
false.
attr/2
使谓词接受对列表Name-Value
也很容易,允许更自然流动、更高层次的编码风格,以及一种“可扩展记录” ——甚至可以说是“对象” ——规范,比如
zebra( Z, W ,HS):-
length( HS, 5),
member( H1, HS), attr( H1, [nation-eng, color-red ] ),
member( H2, HS), attr( H2, [nation-spa, owns-dog ] ),
member( H3, HS), attr( H3, [drink-coffee, color-green] ),
......
等等。。