首先,我会尽量避免使用reverse/2。如果您有这样的解决方案,通常表明有更好的方法可以更直接地获得答案。并非总是如此,但最常见的是。 reverse/2 可能是 Prolog 中第二个最喜欢的创可贴,仅次于使用剪辑。 :)
在许多问题中,都需要一个辅助蓄能器。在这种特殊情况下,它不是。此外,在涉及整数时,我倾向于使用 CLP(FD) 运算,因为它是对整数进行推理的更相关的方法。但是,如果您愿意,可以将下面的解决方案与is/2 等一起使用。它只是不会那么普遍。
numbers(S, E, []) :- S #> E. % null case
numbers(X, X, [X]).
numbers(S, E, [S|T]) :-
S #< E,
S1 #= S + 1,
numbers(S1, E, T).
| ?- numbers(3, 8, L).
L = [3,4,5,6,7,8] ? ;
no
| ?- numbers(A, B, [2,3,4,5]).
A = 2
B = 5 ? ;
no
| ?-
这个解决方案避免了reverse/2并且是尾递归的。
要为奇数更新它,第一个想法是我们可以很容易地修改上面的内容,只需添加 2 而不是 1:
every_other_number(S, E, []) :- S #> E.
every_other_number(X, X, [X]).
every_other_number(S, E, [S|T]) :-
S #< E,
S1 #= S + 2,
every_other_number(S1, E, T).
| ?- every_other_number(3, 7, L).
L = [3,5,7] ? ;
no
| ?- every_other_number(3, 8, L).
L = [3,5,7] ? ;
no
| ?- every_other_number(4, 8, L).
L = [4,6,8] ? ;
no
| ?-
然后我们可以通过创建一个初始谓词来确保第一个值是奇数的条件并调用every_other_number/3来做奇数:
odd_numbers(S, E, L) :-
S rem 2 #= 1,
every_other_number(S, E, L).
odd_numbers(S, E, L) :-
S rem 2 #= 0,
S1 #= S + 1,
every_other_number(S1, E, L).
| ?- odd_numbers(2, 8, L).
L = [3,5,7] ? ;
no
| ?- odd_numbers(2, 9, L).
L = [3,5,7,9] ? ;
no
| ?- odd_numbers(3, 8, L).
L = [3,5,7] ? ;
no
| ?-