Prolog: How to generate simple math expressions? - prolog

I need to write (not calculate) all the states of list of number that means :
Input:
Numbers: 1,2,3
Operators: +,-,/,*
Output:
1+2+3
1-2-3
1/2/3
1*2*3
1+2-3
1+2/3
1+2*3
1-2+3
1-2/3
1-2*3
1/2+3
1/2-3
1/2+3
1*2+3
1*2-3
1+2-3
in descend code just show 1+2+3
How can I develop them to all states?
list_sum([Item], Item).
list_sum([Item1,Item2 | Tail], Total) :-
list_sum([Item1+Item2|Tail], Total).

A variation of the nice solution posted by Carlo Capelli allows us to illustrate an useful programming idiom to better exploit first-argument indexing:
list_combine([N1| Ns], Os, Nt) :-
list_combine(Ns, N1, Os, Nt).
list_combine([], N, _, [N]).
list_combine([N2| Ns], N1, Os, [N1, O| Nt]) :-
member(O, Os),
list_combine(Ns, N2, Os, Nt).
The idea is to pass the list we want to walk by separating the list head from the tail and pass both as argument with the tail as first argument, as exemplified above.
In the original solution, the Prolog compiler will generally not distinguish between a list with just one element and a list with one or more elements. But it will distinguish between an empty list (an atom) and a list with at least one element (a compound term). Note also that the original version creates a spurious choice-point, for each recursive call, on the call to the list_combine/3 predicate in addition to the intended choice-point on the member/2 predicate call.

a simple recursion:
list_combine([N|Nr],Os,[N,O|Nt]) :-
member(O,Os),
list_combine(Nr,Os,Nt).
list_combine([N],_,[N]).
and now
?- forall(list_combine([1,2,3],[+,*],C),writeln(C)).
[1,+,2,+,3]
[1,+,2,*,3]
[1,*,2,+,3]
[1,*,2,*,3]
true.
here is a - maybe - more readable version
list_combine(Ns,Os,Cs) :-
[N|Nr] = Ns,
member(O,Os),
Cs = [N,O|Nt],
list_combine(Nr,Os,Nt).
Of course, use in alternative, just to better understand how unification acts in decomposing and composing arguments.

