Get all sets of list in prolog - prolog

How can I generate all the possible sets of the elements of a list with current length?
?- get_set(X, [1,2,3]).
X = [1,1,1] ;
X = [1,1,2] ;
X = [1,1,3] ;
X = [1,2,1] ;
X = [1,2,2] ;
X = [1,2,3] ;
X = [1,3,1] ;
X = [1,3,2] ;
X = [1,3,3] ;
.....
X = [3,3,2] ;
X = [3,3,3].
UPD: there is good answer given by Sharky.
But maybe it's not the best. Here is another:
get_set(X,L) :- get_set(X,L,L).
get_set([],[],_).
get_set([X|Xs],[_|T],L) :- member(X,L), get_set(Xs,T,L).

Consider:
get_set(L0, L) :-
length(L, Len),
length(L0, Len),
apply_elem(L0, L).
apply_elem([], _).
apply_elem([X|Xs], L) :-
member(X, L),
apply_elem(Xs, L).
Explanation:
Determining the length of the input list L as Len allows us to generate a list of unique variables, L0, via length/2. Then, we simply apply elements of L to all members of L0 via member/2, which leaves choicepoints for options, should they exist (i.e., if the list L is of length > 1). Prolog will backtrack to generate all possible combinations of elements of L into the list L0, as required.

Based on library predicate same_length/2, we can make it work safely in "both" directions!
Simply define get_set/2 like this, using meta-predicate maplist/2:
get_set(Xs,Ys) :-
same_length(Xs,Ys),
maplist(list_member(Ys),Xs).
list_member(Xs,X) :-
member(X,Xs).
First, the sample query suggested by the OP:
?- get_set(Xs,[1,2,3]).
Xs = [1,1,1] ;
Xs = [1,1,2] ;
Xs = [1,1,3] ;
Xs = [1,2,1] ;
Xs = [1,2,2] ;
Xs = [1,2,3] ;
Xs = [1,3,1] ;
Xs = [1,3,2] ;
Xs = [1,3,3] ;
Xs = [2,1,1] ;
Xs = [2,1,2] ;
Xs = [2,1,3] ;
Xs = [2,2,1] ;
Xs = [2,2,2] ;
Xs = [2,2,3] ;
Xs = [2,3,1] ;
Xs = [2,3,2] ;
Xs = [2,3,3] ;
Xs = [3,1,1] ;
Xs = [3,1,2] ;
Xs = [3,1,3] ;
Xs = [3,2,1] ;
Xs = [3,2,2] ;
Xs = [3,2,3] ;
Xs = [3,3,1] ;
Xs = [3,3,2] ;
Xs = [3,3,3] ;
false. % terminates universally
Let's try the other way round!
?- get_set([1,2,3],Ys).
Ys = [1,2,3] ;
Ys = [1,3,2] ;
Ys = [2,1,3] ;
Ys = [3,1,2] ;
Ys = [2,3,1] ;
Ys = [3,2,1] ;
false. % terminates universally

Related

How to obtain ALL the combinations with repetition of the elements of a list - prolog

