问题陈述:在Prolog中定义一个关系equal_a_b(L),其中equal_a_b(L) true 如果L包含相等数量的 a 和< strong> b 条款。
我编写代码来计算术语和b术语的数量,并检查a == b。如果a === b为false,则程序应输出否。但是,当我测试我的代码时,它会输出yes,我不知道为什么。
以下是代码:
equal_a_b(L):-
eqab(L, A, B),
eqabn(A, B).
eqab([], 0, 0).
eqab([a|L], X, Y):- eqab(L, Z, A), X is Z + 1, Y is A + 0.
eqab([b|L], X, Y):- eqab(L, Z, A), X is Z + 0, Y is A + 1.
eqab([C|L], X, Y):- eqab(L, Z, A), X is Z + 0, Y is A + 0.
eqabn(A, B):- A==B.
以下是跟踪程序(equal_a_b([a])。它应该输出no:
| ?- trace, equal_a_b([a]).
The debugger will first creep -- showing everything (trace)
1 1 Call: equal_a_b([a]) ?
2 2 Call: eqab([a],_85,_86) ?
3 3 Call: eqab([],_110,_111) ?
3 3 Exit: eqab([],0,0) ?
4 3 Call: _138 is 0+1 ?
4 3 Exit: 1 is 0+1 ?
5 3 Call: _166 is 0+0 ?
5 3 Exit: 0 is 0+0 ?
2 2 Exit: eqab([a],1,0) ?
6 2 Call: eqabn(1,0) ?
7 3 Call: 1==0 ?
7 3 Fail: 1==0 ?
6 2 Fail: eqabn(1,0) ?
2 2 Redo: eqab([a],1,0) ? n
(10 ms) yes
感谢任何帮助,谢谢。
答案 0 :(得分:2)
equal_a_b(Xs) :-
equals_a_b__n(Xs, 0).
equals_a_b__n([], 0).
equals_a_b__n([C|Cs], N0) :-
char_n_(C, N0,N1),
equals_a_b__n(Cs, N1).
char_n_(C, N, N) :-
dif(C,a),
dif(C,b).
char_n_(a, N0, N) :-
N is N0 + 1.
char_n_(b, N0, N) :-
N is N0 - 1.
这个解决方案是真正的关系,你甚至可以问
告诉我包含相同数量字符
a
和b
的所有列表。
| ?- length(Xs, N), equal_a_b(Xs).
Xs = [], N = 0
; Xs = [_A], N = 1,
dif(_A,a), dif(_A,b)
; Xs = [_A,_B], N = 2,
dif(_A,a), dif(_A,b), dif(_B,a), dif(_B,b)
; Xs = [a,b], N = 2
; Xs = [b,a], N = 2
; Xs = [_A,_B,_C], N = 3,
dif(_A,a), dif(_A,b), dif(_B,a), dif(_B,b), dif(_C,a), dif(_C,b)
; Xs = [_A,a,b], N = 3,
dif(_A,a), dif(_A,b)
; Xs = [_A,b,a], N = 3,
dif(_A,a), dif(_A,b)
; Xs = [a,_A,b], N = 3,
dif(_A,a), dif(_A,b)
; Xs = [a,b,_A], N = 3,
dif(_A,a), dif(_A,b)
; Xs = [b,_A,a], N = 3,
dif(_A,a), dif(_A,b)
; Xs = [b,a,_A], N = 3,
dif(_A,a), dif(_A,b)
...
然后,它在当前的实现中也更有效。事实上,如果地面列表Xs
的长度为 l ,则只需要与log l 成比例的空间,而您和@lurker&#39 ; s解决方案需要与 l 成比例的空间。
答案 1 :(得分:0)
...
eqab([a|L], X, Y):- eqab(L, Z, A), !, X is Z + 1, Y is A + 0.
...
但如果您“反转”控制流程,则整体会更简单:倒数并检查,当列表变空时,如果计数匹配。