Using DCG with phrase/2 as a generator:
operator --> [+].
operator --> [-].
operator --> [*].
operator --> [/].
expr_trinary -->
[1],
operator,
[2],
operator,
[3].
expr(E) :-
phrase(expr_trinary,Expr_trinary),
atomics_to_string(Expr_trinary,E).
Example run:
?- expr(E).
E = "1+2+3" ;
E = "1+2-3" ;
E = "1+2*3" ;
E = "1+2/3" ;
E = "1-2+3" ;
E = "1-2-3" ;
E = "1-2*3" ;
E = "1-2/3" ;
E = "1*2+3" ;
E = "1*2-3" ;
E = "1*2*3" ;
E = "1*2/3" ;
E = "1/2+3" ;
E = "1/2-3" ;
E = "1/2*3" ;
E = "1/2/3".
Since your question works with list, a way to see DCG as list processing is to use listing/1 to convert it to regular Prolog.
?- listing(operator).
operator([+|A], A).
operator([-|A], A).
operator([*|A], A).
operator([/|A], A).
true.
?- listing(expr_trinary).
expr_trinary([1|A], B) :-
operator(A, C),
C=[2|D],
operator(D, E),
E=[3|B].
true.
which can be called as regular Prolog.
?- expr_trinary(E,[]).
E = [1, +, 2, +, 3] ;
E = [1, +, 2, -, 3] ;
E = [1, +, 2, *, 3] ;
E = [1, +, 2, /, 3] ;
E = [1, -, 2, +, 3] ;
E = [1, -, 2, -, 3] ;
E = [1, -, 2, *, 3] ;
E = [1, -, 2, /, 3] ;
E = [1, *, 2, +, 3] ;
E = [1, *, 2, -, 3] ;
E = [1, *, 2, *, 3] ;
E = [1, *, 2, /, 3] ;
E = [1, /, 2, +, 3] ;
E = [1, /, 2, -, 3] ;
E = [1, /, 2, *, 3] ;
E = [1, /, 2, /, 3].
An expanded solution using a number (1,2,3) in any position:
number --> [1].
number --> [2].
number --> [3].
operator --> [+].
operator --> [-].
operator --> [*].
operator --> [/].
expr_trinary -->
number,
operator,
number,
operator,
number.
expr(E) :-
phrase(expr_trinary,Expr_trinary),
atomics_to_string(Expr_trinary,E).
Example run:
?- expr(E).
E = "1+1+1" ;
E = "1+1+2" ;
E = "1+1+3" ;
E = "1+1-1" ;
E = "1+1-2" ;
E = "1+1-3" ;
...
For a explanation of how to generate with DCG see this Amzi section: Generating with Difference Lists
In comment for other answer you wrote:
its not work more than 3 element? can you develop it for more elements?
As the number of elements increases so does the combinatorial explosion.
To keep the combinatorial explosion down for the example run this will only use two numbers (1,2) and two operators (+,*), you can add more to your liking.
number(1) --> [1].
number(2) --> [2].
operator(+) --> [+].
operator(*) --> [*].
expr(N) --> number(N).
expr((E1,Op,E2)) --> operator(Op),expr(E1),expr(E2).
expr(E) :-
length(Expr,_),
phrase(expr(E),Expr).
Note that this uses length/2 for iterative deepening. Basically length/2 generates list of increasing length and then phrase/2 comes up with answers that are of that length.
?- length(Ls,N).
Ls = [],
N = 0 ;
Ls = [_870],
N = 1 ;
Ls = [_870, _876],
N = 2 ;
Ls = [_870, _876, _882],
N = 3 ;
Ls = [_870, _876, _882, _888],
N = 4 ;
Ls = [_870, _876, _882, _888, _894],
N = 5 ;
Ls = [_870, _876, _882, _888, _894, _900],
N = 6
...
So that generator works as expected the normal BNF and DCG, e.g.
<expr> ::= <expr> <op> <expr>
expr((E1,Op,E2)) --> expr(E1),operator(Op),expr(E2).
which is direct left recursive is converted to this
<expr> ::= <op> <expr> <expr>
expr((E1,Op,E2)) --> operator(Op),expr(E1),expr(E2).
Example run:
?- expr(E).
E = 1 ;
E = 2 ;
E = (1, (+), 1) ;
E = (1, (+), 2) ;
E = (2, (+), 1) ;
E = (2, (+), 2) ;
E = (1, (*), 1) ;
E = (1, (*), 2) ;
E = (2, (*), 1) ;
E = (2, (*), 2) ;
E = (1, (+), 1, (+), 1) ;
...
E = (1, (+), 2, (+), 2, (*), 1) ;
E = (1, (+), 2, (+), 2, (*), 2) ;
E = (1, (+), (1, (+), 1), (+), 1) ;
E = (1, (+), (1, (+), 1), (+), 2) ;
E = (1, (+), (1, (+), 2), (+), 1) ;
...

One way is
get_calcul([X], _, Temp, Calcul):-
append(Temp, [X], Calcul).
get_calcul([N|T], [Op|Top], Temp, Out) :-
append(Temp, [N, Op], Temp1),
get_calcul(T, Top, Temp1, Out).
all_operations(In, Out) :-
setof(Op, X^Ops^(permutation([+,-,*,/], X), get_calcul(In, X, [], Ops), atomic_list_concat(Ops, Op)), Out).
Result
?- all_operations([1,2,3], Out).
Out = ['1*2+3', '1*2-3', '1*2/3', '1+2*3', '1+2-3', '1+2/3', '1-2*3', '1-2+3', '1-2/3'|...].
Well, I solved my problem, not your's !
This can be done :
member_(In, X) :-
member(X, In).
get_calcul([N], _, Temp, Out) :-
append(Temp, [N], Out).
get_calcul([N|T], [Op|Top], Temp, Out) :-
append(Temp, [N, Op], Temp1),
get_calcul(T, Top, Temp1, Out).
all_operations(In, Out) :-
% if you have N numbers
length(In, Len),
% you need N-1 operators
LenOps is Len - 1,
length(LOps, LenOps),
setof(Op, LOps^Ops^(maplist(member_([+,-,*,/]), LOps),get_calcul(In, LOps, [], Ops), atomic_list_concat(Ops, Op)), Out).
For example :
?- all_operations([1,2,3], Out), maplist(writeln, Out).
1*2*3
1*2+3
1*2-3
1*2/3
1+2*3
1+2+3
1+2-3
1+2/3
1-2*3
1-2+3
1-2-3
1-2/3
1/2*3
1/2+3
1/2-3
1/2/3
Out = ['1*2*3', '1*2+3', '1*2-3', '1*2/3', '1+2*3', '1+2+3', '1+2-3', '1+2/3', '1-2*3'|...].

