在Prolog中将整数列表拆分为子列表

时间:2019-03-22 08:09:21

标签: prolog

我只是在学习Prolog,我需要向函数提供一个包含正整数和负整数的列表,并且它应该返回子列表的列表,以便每个子列表仅包含连续的正数或仅包含连续的负数。我的意思是基于列表中存在的数字的符号,该功能应该破坏列表。

以下是输入和必需的输出:

f([],[]).
f([H|[]],L).
f([H,E|T],[[H,E|Tail1]|Tail]):-
    H >=0,
    E>=0,
    f(T,[[Tail1]|Tail]).

f([H,E|T],[[H]|Tail]) :-
    H>=0,
    E<0,
    f([E|T],Tail).

f([H,E|T],[[H,E|Tail1]|Tail]) :-
    H<0,
    E<0,
    f(T,[[Tail1]|Tail]).

f([H,E|T],[[H]|Tail]) :-
    H<0,
    E>=0,
    f([E|T],Tail).

到目前为止,我所取得的成就是:

{{1}}

运行上述功能时出现奇怪的跟踪。任何帮助都会很棒。谢谢:)

1 个答案:

答案 0 :(得分:1)

您可以使用fold/4拆分列表:

split(Input, LOutput):-
  foldl(addorsplit, Input, state(_Sgn, LOutput), state(_, [[]])).

sgn(Num, Sgn):-
  Sgn is sign(sign(Num)*2+1).

addorsplit(Item, state(Sgn, LOutput), state(NSgn, [Current|Tail])):-
  sgn(Item, NSgn),
  (Sgn = NSgn -> LOutput=[[Item|Current]|Tail] ; LOutput=[[],[Item|Current]|Tail]).

sgn/2是一个帮助程序,可以让0代表肯定。

示例查询:

?- split([1,2,-3,-4,5,0,7],L).
L = [[1, 2], [-3, -4], [5, 0, 7]]

使用clp(FD)将允许执行更多常规查询:

split2(Input, LOutput):-
  foldl(addorsplit2, Input, state(_Sgn, LOutput), state(_, [[]])).

sgn2(Num, 1):-
  Num #>= 0.
sgn2(Num, -1):-
  Num #< 0.

addorsplit2(Item, state(Sgn, LOutput), state(NSgn, [Current|Tail])):-
  sgn2(Item, NSgn),
  (Sgn #= NSgn -> LOutput=[[Item|Current]|Tail] ; LOutput=[[],[Item|Current]|Tail]).

现在您可以查询例如:

?- split2([X,1,-3,Y],L).
L = [[X, 1], [-3], [Y]],
X in 0..sup,
Y in 0..sup ;
;
L = [[X, 1], [-3, Y]],
X in 0..sup,
Y in inf.. -1 ;
;
L = [[X], [1], [-3], [Y]],
X in inf.. -1,
Y in 0..sup ;
;
L = [[X], [1], [-3, Y]],
X in inf.. -1,
Y in inf.. -1 ;