【问题标题】:Prolog: Split list at integer in list of listsProlog:在列表列表中以整数拆分列表
【发布时间】:2015-01-20 13:50:00
【问题描述】:

我想将通过整数分隔的单词列表拆分为列表列表。

示例查询和预期结果:

?- separatewords([h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e], X).
X = [[h,e,l,l,o],[o,v,e,r],[t,h,e,r,e]].

我已经实现了以下几点: 将列表拆分为第一个整数之前的一个列表和第一个整数之后的一个列表:

带有结果的示例查询:

?- take1word([h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e], X, Y).
X = [h,e,l,l,o], Y = [o,v,e,r,3,t,h,e,r,e].                 % OK

我的代码:

 take1word([H|T],[],T) :-
    integer(H).
 take1word([H|T],[H|Hs],Y) :-
    (  float(H), take1word(T,Hs,Y)
    ;  atom(H), take1word(T,Hs,Y)
    ).

为了分隔单词,我的代码如下:

 separatewords([],[]).
 separatewords([H|T],L) :-  separatewords(T,[take1word([H|T],)|L]).

结果它只给我false,但我不知道,我做错了什么。

【问题讨论】:

    标签: list recursion split prolog


    【解决方案1】:

    以下是您如何以逻辑上纯的方式进行操作。

    splitlistIf/3与具体的类型测试谓词integer_t/2结合使用!

    integer_t(X,Truth) :- integer(X), !, Truth = true.
    integer_t(X,Truth) :- nonvar(X),  !, Truth = false.
    integer_t(X,true)  :- freeze(X,  integer(X)).
    integer_t(X,false) :- freeze(X,\+integer(X)).
    

    让我们看看他们俩的行动吧!

    ?- Xs=[ h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e ], splitlistIf(integer_truth,Xs,Yss)。 Xs = [ h,e,l,l,o,1,o,v,e,r,3,t,h,e,r,e ], Yss = [[h,e,l,l,o],[o,v,e,r],[t,h,e,r,e]]。 % 确定性地成功

    由于实现是单调的,当我们使用非基本术语时可以安全地使用它。

    考虑以下两个逻辑上等效的查询:在程序上,在目标 splitListIf(integer_t,Xs,Yss) 被证明时,它们在 Xs 中的项目的实例化方面有所不同。

    ?- Xs = [_,_,_,_,_], Xs = [a,b,0,b,a], splitlistIf(integer_t,Xs,Yss)。 Xs = [a,b,0,b,a], Yss = [[a,b],[b,a]]。 % 确定性地成功 ?- Xs = [_,_,_,_,_], splitlistIf(integer_t,Xs,Yss), Xs = [a,b,0,b,a]。 Xs = [a,b,0,b,a], Yss = [[a,b],[b,a]] % 成功留下选择点 ;错误的。

    该实现足够聪明,仅在必要时才留下选择点。

    【讨论】:

    • Related 到名称查找。
    • CamelCase 不是很 Prolog-ish。 int 不是类型。 integer_truth/2。没有必要引用实例化状态 (Nonvar):没有约束的实现将完全正确地产生实例化错误。
    • 首先要看的是地面案例。除了整数还有什么可以是偶数?自然数,但它们不是显式类型。而作为域是not_less_than_zero。所以even_truth 对我来说已经足够好了。另一方面,您的大多数定义都接受 0+0 之类的表达式
    • 好点!我可以/应该怎么做?类型测试+异常?或者更确切地说将clpfd_monotonic 标志与(?)/1 结合使用?
    【解决方案2】:

    take1word/3 有问题:如果列表中有整数,它会占用一个单词,但不会占用最后一个单词。您需要为其添加另一个基本子句:

    take1word([], [], []).
    take1word([H|T],[],T) :- integer(H).
    take1word([H|T],[H|Hs],Y) :- float(H), take1word(T,Hs,Y); atom(H), take1word(T,Hs,Y).
    

    现在你的separatewords/2 可以工作了:

    separatewords([],[]).
    separatewords(L, [W|T]) :- take1word(L,W,R), separatewords(R,T).
    

    Demo.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 2012-03-21
      • 1970-01-01
      • 2016-01-08
      • 1970-01-01
      相关资源
      最近更新 更多