This my solution proposal, which I find to be very simple and straight forward, copy and paste below to notepad++ editor to get best readability.
* ________________________________________________ *
*|find_expression(NumsList,TargetValue,Expression)| *
**------------------------------------------------* *
* Expression is an arithmetic expression of the numbers in Numslist with *
* possible operators '+','-','*','/' and '(' and ')' between the numbers *
* in such a way that the expression evaluates to the TargetValue argument *
*****************************************************************************/%
/* a single element number list can evaluate only to itself */
find_expression([SingleNumber],SingleNumber,SingleNumber).
/* expression of a multypile number list */
find_expression(NumberList,Target,Expression):-
/* non-deterministically divide the number list
into 2 separate lists which include at least one number each*/
append([X|Xs],[Y|Ys], NumberList),
/* recursively find an expression for east list,
where the expression evaluates to itself */
find_expression([X|Xs],Exp1,Exp1),
find_expression([Y|Ys],Exp2,Exp2),
/* non-deterministically choose an operand from [+,-,*,division]
and compose Expression to be (Exp1 Operand Exp2) */
( member(Expression,[Exp1+Exp2,Exp1-Exp2,Exp1*Exp2])
; /* prevent zero divison */
(Val2 is Exp2, Val2 =\= 0, Expression = (Exp1/Exp2))), %/*
/* assure that final expression evaluates(matches) the target value
and convert value from integer to float if necessary */
( Target = Expression ; Target is Expression
; FloatTarget is Target*1.0, FloatTarget is Expression).

Related

Prolog unification doesn't evaluate arithmetic expression

Suppose, I wanted to write a program in prolog, which accepts a number input X, and outputs all value pairs for which the sum is X.
some_pred(X,X1,X2) :-
X1 + X2 = X.
This does not work, because X1 + X2 is not evaluated arithmetically.
some_pred(X,X1,X2) :-
Xtemp is X1 + X2,
Xtemp = X.
The other option I have also doesn't work, because X1 and X2 are not instantiated.
How would someone solve this?
Yes, unification doesn't evaluate arithmetic expressions, and if it did that wouldn't help you because X1 and X2 are undefined so adding them together is meaningless.
You need either to write a search yourself such as a brute force nested loop:
sum_a_b(X, A, B) :-
between(1, X, A),
between(1, X, B),
X is A + B.
Or a more nuanced one where you encode something about arithmetic into it, start with 1+(X-1) and then (2+X-2), etc:
sum_a_b(X, A, B) :-
between(0, X, A),
B is X - A.
Or more generally, learn about clpfd (link1, link2) which can do arithmetic evaluating and solving for missing variables in equations, as well as searching through finite domains of possible values:
:- use_module(library(clpfd)).
sum_a_b(X, A, B) :-
[A, B] ins 1..X,
X #= A + B.
? sum_a_b(5, A, B), label([A, B]).
A = 1,
B = 4 ;
A = 2,
B = 3 ;
...
NB. I'm assuming positive integers, otherwise with negatives and decimals you'll get infinite pairs which sum to any given X.
Here's something very similar, using a list:
pos_ints_sum(Sum, L) :-
compare(C, Sum, 1),
pos_ints_sum_(C, L, Sum).
% 0 means the list has ended
pos_ints_sum_(<, [], 0).
% 1 means there is only 1 possible choice
pos_ints_sum_(=, [1], 1).
pos_ints_sum_(>, [I|T], Sum) :-
% Choose a number within the range
between(1, Sum, I),
% Loop with the remainder
Sum0 is Sum - I,
pos_ints_sum(Sum0, T).
Result in swi-prolog:
?- pos_ints_sum(5, L).
L = [1, 1, 1, 1, 1] ;
L = [1, 1, 1, 2] ;
L = [1, 1, 2, 1] ;
L = [1, 1, 3] ;
L = [1, 2, 1, 1] ;
L = [1, 2, 2] ;
L = [1, 3, 1] ;
L = [1, 4] ;
L = [2, 1, 1, 1] ;
L = [2, 1, 2] ;
L = [2, 2, 1] ;
L = [2, 3] ;
L = [3, 1, 1] ;
L = [3, 2] ;
L = [4, 1] ;
L = [5].
Note: X is a poor choice of variable name, when e.g. Sum can easily be used instead, which has far more meaning.

