在 Prolog 中分离列表
Segregating Lists in Prolog
我很难理解如何让我的代码显示由偶数和奇数组成的隔离列表。我什至不确定我的理解缺乏什么。显然我是这种语言的新手,必须在学校使用它。我的命令式和功能性思维不会让我知道这个笑到底是怎么回事。
现在,不,我不是要你做我的作业!我只是请你帮我看看我缺乏理解的是什么。我也查找了类似的答案,但我无法将它们转换为我应该编写此函数的方式。
再一次,请不要 bash 我像以前那样被 bash 教育。请帮我看看我的理解有什么不足。请不要只给我答案和代码片段而不解释。
这里是:
is_even(H) :-
0 is mod(H, 2).
segregate(List, Even, Odd) :- segregator(List, Even, Odd).
segregator([], [], []).
segregator([H|T], E, O) :-
is_even(H),
% I feel here is where I am supposed to build the list,
% but I have no clue how since Even or Odd has not been unified.
segregator(T, E, O),
write('Even is '), write(E), nl.
segregator([H|T], E, O) :-
% Same here as above.
segregator(T, E, O),
write('Odd is '), write(O), nl.
一个逻辑上纯的实现非常简单,感谢clpfd:
:- use_module(library(clpfd)).
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],[X|Es],Os) :-
X mod 2 #= 0,
list_evens_odds(Xs,Es,Os).
list_evens_odds([X|Xs],Es,[X|Os]) :-
X mod 2 #= 1,
list_evens_odds(Xs,Es,Os).
一些示例 我们期望成功的查询(具有有限的答案序列):
?- Xs = [1,2,3,4,5,6,7], list_evens_odds(Xs,Es,Os).
Xs = [1,2,3,4,5,6,7],
Es = [ 2, 4, 6 ],
Os = [1, 3, 5, 7] ;
false.
?- list_evens_odds(Ls,[2,4],[1,3]).
Ls = [2,4,1,3] ? ;
Ls = [2,1,4,3] ? ;
Ls = [2,1,3,4] ? ;
Ls = [1,2,4,3] ? ;
Ls = [1,2,3,4] ? ;
Ls = [1,3,2,4] ? ;
no
我们预计会失败的查询呢?
?- list_evens_odds(Ls,[2,4,5],[1,3]).
no
?- list_evens_odds(Ls,[2,4],[1,3,6]).
no
?- list_evens_odds([_,_,_],[2,4],[1,3]).
no
最后,最一般的查询:
?- assert(clpfd:full_answer).
yes
?- list_evens_odds(Ls,Es,Os).
Ls = [], Es = [], Os = [] ? ;
Ls = [_A], Es = [_A], Os = [], _A mod 2#=0, _A in inf..sup ? ...
编辑 2015-05-06
这是另一种方法 logical-purity!
将元谓词 tpartition/4
与 zeven_t/2
或 zodd_t/2
一起使用。
bool01_t(1,true).
bool01_t(0,false).
zeven_t(Z,Truth) :- Z mod 2 #= 0 #<==> B, bool01_t(B,Truth).
%zodd_t(Z,Truth) :- Z mod 2 #= 1 #<==> B, bool01_t(B,Truth).
zodd_t(Z,Truth) :- Z mod 2 #= B, bool01_t(B,Truth). % tweaked
zeven_t/2
具体化了整数的偶数,zodd_t/2
奇数.
一切就绪,让我们运行一些查询!
?- tpartition(zeven_t,[1,2,3,4,5,6,7],Es,Os).
Es = [2,4,6], Os = [1,3,5,7].
?- tpartition(zodd_t ,[1,2,3,4,5,6,7],Os,Es). % argument order differs
Es = [2,4,6], Os = [1,3,5,7].
两者都确定性地成功。使用 list_evens_odds/3
的等效查询不会。
我很难理解如何让我的代码显示由偶数和奇数组成的隔离列表。我什至不确定我的理解缺乏什么。显然我是这种语言的新手,必须在学校使用它。我的命令式和功能性思维不会让我知道这个笑到底是怎么回事。
现在,不,我不是要你做我的作业!我只是请你帮我看看我缺乏理解的是什么。我也查找了类似的答案,但我无法将它们转换为我应该编写此函数的方式。
再一次,请不要 bash 我像以前那样被 bash 教育。请帮我看看我的理解有什么不足。请不要只给我答案和代码片段而不解释。
这里是:
is_even(H) :-
0 is mod(H, 2).
segregate(List, Even, Odd) :- segregator(List, Even, Odd).
segregator([], [], []).
segregator([H|T], E, O) :-
is_even(H),
% I feel here is where I am supposed to build the list,
% but I have no clue how since Even or Odd has not been unified.
segregator(T, E, O),
write('Even is '), write(E), nl.
segregator([H|T], E, O) :-
% Same here as above.
segregator(T, E, O),
write('Odd is '), write(O), nl.
一个逻辑上纯的实现非常简单,感谢clpfd:
:- use_module(library(clpfd)).
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],[X|Es],Os) :-
X mod 2 #= 0,
list_evens_odds(Xs,Es,Os).
list_evens_odds([X|Xs],Es,[X|Os]) :-
X mod 2 #= 1,
list_evens_odds(Xs,Es,Os).
一些示例 我们期望成功的查询(具有有限的答案序列):
?- Xs = [1,2,3,4,5,6,7], list_evens_odds(Xs,Es,Os).
Xs = [1,2,3,4,5,6,7],
Es = [ 2, 4, 6 ],
Os = [1, 3, 5, 7] ;
false.
?- list_evens_odds(Ls,[2,4],[1,3]).
Ls = [2,4,1,3] ? ;
Ls = [2,1,4,3] ? ;
Ls = [2,1,3,4] ? ;
Ls = [1,2,4,3] ? ;
Ls = [1,2,3,4] ? ;
Ls = [1,3,2,4] ? ;
no
我们预计会失败的查询呢?
?- list_evens_odds(Ls,[2,4,5],[1,3]).
no
?- list_evens_odds(Ls,[2,4],[1,3,6]).
no
?- list_evens_odds([_,_,_],[2,4],[1,3]).
no
最后,最一般的查询:
?- assert(clpfd:full_answer).
yes
?- list_evens_odds(Ls,Es,Os).
Ls = [], Es = [], Os = [] ? ;
Ls = [_A], Es = [_A], Os = [], _A mod 2#=0, _A in inf..sup ? ...
编辑 2015-05-06
这是另一种方法 logical-purity!
将元谓词 tpartition/4
与 zeven_t/2
或 zodd_t/2
一起使用。
bool01_t(1,true).
bool01_t(0,false).
zeven_t(Z,Truth) :- Z mod 2 #= 0 #<==> B, bool01_t(B,Truth).
%zodd_t(Z,Truth) :- Z mod 2 #= 1 #<==> B, bool01_t(B,Truth).
zodd_t(Z,Truth) :- Z mod 2 #= B, bool01_t(B,Truth). % tweaked
zeven_t/2
具体化了整数的偶数,zodd_t/2
奇数.
一切就绪,让我们运行一些查询!
?- tpartition(zeven_t,[1,2,3,4,5,6,7],Es,Os). Es = [2,4,6], Os = [1,3,5,7]. ?- tpartition(zodd_t ,[1,2,3,4,5,6,7],Os,Es). % argument order differs Es = [2,4,6], Os = [1,3,5,7].
两者都确定性地成功。使用 list_evens_odds/3
的等效查询不会。