I'm trying to get all the combinations with repetition of all the elements in a list L . These elements need to be returned in a size N list. (L, N, CWR).
The expected result would be something like:
?-([red,blue,green], 2 , X).
X = [red, red] ;
X = [red, blue] ;
X = [red, green] ;
X = [blue, blue] ;
X = [blue, green] ;
X = [blue, red] ;
X = [green, green] ;
X = [green, blue] ;
X = [green, red] ;
false.
Taking a higher-level view:
combinations_( L, N, R) :-
length( R, N),
maplist( flip(member,L), R).
flip( P, L, X):- call(P, X, L).
We just create a list of length N and fill it up with all the elements of L one after another.
I first saw flip on RosettaCode's Zebra Puzzle page.
This works in SWI-Prolog:
all_combos(_, 0, []).
all_combos(L, N, [H|T]) :-
length([H|T], N),
N1 is N - 1,
member(H, L),
all_combos(L, N1, T).
This is a good start :
?- [user] .
% consulting user_input...
:- op(2'1,'yfx','of') .
(
_yO_ of _Xs_
)
:-
(
(
[] = _Xs_ ;
)
;
(
[_yO_|_xS_] = _Xs_
)
;
(
[_|_xS_] = _Xs_ ,
_yO_ of _xS_
)
)
.
%^D%
% consulting user_query...
?-
_Xs_ = ['red','green','blue'] ,
_pO_ of _Xs_ ,
_qO_ of _Xs_ ,
Ys = [_pO_,_qO_] .
Ys = [red,red] ? ;
Ys = [red,green] ? ;
Ys = [red,blue] ? ;
Ys = [red,_qO_] ? ;
Ys = [green,red] ? ;
Ys = [green,green] ? ;
Ys = [green,blue] ? ;
Ys = [green,_qO_] ? ;
Ys = [blue,red] ? ;
Ys = [blue,green] ? ;
Ys = [blue,blue] ? ;
Ys = [blue,_qO_] ? ;
Ys = [_pO_,red] ? ;
Ys = [_pO_,green] ? ;
Ys = [_pO_,blue] ? ;
Ys = [_pO_,_qO_] ? ;
false
?-

Extra Outputs when using _

I have the following code:
pick_even([], []).
pick_even([_, H | T], [H | R]) :-
pick_even(T, R).
pick_even([_, H , _ | T], [H | R]) :-
pick_even(T, R).
When running the query, ?- pick_even(L,[4,7])., I want to receive the output:
L = [_7650, 4, _7662, 7] ;
L = [_7650, 4, _7662, 7, _7674] ;
Instead I am receiving some extra outputs that I do not want:
L = [_7650, 4, _7662, 7] ;
L = [_7650, 4, _7662, 7, _7674] ;
L = [_7650, 4, _7662, _7668, 7] ;
L = [_7650, 4, _7662, _7668, 7, _7680].
How can I eliminate these extra outputs without modifying the query?
I'm brand new to prolog, so I expect this to be a very easy syntax fix.
list_evens([], []).
list_evens([_|Es], Fs) :-
list_evens2(Es, Fs).
list_evens2([], []).
list_evens2([E|Es], [E|Fs]) :-
list_evens(Es, Fs).
That is, you forgot in particular the case of a one-element list.
And, for testing, the best way is to take the most general query:
?- list_even(Xs, Ys).
Xs = [], Ys = []
; Xs = [_A], Ys = []
; Xs = [_A,_B], Ys = [_B]
; Xs = [_A,_B,_C], Ys = [_B]
; Xs = [_A,_B,_C,_D], Ys = [_B,_D]
; Xs = [_A,_B,_C,_D,_E], Ys = [_B,_D]
; Xs = [_A,_B,_C,_D,_E,_F], Ys = [_B,_D,_F]
; ... .
In this manner you say:
Oh Prolog, why should I figure out what cases are of interest? Please do this for me!
And, diligently, Prolog will fill out the blanks. So you only need to ensure that all the answers you expect are here.

recursive Prolog predicate?

i am currently working on a project and i want to implement helper predicate in Prolog
break_down(N, L)
which works as follows
?- break_down(1,L).
L = [1] ;
false.
?- break_down(4,L).
L = [1, 1, 1, 1] ;
L = [1, 1, 2] ;
L = [1, 3] ;
L = [2, 2] ;
L = [4] ;
false.
and so on for any positive integer N .
i have tried and implemented a code which generates only the first result and i cannot get the rest of the results , and this is my code
break_down(1,[1]).
break_down(N,L):-
N>0,
N1 is N-1,
break_down(N1,L1),
append(L1,[1],L).
which generates only the first output result :
L = [1, 1, 1, 1] ;
any suggestion how to edit my code to get the rest ?
Here's a straight-forward recursive implementation using plain integer arithmetic and backtracking:
break_down(N,L) :-
break_ref_down(N,1,L). % reference item is initially 1
break_ref_down(0,_,[]).
break_ref_down(N,Z0,[Z|Zs]) :-
between(Z0,N,Z), % multiple choices
N0 is N-Z,
break_ref_down(N0,Z,Zs). % pass on current item as reference
Sample query:
?- break_down(8,Zs).
Zs = [1,1,1,1,1,1,1,1]
; Zs = [1,1,1,1,1,1,2]
; Zs = [1,1,1,1,1,3]
; Zs = [1,1,1,1,2,2]
; Zs = [1,1,1,1,4]
; Zs = [1,1,1,2,3]
; Zs = [1,1,1,5]
; Zs = [1,1,2,2,2]
; Zs = [1,1,2,4]
; Zs = [1,1,3,3]
; Zs = [1,1,6]
; Zs = [1,2,2,3]
; Zs = [1,2,5]
; Zs = [1,3,4]
; Zs = [1,7]
; Zs = [2,2,2,2]
; Zs = [2,2,4]
; Zs = [2,3,3]
; Zs = [2,6]
; Zs = [3,5]
; Zs = [4,4]
; Zs = [8]
; false.
Here's an implementation based on clpfd.
:- use_module(library(clpfd)).
As the predicate break_downFD/2 is non-recursive, the code is both readable and simple:
break_downFD(N,Zs) :-
length(Max,N), % multiple choices
append(_,Zs,Max),
Zs ins 1..N,
sum(Zs,#=,N),
chain(Zs,#=<), % enforce sequence is non-descending
labeling([],Zs). % multiple choices, possibly
Sample query using SWI-Prolog:
?- break_downFD(6,Zs).
Zs = [1,1,1,1,1,1]
; Zs = [1,1,1,1,2]
; Zs = [1,1,1,3]
; Zs = [1,1,2,2]
; Zs = [1,1,4]
; Zs = [1,2,3]
; Zs = [2,2,2]
; Zs = [1,5]
; Zs = [2,4]
; Zs = [3,3]
; Zs = [6]
; false.

Prolog. Fill out lists

I have to fill out a list of length n digits.
I know that n-1 is in the range from 1 to 9, and one digit can be in the range from 1 to 99.
I did it this way:
generate([First|Next],Czynniki):-
between(1,99,First),
generate2(Next).
generate2(Next):-
sublist([1,2,3,4,5,6,7,8,9],Next).
sublist([],[]).
sublist([H|T],[H|S]):-
sublist(T,S).
sublist([_|T],S):-
sublist(T,S).
Doing it this way I generate some of the same solutions.
Maybe you have some idea ​​how I can generate lists without repetition?
Edit
For the sake of clarity, I (#repeat) have added the following relevant comment by the OP:
At the entrance I have list of length N of undefined variables. And want fill out my list: N-1 numbers from the interval 1-9 and one number in the range 1-99.
Example: N=5, L=[56,2,3,4,8] ...
Use clpfd!
:- use_module(library(clpfd)).
Let's define digits10plusdigit100_n/2 like this:
digits10plusdigit100_n(Zs,N) :-
Zs = [CentDigit|DecDigits],
length(Zs,N),
CentDigit in 1..99,
DecDigits ins 1..9,
labeling([],Zs).
Sample queries:
?- digits10plusdigit100_n(Zs,1).
Zs = [1]
; Zs = [2]
; Zs = [3]
...
; Zs = [98]
; Zs = [99]
; false.
?- digits10plusdigit100_n(Zs,3).
Zs = [1,1,1]
; Zs = [1,1,2]
; Zs = [1,1,3]
...
; Zs = [1,2,1]
; Zs = [1,2,2]
...
; Zs = [1,9,8]
; Zs = [1,9,9]
; Zs = [2,1,1]
; Zs = [2,1,2]
...
; Zs = [2,1,3]
; Zs = [2,1,4]
...
; Zs = [98,9,9]
; Zs = [99,1,1]
; Zs = [99,1,2]
...
; Zs = [99,9,8]
; Zs = [99,9,9]
; false.
maybe change to between(10,99,X)
so reverse your predicates, generate numbers less then 10 and then generate last variable wich will be greater then 10
Isn't this just a variation of what #false very elegantly did in here ?
gen(Xs) :-
between(1, 9, L),
length(Xs, L),
maplist(between(1,99), Xs).
?- gen(Xs).
Xs = [1] ;
Xs = [2] ;
Xs = [3] ;
Xs = [4] ;
Xs = [5] ;
..
Xs = [99] ;
Xs = [1, 1] ;
Xs = [1, 2] ;
Xs = [1, 3] ;
Xs = [1, 4] ;
..
Xs = [1, 98] ;
Xs = [1, 99] ;
Xs = [2, 1] ;
Xs = [2, 2] ;
Xs = [2, 3] ;
Xs = [2, 4] ;
Xs = [2, 5] ;
Xs = [2, 6] ;

Reversing Part of a List in Prolog

My goal for this Prolog function is as follows:
Given two lists, x and y, return true if y can be formed from x by reversing a contiguous part of list x.
For example, if the input is x = [1, 3, 2, 4], y = [1, 2, 3, 4], the result should be "true" because we can reverse the second and third elements of x to get y.
I really have no idea, and I need some help!
Here's a straight-forward implementation using SICStus Prolog 4.3.1:
:- use_module(library(lists)).
list_singlePartReversed(Xs,Ys) :-
same_length(Xs,Ys), % Xs and Ys are lists w/the same length
dif(Xs,Ys), % Xs and Ys are not equal
append(Prefix ,Xs0 ,Xs), % Xs and Ys have common prefix
append(Prefix ,Ys0 ,Ys),
append(Part ,Suffix,Xs0), % Xs and Ys have common suffix
append(Reversed,Suffix,Ys0),
reverse(Part,Reversed). % the rest of Xs is reversed in Ys
Now on to some sample queries... First, the original query you posted in the question:
?- list_singlePartReversed([1,3,2,4], [1,2,3,4]).
yes
Next, a simple case we expect to fail:
?- list_singlePartReversed([1,4,3,2],[]).
no
What about all possible ways to do the reversal?
?- list_singlePartReversed([1,2,3,4], Xs).
Xs = [2,1,3,4] ? ;
Xs = [3,2,1,4] ? ;
Xs = [4,3,2,1] ? ;
Xs = [1,3,2,4] ? ;
Xs = [1,4,3,2] ? ;
Xs = [1,2,4,3] ? ;
no
What if the first argument is not instantiated but the second one is?
?- list_singlePartReversed(Xs, [1,2,3,4]).
Xs = [2,1,3,4] ? ;
Xs = [3,2,1,4] ? ;
Xs = [4,3,2,1] ? ;
Xs = [1,3,2,4] ? ;
Xs = [1,4,3,2] ? ;
Xs = [1,2,4,3] ? ;
no
And what about the most general query? Do we get a fair enumeration of the infinite solution set?
?- list_singlePartReversed(Xs,Ys).
Xs = [_A,_B], Ys = [_B,_A], prolog:dif([_A,_B],[_B,_A]) ? ;
Xs = [_A,_B,_C], Ys = [_B,_A,_C], prolog:dif([_A,_B,_C],[_B,_A,_C]) ? ;
Xs = [_A,_B,_C], Ys = [_C,_B,_A], prolog:dif([_A,_B,_C],[_C,_B,_A]) ? ;
Xs = [_A,_B,_C], Ys = [_A,_C,_B], prolog:dif([_A,_B,_C],[_A,_C,_B]) ? ;
Xs = [_A,_B,_C,_D], Ys = [_B,_A,_C,_D], prolog:dif([_A,_B,_C,_D],[_B,_A,_C,_D]) ? ...
Algorithmically, you can compare both from index 0, and find where they differ (call this index "a"), and compare backwards from n, until they differ (call this index "b").
Then reverse from index "a" to index "b" in one list, and compare the lists (or sub-list, it doesn't matter) to see if they are the same. If so, then true, otherwise false.
A corner case would be when both lists are identical. This could be be defined as either true or false, depending on whether a null set counts as a contiguous part of a list.
Search forward for mismatch:
[1,2,3,4]
[1,3,2,4]
^-------a
Search backward for mismatch:
[1,2,3,4]
[1,3,2,4]
^-----b
Reverse sub-list from a to b in either list:
[1,3,2,4] <-- Reversed sub-list indexed from 1-2
[1,3,2,4]
If equal, then true.
Does that help? This assumes that there is a single reversed sub-list.
This is a Prologish way you can do it:
rev(X,Y) :-
append(X1,X2,X3),
append(X3,X4,X),
reverse(X2,X5),
append(X1,X5,X6),
append(X6,X4,Y),
!.
Examples:
?- rev([1,3,2,4],[1,2,3,4]).
true.
?- rev([1,4,3,2],[1,2,3,4]).
true.

Resources