Find all natural divisors of a number (with Prolog)

I want to create a predicate divisors(X,[Y]) which is true if
X>1 and Y is the list of all divisors of X starting with X and going down to 1.
What my code right now looks like:
divisors(1,[1]).
divisors(X,[Y,Z|Ys]) :-
X>0,
Y is X,
Y>Z,
divides(X,[Z|Ys]).
divides(X,[Y,Z|Ys]) :-
Y>Z,
0 is X mod Y,
divides(X,[Z|Ys]).
divides(X,[1]).
But there are several problems with it:
prolog returns an error if asked for the list (e.g. ?-divisors(10,X).)
?- divisors(X,[Y]). Where [Y] is an incomplete list of divisors is true...
Edit by Guy Coder
This answer is by the OP and was posted in a comment below.
Moving here so others can see it.
divisors(X,R) :-
X > 1,
divisors(X,1,[],R).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0).
divides(N,D) :-
0 is N mod D.
Op also noted some errors in this version:
It doesn't terminate if I ask a wrong statement like (10,[1,2,3]).
It throws an error if I ask a statement like (X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
While the answer by William is nice and probably faster here is answer closer to what you were writing.
divides(N,D) :-
0 is N mod D.
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(N,D,R0,R0) :-
\+ divides(N,D).
divisors(_,0,R,R).
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 - 1,
divisors(N,D,R1,R).
divisors(X,R) :-
X > 1,
divisors(X,X,[],R), !.
Example:
?- between(1,15,N), divisors(N,Rs).
N = 2,
Rs = [1, 2] ;
N = 3,
Rs = [1, 3] ;
N = 4,
Rs = [1, 2, 4] ;
N = 5,
Rs = [1, 5] ;
N = 6,
Rs = [1, 2, 3, 6] ;
N = 7,
Rs = [1, 7] ;
N = 8,
Rs = [1, 2, 4, 8] ;
N = 9,
Rs = [1, 3, 9] ;
N = 10,
Rs = [1, 2, 5, 10] ;
N = 11,
Rs = [1, 11] ;
N = 12,
Rs = [1, 2, 3, 4, 6, 12] ;
N = 13,
Rs = [1, 13] ;
N = 14,
Rs = [1, 2, 7, 14] ;
N = 15,
Rs = [1, 3, 5, 15].
Edit
OP modified their code, see update in question and had some errors.
This version resolves those errors.
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
divisors(X,D,R,R):-
D>X.
divisors(N,D0,R0,R) :-
divisors_0(N,D0,R0,R1),
D is D0 + 1,
divisors(N,D,R1,R).
divisors_0(N,D,R0,[D|R0]) :-
divides(N,D).
divisors_0(_,_,R0,R0).
divides(N,D) :-
0 is N mod D.
The first error: It doesn't terminate if I ask a wrong statement like divisors(10,[1,2,3]).
is fixed by adding to divisors/2
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
and
divisors_2(_,[]).
divisors_2(X,[H|T]) :-
divides(X,H),
divisors_2(X,T).
which just processes the list of denominators instead of generating a list.
The second error: It throws an error if I ask a statement like divisors(X, [10,5,2,1]). (-> Arguments are not sufficiently initialized.)
is resolved by further adding to divisor/2
divisors(X,R) :-
(
var(X)
->
false
;
(
var(R)
->
X > 1,
divisors(X,1,[],R)
;
divisors_2(X,R), !
)
).
which checks if the first parameter X is a variable and if so just returns false. The other option would be to generate an infinite list of answers. While possible it wasn't requested.
In Prolog, it is quite common to use backtracking and propose multiple solutions to the same query. Instead of constructing a list of dividers, we thus can construct a predicate that unifies the second parameter with all divisors. For example:
divisor(N, D) :-
between(1, N, D),
0 is N mod D.
This then yields:
?- divisor(12, N).
N = 1 ;
N = 2 ;
N = 3 ;
N = 4 ;
N = 6 ;
N = 12.
The above algorithm is an O(n) algorithm: we scan for divisors linear with the value of the item for which we want to obtain the divisors. We can easily improve this to O(√n) by scanning up to √n, and each time yield both the divisor (of course in case it is a divisor), and the co-divisor, like:
emitco(D, _, D).
emitco(D, C, C) :-
dif(D, C).
divisor(N, R) :-
UB is floor(sqrt(N)),
between(1, UB, D),
0 is N mod D,
C is N / D,
emitco(D, C, R).
This still yield the correct answers, but the order is like a convergent alternating sequence:
?- divisor(12, N).
N = 1 ;
N = 12 ;
N = 2 ;
N = 6 ;
N = 3 ;
N = 4.
?- divisor(16, N).
N = 1 ;
N = 16 ;
N = 2 ;
N = 8 ;
N = 4 ;
false.
We can obtain a list of the divisors by using a findall/3 [swi-doc] or setof/3 [swi-doc]. The setof/3 will even sort the divisors, so we can implement divisors/2 in terms of divisor/2:
divisors(N, Ds) :-
setof(D, divisor(N, D), Ds).
For example:
?- divisors(2, N).
N = [1, 2].
?- divisors(3, N).
N = [1, 3].
?- divisors(5, N).
N = [1, 5].
?- divisors(12, N).
N = [1, 2, 3, 4, 6, 12].
?- divisors(15, N).
N = [1, 3, 5, 15].
We can use reverse/2 to reverse that result.

Prolog: why my predicate returns false?

so I wrote a predicate that counts how many times an element occurs in a list of lists.
count([], _, 0). #base case
count([[Elem|Rest]|OtherLists], Elem, Count) :- #Elem is the head of sublist
!,
count([Rest|OtherLists], Elem, NewCount),
succ(NewCount, Count).
count([[_|Rest]|OtherLists], Elem, Count) :- #Elem is not the head of sublist
count([Rest|OtherLists], Elem, Count).
count([[]|OtherLists], Elem, Count) :- #Head sublist is an empty list
count(OtherLists, Elem, Count).
Now that if I query the predicate with the following:
count([[1,2,3],[4,1,5],[4,6,1]], 1, X).
it returns X = 3, which is correct, but it will also say 'false' if I continue with the query.
So it counts elements correctly, but I cannot use this predicate inside other predicates since it eventually returns FALSE.
What am I doing wrong?
When Prolog encounters a "choice point" (a place in the code where it can come back to seek more possible solutions) in the process of finding a solution, it will show the solution and prompt you for more possible solutions. If it finds no more, it displays "false". This is not any kind of error in your logic. It's the way Prolog works.
It is not always desirable to remove the choice point. It depends upon what your goals are for the predicate. The danger in removing choice points using cuts is that the choice point may be a path to valid alternative solutions, and the cut prevents your program from finding those solutions.
Let's try your updated program with the new proposed cut in your answer:
| ?- count([[1,2,3],[4,1,5],[4,6,1]], 1, X).
X = 3
yes
| ?- count([[1,2,1,3],[4,1,5],[4,6,1]], 1, X).
X = 4
yes
| ?- count([[1,2,1,3],[4,1,5],[4,6,1],[1]], 1, X).
X = 5
So far, so good. These look like complete and correct answers. I believe your additional cut (and including your original cut) will yield a correct answer as long as the first argument is fully bound with no variables. Let's try a more interesting query:
2 ?- count([[A,2,B],[C,1,D]], 1, X).
A = B, B = C, C = D, D = 1,
X = 5.
3 ?-
The predicate found one solution. However, aren't there more? What about this one?
A = _ % something other than 1
B = C, C = D, D = 1,
X = 4.
This would be a correct solution as well, but the predicate fails to find it.
Also, what about this query?
2 ?- count([[1,2,1,3],[4,1,5],[4,6,1],[1]], E, X).
E = 1,
X = 5.
3 ?-
Again, only one solution found. But aren't there more? What about E = 4 and X = 2?
If we remove all of the cuts from the original predicate in an attempt to get all of the correct solutions, then we get incorrect solutions as well:
2 ?- count([[1,2],[3,1,4],[1]], 1,X).
X = 3 ;
X = 2 ;
X = 2 ;
X = 1 ;
X = 2 ;
X = 1 ;
X = 1 ;
X = 0 ;
false.
2 ?- count([[1,2,1,3],[4,1,5],[4,6,1],[1]], E, X).
E = 1,
X = 5 ;
E = 1,
X = 4 ;
E = 1,
X = 3 ;
...
So if more generality is desired, a more effective solution needs to be constructed.
count_occurrences_lol([], _, 0).
count_occurrences_lol([List|Lists], X, Count) :-
count_occurrences(List, X, C1), % Count occurrences in this list
count_occurrences_lol(Lists, X, C2), % Count occurrences in remaining sublists
Count is C1 + C2. % Total the counts
count_occurrences([], _, 0).
count_occurrences([X|Xs], X, Count) :-
count_occurrences(Xs, X, C1),
Count is C1 + 1.
count_occurrences([X1|Xs], X, Count) :-
dif(X1, X),
count_occurrences(Xs, X, Count).
Now we get the following:
3 ?- count_occurrences_lol([[1,2],[3,1,4],[1]], 1,X).
X = 3 ;
false.
Just one solution, as expected. And the following:
5 ?- count_occurrences_lol([[A,2,B],[C,1,3]], 1, X).
A = B, B = C, C = 1,
X = 4 ;
A = B, B = 1,
X = 3,
dif(C, 1) ;
A = C, C = 1,
X = 3,
dif(B, 1) ;
A = 1,
X = 2,
dif(B, 1),
dif(C, 1) ;
B = C, C = 1,
X = 3,
dif(A, 1) ;
B = 1,
X = 2,
dif(A, 1),
dif(C, 1) ;
C = 1,
X = 2,
dif(A, 1),
dif(B, 1) ;
X = 1,
dif(A, 1),
dif(B, 1),
dif(C, 1) ;
false.
3 ?- count_occurrences_lol([[1,2,1,3],[4,1,5],[4,6,1],[1]], E, X).
E = 1,
X = 5 ;
E = 2,
X = 1 ;
E = 3,
X = 1 ;
E = 4,
X = 2 ;
E = 5,
X = 1 ;
E = 6,
X = 1 ;
X = 0,
dif(E, 1),
dif(E, 1),
dif(E, 6),
dif(E, 4),
dif(E, 5),
dif(E, 1),
dif(E, 4),
dif(E, 3),
dif(E, 1),
dif(E, 2),
dif(E, 1).
4 ?-
Several possible solutions as expected.
Ok, it looks like it was backtracking on the part where 'Elem is not the head of sublist', and I was able to fix it by changing it to:
count([[_|Rest]|OtherLists], Elem, Count) :- #Elem is not the head of sublist
!,
count([Rest|OtherLists], Elem, Count).
If anyone can confirm whether this is a correct solution. Thanks

SWI-Prolog Delete items that have pair occurrences

I need a solution that deletes elements that have pairs of occurrences from list.
I did it in haskell, but i don't have any ideas how to interpretate it in Prolog.
For example [1,2,2,2,4,4,5,6,6,6,6] -> [1,2,2,2,5]
Code in Haskell :
import Data.List
count e list = length $ filter (==e) list
isnotEven = (== 1) . (`mod` 2)
removeUnique :: [Int] -> [Int]
removeUnique list = filter (\x -> isnotEven (count x list) ) list
The following follows your Haskell code.
You need library(reif) for SICStus|SWI.
:- use_module(reif).
oddcount_t(List, E, T) :- % reified: last argument is truth value
tfilter(=(E), List, Eqs),
length(Eqs, Nr),
M is Nr mod 2,
=(M, 1, T).
removeevenocc(List, RList) :-
tfilter(oddcount_t(List), List, RList).
?- removeevenocc([1,2,2,2,4,4,5,6,6,6,6], R).
R = [1,2,2,2,5].
?- removeevenocc([1,X], R).
X = 1, R = []
; R = [1, X],
dif(X, 1).
Note the last question. Here, the list was not entirely given: The second element is left unknown. Therefore, Prolog produces answers for all possible values of X! Either X is 1, then the resulting list is empty, or X is not 1, then the list remains the same.
this snippet uses some of the libraries (aggregate,lists,yall) available, as well as some builtins, like setof/3, and (=:=)/2:
?- L=[1,2,2,2,4,4,5,6,6,6,6],
| setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds),
| foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = [1, 2, 2, 2, 4, 4, 5, 6, 6|...],
Ds = [4, 6],
R = [1, 2, 2, 2, 5].
edit
to account for setof/3 behaviour (my bug: setof/3 fails if there are no solutions), a possible correction:
?- L=[1],
(setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds);Ds=[]),
foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = R, R = [1],
Ds = [].
Now there is a choice point left, the correct syntax could be
?- L=[1],
(setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds)->true;Ds=[]),
foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = R, R = [1],
Ds = [].

