Prolog: “findall” for limited number of solutions

后端 未结 9 896
暖寄归人
暖寄归人 2020-12-06 17:36

Say I want to find sum of all solutions to a predicate, I just can use

findall(L, find(L), Sols),

and just sum members of Sols.

But

9条回答
  •  没有蜡笔的小新
    2020-12-06 18:20

    A portable solution in ISO Prolog:

    :- dynamic(find_n_solution/1).
    :- dynamic(find_n_counter/1).
    
    find_n(N, Term, Goal, Solutions) :-
        (   set_find_n_counter(N),
            retractall(find_n_solution(_)),
            once((
                call(Goal),
                assertz(find_n_solution(Term)),
                dec_find_n_counter(M),
                M =:= 0
            )),
            fail
        ;   findall(Solution, retract(find_n_solution(Solution)), Solutions)
        ).
    
    set_find_n_counter(N) :-
        retractall(find_n_counter(_)),
        assertz(find_n_counter(N)).
    
    dec_find_n_counter(M) :-
        retract(find_n_counter(N)),
        M is N - 1,
        assertz(find_n_counter(M)).
    

    Using the sample predicate find/1 @ChristianF answer:

    | ?- find_n(10, X, find(X), L).
    L = [0,1,2,3,4,5,6,7,8,9]
    yes
    

    Note that this solution will still return a list of solutions even if there are less than the required number of solutions. Some Prolog compilers, including B-Prolog and ECLiPSe provide non-logical global variables that can be used to implement the counter but that would make the solution non-portable.

提交回复
热议问题