Fringo
Fringo

Reputation: 355

SWI ProLog / ProbLog: Check if exactly one element in a list is true

I'm trying to make a function in ProbLog (extension of ProLog) that checks if only one of the inputs is True. As input the function will take a list of variables as argument. An XOR is not good enough in this case, because I am working with more than two arguments and I want the function to be true if and only if one of the elements in the list is True.

So for example:

function([X|Xs) :- code that checks if only (exactly) one element in the list is true

Upvotes: 1

Views: 1437

Answers (2)

Felix Dombek
Felix Dombek

Reputation: 14372

I don't know about the Problog extension, but maybe you can simply count the true elements and check if the count is one? Perhaps using this as a starting point:

length(List, N) :-
  length(List, 0, N).

length([], N, N).       % Second argument is the accumulator.
length([H|T], L, N) :-
    L1 is L + 1,
    length(T, L1, N).

You would then add a case where L is not incremented if H is not true, and in the end check if N is one.

hasOneTrueElement(List) :-
    countTrueElements(List, 1).
countTrueElements(List, N) :-
    countTrueElements(List, 0, N).
countTrueElements([], N, N).
countTrueElements([H|T], L, N) :-
    call(H),
    L1 is L + 1,
    countTrueElements(T, L1, N).
countTrueElements([H|T], L, N) :-
    \+ H,
    countTrueElements(T, L, N).

Upvotes: 2

CapelliC
CapelliC

Reputation: 60024

this should work

list_unique(List, Unique) :-
  select(Unique, List, Rest), \+ memberchk(Unique, Rest).

Upvotes: 1

Related Questions