printing pairs of a list in SWI-prolog

basically, I want to print pairs from one list like this
?- [1 2 3 4 5,R]
the output is
R = [1, 2]
R = [1, 3]
R = [1, 4]
R = [1, 5]
R = [2, 3]
R = [2, 4]
R = [2, 5]
R = [3, 4]
R = [3, 5]
R = [4, 5]
I used the code that creates subsets and modified it
sub(0,_,[]).
sub(N,[X|T],[X|R]):-N>0,N1 is N-1,sub(N1,T,R).
sub(N,[_|T],R):-N>0,sub(N,T,R).
and I would call
sub(2,[1,2,3,4,5],R)
but is there a way to do it without using a counter?
Prolog is about defining relations (in the form of rules) and to try to avoid thinking procedurally (steps of execution to achieve a result). You can solve this by breaking it down into simple rules for the pairs:
For a list with head H and tail T, a valid pair is [H,E] where E is a member of T.
For a list with head H and tail T, a valid pair is a pair taken from T.
If you think about these rules, they are (1) mutually exclusive (there isn't a solution that matches both rules), and (2) they are complete (they cover all of the valid solutions).
Writing these in Prolog, you get:
pair([H|T], [H,E]) :- member(E, T).
pair([_|T], P) :- pair(T, P).
This provides a relational solution which yields:
| ?- sub([a,b,c,d], S).
S = [a,b] ? ;
S = [a,c] ? ;
S = [a,d] ? ;
S = [b,c] ? ;
S = [b,d] ? ;
S = [c,d] ? ;
(1 ms) no
| ?-
And works in a more general case:
| ?- pair(L, P).
L = [A,B]
P = [A,B] ? ;
L = [A,B|_]
P = [A,B] ? ;
L = [A,_,B|_]
P = [A,B] ? ;
L = [A,_,_,B|_]
P = [A,B] ? ;
...
an easy way:
?- L = [1,2,3,4,5], forall((nth1(I,L,X), nth1(J,L,Y), I<J), writeln(I/J)).
1/2
1/3
1/4
1/5
2/3
2/4
2/5
3/4
3/5
4/5
L = [1, 2, 3, 4, 5].
Yes, there is, since you don't have to account for subsets of arbitrary length.
There are two steps you need to account for, and both have two variants.
Select the first element of the pair:
Use the head of the list
Discard the head and pick it out of the tail of the list
Select the second element of the pair:
Use the head of the list
Discard the head and pick it out of the tail of the list
% Use the head as the first element
pairs((H, P2), [H | T]) :- pairs((H, P2), T).
% If we have the first element, use the head as the second element
pairs((P1, H), [H | _]) :- nonvar(P1).
% Ignore the head and pick what we need out of the tail
pairs(P, [_ | T]) :- pairs(P, T).

Resources