偶数和奇数列表

Ang*_*ris 2 list prolog

我正在尝试实现一个将列表分成两个列表的Prolog程序.第一个将包含偶数位置的数字,第二个包含数字是奇数位置.

例如:even_odd([1,2,4,7,5],Even,Odd).将导致Even=[2,7].Odd=[1,4,5].

我找到了比谷歌搜索问题更优雅的解决方案,但是我想在我的代码中找到问题所在(可能是操作员滥用)因为我真的认为我对Prolog操作符的理解非常差(特别是在算术比较中) .谷歌搜索只会使情况变得更糟,每个网站都有完全不同的解释.

我的代码:

even_odd([], [], []).
even_odd([H|T], Even, Odd) :-
    length([H|T], X),
    X mod 2 is 0,
    append(Even1, H, Even),
    even_odd(T, Even1, Odd).
even_odd([H|T], Even, Odd) :-
    length([H|T], X),
    X mod 2 is 1,
    append(Odd1, H, Odd),
    even_odd(T,Even,Odd1).
Run Code Online (Sandbox Code Playgroud)

我试过跟踪,我知道问题在于X mod 2 is 1或者0,它们都不是真的.如果我有一个三个元素的列表并且改变X is 3它的条件是完全没问题的,但是这个部门似乎搞得一团糟,所以任何想法?

Cap*_*liC 5

算术求值运算符 (is)/2 对右侧表达式执行算术,并将其与其左侧参数统一,然后将测试应用于错误的变量。应该

even_odd([H|T],Even,Odd):- 0 is H mod 2,...
Run Code Online (Sandbox Code Playgroud)

或者,还有 (=:=)/2 在两边执行算术。那么可能是

H mod 2 =:= 0
Run Code Online (Sandbox Code Playgroud)

此外,处理列表的方式没有多大意义。您必须在偶数列表中放入偶数值。然后像

even_odd([H|T],[H|Even],Odd):- 0 is H mod 2,...
Run Code Online (Sandbox Code Playgroud)

会更有意义。


SQB*_*SQB 5

虽然CapelliC对你的代码失败的原因有正确的认识,但他误解了你关于想要偶数/奇数位置的问题.

问题是,你正在计算列表末尾的那些,因此even_odd([1,2,4,7],Even,Odd).会产生,Even=[1,4].Odd=[2,7].不是你想要的.
解决方案是在处理之前颠倒列表并在之后反转结果,或采取不同的方法.

在这里,我们首先将第一个元素添加到奇数列表,然后在添加到偶数列表和奇数列表之间交替,直到我们到达最终元素.

even_odd(List, Even, Odd) :- 
    % First position is odd
    even_odd_odd(List, Even, Odd).

% We handle the odd position, the next is even
even_odd_odd([H|T], Even, [H|Odd]) :- 
    even_odd_even(T, Even, Odd).
even_odd_odd([], [], []).

% We handle the even position; the next is odd
even_odd_even([H|T], [H|Even], Odd) :- 
    even_odd_odd(T, Even, Odd).
even_odd_even([], [], []).
Run Code Online (Sandbox Code Playgroud)