Prolog count list elements higher than n

前端 未结 3 1304
谎友^
谎友^ 2020-12-21 06:21

I\'m kinda new to Prolog so I have a few problems with a certain task. The task is to write a tail recursive predicate count_elems(List,N,Count) condition

3条回答
  •  悲哀的现实
    2020-12-21 06:39

    Preserve logical-purity with clpfd!

    Here's how:

    :- use_module(library(clpfd)).
    
    count_elems([],_,0).
    count_elems([X|Xs],Z,Count) :-
       X #=< Z,
       count_elems(Xs,Z,Count).
    count_elems([X|Xs],Z,Count) :-
       X #> Z,
       Count #= Count0 + 1,
       count_elems(Xs,Z,Count0).
    

    Let's have a look at how versatile count_elems/3 is:

    ?- count_elems([1,2,3,4,5,4,3,2],2,Count).
    Count = 5 ;                                   % leaves useless choicepoint behind
    false.
    
    ?- count_elems([1,2,3,4,5,4,3,2],X,3).
    X = 3 ;
    false.
    
    ?- count_elems([1,2,3,4,5,4,3,2],X,Count).
    Count = 0, X in 5..sup ;
    Count = 1, X = 4       ;
    Count = 3, X = Count   ;
    Count = 5, X = 2       ;
    Count = 7, X = 1       ;
    Count = 8, X in inf..0 .
    

    Edit 2015-05-05

    We could also use meta-predicate tcount/3, in combination with a reified version of (#<)/2:

    #<(X,Y,Truth) :- integer(X), integer(Y), !, ( X Truth=true ; Truth=false ).
    #<(X,Y,true)  :- X #<  Y.
    #<(X,Y,false) :- X #>= Y.
    

    Let's run above queries again!

    ?- tcount(#<(2),[1,2,3,4,5,4,3,2],Count).
    Count = 5.                                           % succeeds deterministically
    
    ?- tcount(#<(X),[1,2,3,4,5,4,3,2],3).
    X = 3 ;
    false.
    
    ?- tcount(#<(X),[1,2,3,4,5,4,3,2],Count).
    Count = 8, X in inf..0 ;
    Count = 7, X = 1       ;
    Count = 5, X = 2       ;
    Count = 3, X = Count   ;
    Count = 1, X = 4       ; 
    Count = 0, X in 5..sup .
    

    A note regarding efficiency:

    • count_elems([1,2,3,4,5,4,3,2],2,Count) left a useless choicepoint behind.
    • tcount(#<(2),[1,2,3,4,5,4,3,2],Count) succeeded deterministically.

提交回复
热议问题