在Prolog

时间:2016-10-23 05:48:21

标签: prolog

美好的一天,

我有一个任务,如果给出一个列表[3,9,11,2,14],我想过滤掉任何大于6的值。我现在就有效。

sift([],[]).
sift([X|T], [X|Result]):-
    X > 6,                         /* is X greater than 6 */
    write(isList(Result)),
    /* append([X]|['CCC'], [Result]), but this didn't work */
    sift(T,Result).                /* if so then go find the rest */
sift([ThrowAway|Tail],Result):-    /* disregard the head */
    sift(Tail,Result).             /* and look in the tail */ 

正如我前面提到的,这会返回正确的结果。我的困境是,如果一个大于6的值,我想添加' CCC'的额外值。在符合条件的号码之后。所以它看起来像:

[9,CCC,11,CCC,14,CCC]。

我试图写出列表的内容,但是当我这样做时,我得到了值:

12 ?- sift([3,9,11,2,14], Results).
isList(_G2271)isList(_G2276)isList(_G2281)
Results = [9, 11, 14].
13 ?- 

我试图检查列表的内容以查看它是什么。

有没有人对如何做到这一点有任何想法?

TIA,

COSON

1 个答案:

答案 0 :(得分:1)

添加append([X]|['CCC'], [Result])时的问题是您实例化Result=[X,'CCC']。您不只是将'CCC'添加到Result,而是将[X]附加到['CCC'],结果就是结果列表(所以Result=[X,'CCC'])。之后,当您致电sift(T,Result)时。结果已完全实例化,因此添加元素将返回false。

还有另一个问题,查询?- sift([3,9,11,2,14], Results).给出:

?- sift([3,9,11,2,14], Results).
isList(_G1296)isList(_G1301)isList(_G1306)
Results = [9, 11, 14] ;
Results = [9, 11] ;
isList(_G1301)
Results = [9, 14] ;
Results = [9] ;
isList(_G1296)isList(_G1301)
Results = [11, 14] ;
Results = [11] ;
isList(_G1296)
Results = [14] ;
Results = [].

由于您的第三个子句与所有输入案例匹配,因此它提供了很多列表。要解决此问题,您可以在第三个子句中添加X=<6

最后你可以写:

sift([],[]). 
sift([X|T],[X,'CCC'|Result]):-X > 6,sift(T,Result).
sift([ThrowAway|Tail],Result):-ThrowAway=<6,sift(Tail,Result). 

解决了这两个问题。在您的示例中:

?- sift([3,9,11,2,14], Results).
Results = [9, 'CCC', 11, 'CCC', 14, 'CCC'] ;
false.