Check predicate

2019-08-28 17:20发布

问题:

I've a problem. I have 5 constants.

C(1).
C(2).
C(3).
C(4).
C(5).

And I've a predicate named "check" that receives two arguments.

Example:

check( [C(1), C(3), C(4), _, C(5)], ListFinal).

And now it should give me

ListFinal = [C(1), C(3), C(4), C(2), C(5)].

How do I do this? How to check for that black space to put there, the constant I haven't used? It is possible to change the implementation of the constants.

回答1:

You could try

check( []        , []        ) .
check( [c(X)|Xs] , [c(X)|Rs] ) :- c(X) , check(Xs,Rs) .

You might also look at findall/3.

You should note however, that your 'constants' aren't constants in prolog. The way you've written them they are are facts. And the ones you've listed aren't syntactically valid Prolog: The functor of a term must be either a bareword atom like c(3). or an atom enclosed in single quotes like 'C'(3). (though why anybody would voluntarily choose to do something like that is beyond me.)



回答2:

check(L, C) :-
    check(L, [], C).
check([], _, []).
check([c(X)|T], A, [c(X)|C]) :-
    c(X),
    \+ memberchk(c(X), A),
    check(T, [c(X)|A], C).

Some tests:

| ?- check([_, c(3), c(4), _, c(5)], ListFinal).

ListFinal = [c(1),c(3),c(4),c(2),c(5)] ? a

ListFinal = [c(2),c(3),c(4),c(1),c(5)]

no
| ?- check([c(1), c(3), c(4), _, c(5)], ListFinal).

ListFinal = [c(1),c(3),c(4),c(2),c(5)] ? a

no
| ?-


Here's a DCG approach:

remap([c(X)|T], A) --> {c(X), \+ memberchk(c(X), A)}, [c(X)], remap(T, [c(X)|A]).
remap([], _) --> [].

check(L, C) :- phrase(remap(L, []), C).


回答3:

once corrected the syntax, check each argument (easy to do with maplist/3)

check(In, Out) :-
  exclude(var, In, NoVars),
  maplist(check_var(NoVars), In, Out).

check_var(In, X, Y) :-
  var(X) -> c(Z), \+ memberchk(c(Z), In), Y = c(Z) ; Y = X.

usage example

1 ?- check([c(1),X,c(3),c(5)],L).
L = [c(1), c(2), c(3), c(5)] ;
L = [c(1), c(4), c(3), c(5)] ;
false.


标签: prolog