Prolog 列表练习
Prolog list exercise
这是我的练习:在 prolog 中定义一个谓词,应用于整数列表 L,结果给出 L 中偶数元素的后继列表。
我写的代码只有当一个元素是偶数时才有效,谁能帮我找出我错在哪里?
even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).
list_even([],[]).
list_even([T|C],K):- even(T), E is T+1, list_even(C,K1), append(K1,E,X), K is X.
list_even([T|C],K):- odd(T),list_even(C,K).
您的代码中的一些缺陷是:
append(K1, E, X)
:这个目标应该附加两个列表来生成第三个列表;但是,E
只是一个元素,而不是列表。所以你需要写append(K1, [E], X)
.
K is X
:该目标对变量X
表示的算术表达式进行求值,并将其值与变量K
统一;但是,X
是一个列表,而不是算术表达式。所以你需要删除它。
所以正确的代码如下:
list_even([], []).
list_even([T|C], K):- even(T), E is T+1, list_even(C, K1), append(K1, [E], K).
list_even([T|C], K):- odd(T), list_even(C, K).
示例:
?- list_even([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [9, 41, 21] ;
false.
注意在得到的答案中,后继出现的顺序是相反的(输入列表中第一个偶数元素是20
,但它的后继21
是输出列表中的最后一个元素).
所以更好的代码如下:
even_number_successors([], []).
even_number_successors([X|Xs], Successors) :-
( X mod 2 =:= 0
-> Y is X + 1,
Successors = [Y|Ys]
; Successors = Ys ),
even_number_successors(Xs, Ys).
示例:
?- even_number_successors([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [21, 41, 9].
根据你的问题陈述,
define a predicate in prolog which, applied to a list L
of integers, gives as a result the list of the successors of the even elements present in L
.
从表面上看,你不需要odd/1
:不是偶数就是奇数。
为什么要用append/3
?您只是 iterating/filtering 一个列表并正在构建一个新列表,对吗?相反,您可以通过使列表不完整并带有未绑定的尾部来按顺序构建列表。当我们向下递归时,我们构建列表的尾部,或者通过将它与一个新列表统一,或者在最后,将它与空列表统一,即原子 []
).
我会这样做:
list_even( [] , [] ) . % empty list? All done.
list_even( [X|Xs] , [Y|Ys] ) :- % non-empty?
even(X), % - is X even? if so...
!, % - eliminate the choice point
Y is X+1, % - get the successor of X
list_even(Xs,Ys) % - recurse down
. %
list_even( [_|Xs] , Ys ) :- % Otherwise, the head of the list is odd: discard the head, and...
list_even(Xs,Ys) % - recurse down
. % Easy!
even(X) :- 0 =:= X .
这是我的练习:在 prolog 中定义一个谓词,应用于整数列表 L,结果给出 L 中偶数元素的后继列表。
我写的代码只有当一个元素是偶数时才有效,谁能帮我找出我错在哪里?
even(X):- 0 is mod(X,2).
odd(X):- 1 is mod(X,2).
list_even([],[]).
list_even([T|C],K):- even(T), E is T+1, list_even(C,K1), append(K1,E,X), K is X.
list_even([T|C],K):- odd(T),list_even(C,K).
您的代码中的一些缺陷是:
append(K1, E, X)
:这个目标应该附加两个列表来生成第三个列表;但是,E
只是一个元素,而不是列表。所以你需要写append(K1, [E], X)
.K is X
:该目标对变量X
表示的算术表达式进行求值,并将其值与变量K
统一;但是,X
是一个列表,而不是算术表达式。所以你需要删除它。
所以正确的代码如下:
list_even([], []).
list_even([T|C], K):- even(T), E is T+1, list_even(C, K1), append(K1, [E], K).
list_even([T|C], K):- odd(T), list_even(C, K).
示例:
?- list_even([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [9, 41, 21] ;
false.
注意在得到的答案中,后继出现的顺序是相反的(输入列表中第一个偶数元素是20
,但它的后继21
是输出列表中的最后一个元素).
所以更好的代码如下:
even_number_successors([], []).
even_number_successors([X|Xs], Successors) :-
( X mod 2 =:= 0
-> Y is X + 1,
Successors = [Y|Ys]
; Successors = Ys ),
even_number_successors(Xs, Ys).
示例:
?- even_number_successors([1, 20, 3, 40, 5, 7, 8], Successors).
Successors = [21, 41, 9].
根据你的问题陈述,
define a predicate in prolog which, applied to a list
L
of integers, gives as a result the list of the successors of the even elements present inL
.
从表面上看,你不需要
odd/1
:不是偶数就是奇数。为什么要用
append/3
?您只是 iterating/filtering 一个列表并正在构建一个新列表,对吗?相反,您可以通过使列表不完整并带有未绑定的尾部来按顺序构建列表。当我们向下递归时,我们构建列表的尾部,或者通过将它与一个新列表统一,或者在最后,将它与空列表统一,即原子[]
).
我会这样做:
list_even( [] , [] ) . % empty list? All done.
list_even( [X|Xs] , [Y|Ys] ) :- % non-empty?
even(X), % - is X even? if so...
!, % - eliminate the choice point
Y is X+1, % - get the successor of X
list_even(Xs,Ys) % - recurse down
. %
list_even( [_|Xs] , Ys ) :- % Otherwise, the head of the list is odd: discard the head, and...
list_even(Xs,Ys) % - recurse down
. % Easy!
even(X) :- 0 =:= X .