我尝试为Can You Crack The Code? “Only Geniuses Can Solve”编写Prolog解决方案。
为方便起见,我在此处复制文本:
数字锁需要一个3位数字的密码。根据这些提示:
682 –一个数字正确且位置正确
645 –一个数字正确但位置错误
206 –两个数字正确但位置错误
738 –没错
780 –一个数字正确但位置错误
您可以破解代码吗?
A为每种提示提供了一个谓词。
对于“一个数字正确且位置正确”的提示,我写道:
correct_position(A, B, C, S) :-
S = [A, _, _],
\+ member(B, S),
\+ member(C, S).
correct_position(A, B, C, S) :-
S = [_, B, _],
\+ member(A, S),
\+ member(C, S).
correct_position(A, B, C, S) :-
S = [_, _, C],
\+ member(A, S),
\+ member(B, S).
对于“一个数字正确但位置错误”的提示,我写道:
wrong_position(A, B, C, S) :-
(S = [_, A, _] ; S = [_, _, A]),
\+ member(B, S),
\+ member(C, S).
wrong_position(A, B, C, S) :-
(S = [B, _, _] ; S = [_, _, B]),
\+ member(A, S),
\+ member(C, S).
wrong_position(A, B, C, S) :-
(S = [C, _, _] ; S = [_, C, _]),
\+ member(A, S),
\+ member(B, S).
对于“两个数字是正确的但位置错误”的提示,我写道:
two_wrong_position(A, B, C, S) :-
S \= [A, _, _],
S \= [_, B, _],
member(A, S),
member(B, S),
\+ member(C, S).
two_wrong_position(A, B, C, S) :-
S \= [A, _, _],
S \= [_, _, C],
member(A, S),
member(C, S),
\+ member(B, S).
two_wrong_position(A, B, C, S) :-
S \= [_, B, _],
S \= [_, _, C],
member(B, S),
member(C, S),
\+ member(A, S).
最后,我写了“什么都不对”的提示:
none(A, B, C, S) :-
\+ member(A, S),
\+ member(B, S),
\+ member(C, S).
然后获得解决方案:
solution(S) :-
between(0, 9, A),
between(0, 9, B),
between(0, 9, C),
S = [A, B, C],
correct_position(6, 8, 2, S),
wrong_position(6, 4, 5, S),
two_wrong_position(2, 0, 6, S),
none(7, 3, 8, S),
wrong_position(7, 8, 0, S).
当然可以,但是提示的谓词是对问题实例的“硬编码”,根本无法扩展。错误位置和two_wrong_positions谓词说明的情况相似,但完全不同,并且在出现新问题的情况下,给出了“三个数字正确但位置错误”的提示,必须从头开始将其编码。
如何重写此类提示的谓词?