我想问一下,是否有人知道如何改进(如果不是最佳的话)此代码。
这个想法是,您有一个元素列表,我想返回一个列表,其中包含两个子列表,第一个子列表应包含列表中奇数个位置中包含的元素,第二个子列表应该包含包含在列表偶数位置的元素。
一些例子:
?-evenAndOdd([1,2,3,4,5],[[1,3,5],[2,4]])
True.
?-evenAndOdd([a,b,c,d,e],[[a,c,e],[b,d]]).
True.
我实现的代码是下一个:
evenAndOdd([],[]).
evenAndOdd([H|R],NL):-
evenAndOddRec([H|R], [[],[]],1,NL).
evenAndOddRec([], [LOdd,LEven],_,[LOdd,LEven]).
evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
\+ even(Pos),
!,
NPos is Pos +1,
append(LOdd,[H],NLOdd),
evenAndOddRec(R,[NLOdd,LEven],NPos,NL).
evenAndOddRec([H|R],[LOdd,LEven],Pos,NL):-
NPos is Pos + 1,
append(LEven, [H], NLEven),
evenAndOddRec(R,[LOdd, NLEven],NPos,NL).
even(N):-
N mod 2 =:=0.
答案 0 :(得分:4)
通过一次获取两个元素(并考虑元素中具有奇数个元素的情况),可以隐式确定递归时的偶数和奇数值:
evenAndOdd(L, [LOdd, LEven]):-
evenAndOdd(L, LOdd, LEven).
evenAndOdd([], [], []).
evenAndOdd([Odd], [Odd], []).
evenAndOdd([Odd,Even|Tail], [Odd|LOdd], [Even|LEven]):-
evenAndOdd(Tail, LOdd, LEven).
答案 1 :(得分:3)
代码不是最佳的一个征兆是,如果您要求在-,+,+实例化模式中寻求其他解决方案,它将陷入困境:
?- evenAndOdd(X, [[1,3,5], [2,4,6]]).
X = [1, 2, 3, 4, 5, 6] ;
<time passes>
在Prolog中手动尝试将列表与索引匹配时,这种情况经常发生。
从风格上讲,当我只有三个参数而不是两个参数时,我不希望返回一个仅包含两个列表的列表。毕竟,这是三个列表,组合列表以及偶数和奇数项之间的关系。
此外,只是盯着它,我不确定为什么这里需要任何算术或任何削减。这就是我的实现方式:
evenAndOdd([], [], []).
evenAndOdd([O], [O], []).
evenAndOdd([O,E|Rest], [O|ORest], [E|ERest]) :- evenAndOdd(Rest, ORest, ERest).
这适用于许多实例:
?- evenAndOdd([1,2,3,4,5,6], O, E).
O = [1, 3, 5],
E = [2, 4, 6].
?- evenAndOdd([1,2,3,4,5], O, E).
O = [1, 3, 5],
E = [2, 4] ;
false.
?- evenAndOdd(X, [1,3,5], [2,4]).
X = [1, 2, 3, 4, 5] ;
false.
?- evenAndOdd(X, [1,3,5], [2,4,6]).
X = [1, 2, 3, 4, 5, 6].
?- evenAndOdd(X, [1,3,5], [2,4,6,8]).
false.
?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6,8]).
false.
?- evenAndOdd([1,2,3,4,5,6], X, [2,4,6]).
X = [1, 3, 5].