I want to implement a predicate P(Xs,Ys,Zs) where Xs,Ys,Zs are lists.
I'm new in Prolog and I can't find a way to get to the longest sequence in Xs (example. Xs = ['b','b','A','A','A','A','b','b']) which is included to Ys (for example Ys = ['A','A','A','A','c','A','A','A','A']) without crossing- an even number of times. Maybe someone already wrote this code ore some one can say me how can I start. Thanks for helps.
explanation of teacher.
longest_subsequence(List, Part, Subsequence):-
longest_subsequence_(List, Part, [], Subsequence).
longest_subsequence_(Xs, Ys, CurrentSubsequence, LongestSubsequence):-
append(CurrentSubsequence, Ys, NextSubsequence),
divide_list(Xs, [_LeftYs, NextSubsequence, _RightYs]), !,
longest_subsequence_(Xs, Ys, NextSubsequence, LongestSubsequence).
longest_subsequence_(_Xs, _Ys, LongestSubsequence, LongestSubsequence).
okey i did.
main_task(Xs, Ys, Zs) :-
atom_chars(Xs, Xl),
atom_chars(Ys, Yl),
retractall(record(_, _)),
assert(record(0, [])),
process(Xl, Yl, Zl),
atom_chars(Zs, Zl).
process(Xl, Yl, _) :-
get_sublist(Xl, Zl),
length(Zl, L),
record(MaxL, _),
L > MaxL,
get_index(Yl, Zl, Il),
test_even(Il),
test_intersect(Il, L),
retractall(record(_, _)),
assert(record(L, Zl)),
fail.
process(_, _, Zl) :-
record(_, Zl).
get_sublist(L1, L2) :-
get_tail(L1, L3),
get_head(L3, L2).
get_tail(L, L).
get_tail([_|T], L) :-
get_tail(T, L).
get_head([H|T1], [H|T2]) :-
get_head(T1, T2).
get_head(_, []).
get_index(Yl, Zl, Il) :-
get_index(Yl, Zl, Il, 0).
get_index([], _, [], _).
get_index([Yh|Yt], Zl, [I|It], I) :-
get_head([Yh|Yt], Zl),
!,
I1 is I + 1,
get_index(Yt, Zl, It, I1).
get_index([_|Yt], Zl, Il, I) :-
I1 is I + 1,
get_index(Yt, Zl, Il, I1).
test_even(Il) :-
length(Il, L),
L > 0,
L mod 2 =:= 0.
test_intersect([_], _).
test_intersect([X,Y|T], L) :-
Y - X >= L,
test_intersect([Y|T], L).
All lines in the list at the symbols on working with lists
Initialize the dynamic database - will be stored in it, and its maximum line length
enumerates all of the substring (sublists) from X. Bust goes double "pruning" - first place in a list of cut off the front, then from behind.
Check the length of the resulting string, if we already have a long, immediately leave for the continuation of busting
We consider a list of indexes in the occurrence of a Y, then there is every element of the list - a position in the Y, from which it includes Z.
Check the parity - just consider the length of the list of indexes, chёtnaya length - an even number of entries. And we need to check that it is greater than zero.
Check the intersection - you need to check the difference between two adjacent elements of the list of indexes, the difference should always be greater than the length Z.
If all checks are made, there is a dynamic database updates - current list Z is stored as the maximum
At the end it is a forced failure, it is rolled back to the fork in paragraph 3) and the continued search.
Note: If any check is not performed, the failure of this test is immediately rolled back to the fork in paragraph 3) and the continued search.
When the bust comes to an end, performed a second rule predicate process, it simply selects the last spicok Z in the base.
At the end of the list Z is converted back to a string
A naive approach is the following:
longest_subsequence(Xs,Ys,Zs) :-
longest_subsequence(Xs,Ys,Ys,0,[],Zs).
longest_subsequence([X|Xs],Y0,[Y|Ys],N0,Z0,Z) :-
try_seq([X|Xs],[Y|Ys],Nc,Zc),
(Nc > N0
-> longest_subsequence([X|Xs],Y0,Ys,Nc,Zc,Z)
; longest_subsequence([X|Xs],Y0,Ys,N0,Z0,Z)
).
longest_subsequence([_|Xs],Y0,[],N0,Z0,Z) :-
longest_subsequence(Xs,Y0,Y0,N0,Z0,Z).
longest_subsequence([],_,_,_,Z,Z).
try_seq([H|TA],[H|TB],N,[H|TC]) :-
!,
try_seq(TA,TB,N1,TC),
N is N1+1.
try_seq(_,_,0,[]).
here a predicate try_seq/3 aims to match as much as possible (generate the longest common subsequence) starting from the beginning of the list.
The problem is that this is a computationally expensive approach: it will have a time complexity O(m n p) with n the length of the first list, m the length of the second list and p the minimum length of the two lists.
Calling this with your example gives:
?- longest_subsequence([b,b,a,a,a],[a,a,a,c,a,a,a],Zs).
Zs = [a, a, a] ;
false.
You can make the algorithm more efficient using back-referencing, this is more or less based on the Knuth-Morris-Pratt-algorithm.
When approaching a problem, first try: divide and conquer.
When we have a list_subsequence(+List, ?Subsequence) predicate
list_subsequence([H|T], S) :-
list_subsequence(H, T, S, _).
list_subsequence([H|T], S) :-
list_subsequence(H, T, _, R),
list_subsequence(R, S).
list_subsequence(H, [H|T], [H|S], R) :- !, list_subsequence(H, T, S, R).
list_subsequence(H, R, [H], R).
we can call for library(aggregate) help:
longest_subsequence(Seq, Rep, Longest) :-
aggregate(max(L, Sub), N^(
list_subsequence(Seq, Sub),
aggregate(count, list_subsequence(Rep, Sub), N),
N mod 2 =:= 0,
length(Sub, L)
), max(_, Longest)).
edit: more library support available
A recently added library helps:
longest_subsequence_(Seq, Rep, Longest) :-
order_by([desc(L)], filter_subsequence(Seq, Rep, Longest, L)), !.
where filter_subsequence/4 is simply the goal of the outer aggregate:
filter_subsequence(Seq, Rep, Sub, L) :-
list_subsequence(Seq, Sub),
aggregate(count, list_subsequence(Rep, Sub), N),
N mod 2 =:= 0,
length(Sub, L).
Related
I'm having a hard time coming up with an efficient clause set for the following problem: given a list X find its maximum prefix consisting of same elements along with the remaining suffix. That is:
| ?- trim([a,a,a,b,b,c], [a,a,a], [b,b,c]).
yes
| ?- trim([a,a,a,a,b,b,c,c], X, Y).
X = [a,a,a,a],
Y = [b,b,c,c]
Here is what I have so far:
same([]).
same([_]).
same([X,X|T]) :- same([X|T]).
trim([], [], []).
trim(L, L, []) :- same(L).
trim(L, [A|B], [C|D]) :- append([A|B], [C|D], L), A \= C, same([A|B]).
The append part doesn't seem very efficient though. Is there a simple, iterative way to accomplish this?
Thinking about this problem from the start, we know we want the trivial case to be true:
trim([], [], []).
Then we want the longest repeated element prefix case:
trim([X], [X], []). % Trivial case
trim([X,Y|T], [X], [Y|T]) :- % Non-repeating element, ends recursion
dif(X, Y).
trim([X,X|T], [X|Xs], S) :- % Repeating element, recursive case
trim([X|T], Xs, S).
I'm trying to count the numer of inversions in a list. A predicate inversion(+L,-N) unifies N to the number of inversions in that list. A inversion is defined as X > Y and X appears before Y in the list (unless X or Y is 0). For example:
?- inversions([1,2,3,4,0,5,6,7,8],N).
N = 0.
?- inversions([1,2,3,0,4,6,8,5,7],N).
N = 3.
For what I'm using this for, the list will always have exacly 9 elements, and always containing the numbers 0-8 uniquely.
I'm quite new to Prolog and I'm trying to do this as concise and as elegant as possible; It seems like DCG will probably help a lot. I read into the official definition and some tutorial sites, but still don't quit understand what it is. Any help would be greatly appreciated.
Here is another solution that doesn't leave choice points using if_/3:
inversions([],0).
inversions([H|T], N):-
if_( H = 0,
inversions(T,N),
( find_inv(T,H,N1),inversions(T, N2), N #= N1+N2 )
).
find_inv([],_,0).
find_inv([H1|T],H,N1):-
if_( H1=0,
find_inv(T,H,N1),
if_( H#>H1,
(find_inv(T,H,N2),N1 #= N2+1),
find_inv(T,H,N1)
)
).
#>(X, Y, T) :-
( integer(X),
integer(Y)
-> ( X > Y
-> T = true
; T = false
)
; X #> Y,
T = true
; X #=< Y,
T = false
).
I'm not so sure a DCG would be helpful here. Although we're processing a sequence, there's a lot of examination of the entire list at each point when looking at each element.
Here's a CLPFD approach which implements the "naive" algorithm for inversions, so it's transparent and simple, but not as efficient as it could be (it's O(n^2)). There's a more efficient algorithm (O(n log n)) involving a divide and conquer approach, which I show further below.
:- use_module(library(clpfd)).
inversions(L, C) :-
L ins 0..9,
all_distinct(L),
count_inv(L, C).
% Count inversions
count_inv([], 0).
count_inv([X|T], C) :-
count_inv(X, T, C1), % Count inversions for current element
C #= C1 + C2, % Add inversion count for the rest of the list
count_inv(T, C2). % Count inversions for the rest of the list
count_inv(_, [], 0).
count_inv(X, [Y|T], C) :-
( X #> Y, X #> 0, Y #> 0
-> C #= C1 + 1, % Valid inversion, count it
count_inv(X, T, C1)
; count_inv(X, T, C)
).
?- inversions([1,2,3,4,0,5,6,7,8],N).
N = 0 ;
false.
?- inversions([1,2,3,0,4,6,8,5,7],N).
N = 3 ;
false.
?- inversions([0,2,X],1).
X = 1 ;
false.
It does leave a choice point, as you can see, which I haven't sorted out yet.
Here's the O(n log n) solution, which is using the sort/merge algorithm.
inversion([], [], 0).
inversion([X], [X], 0).
inversion([HU1, HU2|U], [HS1, HS2|S], C) :- % Ensure list args have at least 2 elements
split([HU1, HU2|U], L, R),
inversion(L, SL, C1),
inversion(R, SR, C2),
merge(SL, SR, [HS1, HS2|S], C3),
C #= C1 + C2 + C3.
% Split list into left and right halves
split(List, Left, Right) :-
split(List, List, Left, Right).
split(Es, [], [], Es).
split(Es, [_], [], Es).
split([E|Es], [_,_|T], [E|Ls], Right) :-
split(Es, T, Ls, Right).
% merge( LS, RS, M )
merge([], RS, RS, 0).
merge(LS, [], LS, 0).
merge([L|LS], [R|RS], [L|T], C) :-
L #=< R,
merge(LS, [R|RS], T, C).
merge([L|LS], [R|RS], [R|T], C) :-
L #> R, R #> 0 #<==> D, C #= C1+D,
merge([L|LS], RS, T, C1).
You can ignore the second argument, which is the sorted list (just a side effect if all you want is the count of inversions).
Here is another possibility to define the relation. First, #</3 and #\=/3 can be defined like so:
:- use_module(library(clpfd)).
bool_t(1,true).
bool_t(0,false).
#<(X,Y,Truth) :- X #< Y #<==> B, bool_t(B,Truth).
#\=(X,Y,Truth) :- X #\= Y #<==> B, bool_t(B,Truth).
Based on that, if_/3 and (',')/3 a predicate inv_t/3 can be defined, that yields true in the case of an inversion and false otherwise, according to the definition given by the OP:
inv_t(X,Y,T) :-
if_(((Y#<X,Y#\=0),X#\=0),T=true,T=false).
And subsequently the actual relation can be described like so:
list_inversions(L,I) :-
list_inversions_(L,I,0).
list_inversions_([],I,I).
list_inversions_([X|Xs],I,Acc0) :-
list_x_invs_(Xs,X,I0,0),
Acc1 #= Acc0+I0,
list_inversions_(Xs,I,Acc1).
list_x_invs_([],_X,I,I).
list_x_invs_([Y|Ys],X,I,Acc0) :-
if_(inv_t(X,Y),Acc1#=Acc0+1,Acc1#=Acc0),
list_x_invs_(Ys,X,I,Acc1).
Thus the example queries given by the OP succeed deterministically:
?- list_inversions([1,2,3,4,0,5,6,7,8],N).
N = 0.
?- list_inversions([1,2,3,0,4,6,8,5,7],N).
N = 3.
Such application-specific constraints can often be built using reified constraints (constraints whose truth value is reflected into a 0/1 variable). This leads to a relatively natural formulation, where B is 1 iff the condition you want to count is satisfied:
:- lib(ic).
inversions(Xs, N) :-
( fromto(Xs, [X|Ys], Ys, [_]), foreach(NX,NXs) do
( foreach(Y,Ys), param(X), foreach(B,Bs) do
B #= (X#\=0 and Y#\=0 and X#>Y)
),
NX #= sum(Bs) % number of Ys that are smaller than X
),
N #= sum(NXs).
This code is for ECLiPSe.
Using clpfd et automaton/8 we can write
:- use_module(library(clpfd)).
inversions(Vs, N) :-
Vs ins 0..sup,
variables_signature(Vs, Sigs),
automaton(Sigs, _, Sigs,
[source(s),sink(i),sink(s)],
[arc(s,0,s), arc(s,1,s,[C+1]), arc(s,1,i,[C+1]),
arc(i,0,i)],
[C], [0], [N]),
labeling([ff],Vs).
variables_signature([], []).
variables_signature([V|Vs], Sigs) :-
variables_signature_(Vs, V, Sigs1),
variables_signature(Vs, Sigs2),
append(Sigs1, Sigs2, Sigs).
variables_signature_([], _, []).
variables_signature_([0|Vs], Prev, Sigs) :-
variables_signature_(Vs,Prev,Sigs).
variables_signature_([V|Vs], Prev, [S|Sigs]) :-
V #\= 0,
% Prev #=< V #<==> S #= 0,
% modified after **false** remark
Prev #> V #<==> S,
variables_signature_(Vs,Prev,Sigs).
examples :
?- inversions([1,2,3,0,4,6,8,5,7],N).
N = 3 ;
false.
?- inversions([1,2,3,0,4,5,6,7,8],N).
N = 0 ;
false.
?- inversions([0,2,X],1).
X = 1.
in SWI-Prolog, with libraries aggregate and lists:
inversions(L,N) :-
aggregate_all(count, (nth1(P,L,X),nth1(Q,L,Y),X\=0,Y\=0,X>Y,P<Q), N).
both libraries are autoloaded, no need to explicitly include them.
If you want something more general, you can see the example in library(clpfd), under the automaton section, for some useful ideas. But I would try to rewrite your specification in simpler terms, using element/3 instead of nth1/3.
edit
after #false comment, I tried some variation on disequality operators, but none I've tried have been able to solve the problematic query. Then I tried again with the original idea, to put to good use element/3. Here is the result:
:- use_module(library(clpfd)).
inversions(L) :-
L ins 0..8,
element(P,L,X),
element(Q,L,Y),
X #\= 0, Y #\= 0, X #> Y, P #< Q,
label([P,Q]).
inversions(L,N) :-
aggregate(count, inversions(L), N) ; N = 0.
The last line label([P,Q]) it's key to proper reification: now we can determine the X value.
?- inversions([0,2,X],1).
X = 1.
I would like to get the middle element of a list in Prolog.
The predicates middle([1,2,3],M) and middle([1,2,3,4],M) should both return 2 as a result.
And I am allowed to use the predicate deleteLast.
I know that there are similar posts that solve that question but I have not found one that just uses deleteLast.
Even the syntax is not correct - however this is my solution so far:
middle([], _).
middle([X|XTail|Y], E) :-
1 is mod(list_length([X|XTail|Y], 2)),
middle([XTail], E).
middle([X|XTail|Y], E) :-
0 is mod(list_length([X|XTail|Y], 2)),
middle([X|XTail], E).
middle([X], X).
Question: Is that partly correct or am I completely on the wrong path ?
Sorry, the attempted solution you have is completely on the wrong path.
It doesn't use deleteLast/2 as you stated you require
You are using list_length/2 as if it were an arithmetic function, which it is not. It's a predicate.
You have a term with invalid syntax and unknown semantics, [X|XTail|Y]
In Prolog, you just need to think about it in terms of the rules. Here's an approach using deleteLast/2:
middle([X], X). % `X` is the middle of the single element list `[X]`
middle([X,_], X). % `X` is the middle of the two-element list `[X,_]`
% X is the middle of the list `[H|T]` if X is the middle of the list TWithoutLast
% where TWithoutLast is T with its last element removed
%
middle([H|T], X) :-
deleteLast(T, TWithoutLast),
middle(TWithoutLast, X).
I assume deleteLast/2 is well-behaved and just fails if T is empty.
You can also do this with same_length/2 and append/3, but, alas, doesn't use deleteLast/2:
middle(L, M) :-
same_length(L1, L2),
append(L1, [M|L2], L).
middle(L, M) :-
same_length(L1, L2),
append(L1, [M,_|L2], L).
So much unnecessary work, and unnecessary code. length/2 is very efficient, and a true relation. Its second argument is guaranteed to be a non-negative integer. So:
middle(List, Middle) :-
List = [_|_], % at least one element
length(List, Len),
divmod(Len, 2, Q, R), % if not available do in two separate steps
N is Q + R,
nth1(N, List, Middle).
And you are about ready:
?- middle(L, M), numbervars(L).
L = [A],
M = A ;
L = [A, B],
M = A ;
L = [A, B, C],
M = B ;
L = [A, B, C, D],
M = B ;
L = [A, B, C, D, E],
M = C ;
L = [A, B, C, D, E, F],
M = C .
I understand that this doesn't solve your problem (the answer by #lurker does) but it answers your question. :-(
Here is my attempt:
middle(L,M):- append(L1,L2,L),length(L1,N),length(L2,N), reverse(L1,[M|_]).
middle(L,M):- append(L1,L2,L),length(L1,N),length(L2,N1), N is N1+1 ,
reverse(L1,[M|_]).
Example:
?- middle([1,2,3],M).
M = 2 ;
false.
?- middle([1,2,3,4],M).
M = 2 ;
false.
In your implementation the problem is that by writing for example:
list_length([X|XTail|Y], 2)
The above does not give you as X the first element and as Y the last so I think it has some major problems...
As well pointed out by lurker you could write the above solution in one clause without using reverse/2:
middle(L, M) :- append(L1, [M|T], L), length(L1, N), length([M|T], N1),
(N1 is N + 1 ; N1 is N + 2).
Also to make the solution more relational (also see mat's comment below) you could use CLPFD library and replace is/2 with #= like:
middle(L, M) :- append(L1, [M|T], L), length(L1, N), length([M|T], N1),
(N1 #= N + 1 ; N1 #= N + 2).
Another interesting solution is to consider this predicate for splitting a list in half:
half(List, Left, Right) :-
half(List, List, Left, Right).
half(L, [], [], L).
half(L, [_], [], L).
half([H|T], [_,_|T2], [H|Left], Right) :-
half(T, T2, Left, Right).
This predicate divides an even list into two equal halves, or an odd list into two pieces where the right half has one more element than the left. It does so by reducing the original list, via the second argument, by two elements, each recursive call, while at the same time reducing the original list by one element each recursive call via the first argument. When it recurses down to the second argument being zero or one elements in length, then the first argument represents the half that's left, which is the right-hand list.
Example results for half/3 are:
| ?- half([a,b,c], L, R).
L = [a]
R = [b,c] ? a
(1 ms) no
| ?- half([a,b,c,d], L, R).
L = [a,b]
R = [c,d] ? a
no
| ?-
We can't quite use this to easily find the middle element because, in the even case, we want the last element of the left hand list. If we could bias the right-hand list by an extra element, we could then pick off the head of the right-hand half as the "middle" element. We can accomplish this using the deleteLast/2 here:
middle([X], X).
middle(List, Middle) :-
deleteLast(List, ListWithoutLast),
half(ListWithoutLast, _, [Middle|_]).
The head of the right half list of the original list, with the last element deleted, is the "middle" element. We can also simply half/3 and combine it with middle/2 since we don't really need everything half/3 does (e.g., we don't need the left-hand list, or the tail of the right hand list):
middle([X], X).
middle(List, Middle) :-
deleteLast(List, ListWithoutLast),
middle(ListWithoutLast, ListWithoutLast, Middle).
middle([M|_], [], M).
middle([M|_], [_], M).
middle([_|T], [_,_|T2], Right) :-
middle(T, T2, Right).
Another approach would be to modify half/3 to bias the splitting of the original list in half toward the right-hand half, which eliminates the need for using deleteLast/2.
modified_half(List, Left, Right) :-
modified_half(List, List, Left, Right).
modified_half(L, [_], [], L).
modified_half(L, [_,_], [], L).
modified_half([H|T], [_,_,X|T2], [H|Left], Right) :-
modified_half(T, [X|T2], Left, Right).
This will bias the right hand list to have an extra element at the "expense" of the left:
| ?- modified_half([a,b,c,d,e], L, R).
L = [a,b]
R = [c,d,e] ? a
no
| ?- modified_half([a,b,c,d,e,f], L, R).
L = [a,b]
R = [c,d,e,f] ? a
no
| ?-
Now we can see that the middle element, per the original definition, is just the head of the right hand list. We can create a new definition for middle/2 using the above. As we did before with half/3, we can ignore everything but the head in the right half, and we can eliminate the left half since we don't need it, and create a consolidated middle/2 predicate:
middle(List, Middle) :-
middle(List, List, Middle).
middle([M|_], [_,_], M).
middle([M|_], [_], M).
middle([_|T], [_,_,X|T2], Middle) :-
middle(T, [X|T2], Middle).
This reduces the original list down one element at a time (first argument) and two elements at a time (second argument) until the second argument is reduced to one or two elements. It then considers the head first argument to be the middle element:
This gives:
| ?- middle([a,b,c], M).
M = b ? ;
no
| ?- middle([a,b,c,d], M).
M = b ? ;
no
| ?- middle(L, M).
L = [M,_] ? ;
L = [M] ? ;
L = [_,M,_,_] ? ;
L = [_,M,_] ? ;
L = [_,_,M,_,_,_] ? ;
L = [_,_,M,_,_] ? ;
L = [_,_,_,M,_,_,_,_] ?
...
I need to finish a prolog exercise, I have half of it but I need something more to finish it, that is the reason I am asking for help.
What I need is an small prolog program, given two lists (L1, L2) and one position as P, insert the first list into the second one and store that list in a third list (L3).
insert_at(L1,L2,P,L3)
Here an example:
?- insert_at ([h1,h2], [a1,a2,a3,a4], 2,L3).
L3 = [a1,h1,h2,a2,a3,a4]
The code I have for this is this one:
remove_at(X,[X|Xs],1,Xs).
remove_at(X,[Y|Xs],K,[Y|Ys]) :-
K > 1,
K1 is K - 1,
remove_at(X,Xs,K1,Ys).
insert_at(X,L,K,R) :- remove_at(X,R,K,L).
What I get is this:
?- insert_at([h1,h2],[a1,a2,a3,a4],2,L3).
L3 = [a1, [h1, h2], a2, a3, a4] % What I get
L3 = [a1, h1, h2, a2, a3, a4] % What I really want
I dont know why I get the brackets inside the list...I dont want them as I explained up.
To finish it I also need to take care about more cases:
If P is higher than the second list lenght, L1 will be inserted at the end of L2.
If we insert a non-empty list in an empty list (no matters P), we will get the inserted list.
If we insert an empty list in a non-empty list (no matters P), we will get the non-empty list.
Thanks in advance
The quick-fix solution:
insert_at(X, L, K, R) :-
remove_at(X, R1, K, L),
flatten(R1, R).
The solution involving rewriting remove_at to manage a list:
remove_at([], Y, _, Y) :- !. % added as a list base case
remove_at(_, [], _, []) :- !. % added as a list base case
remove_at([X|T], [X|Xs], 1, L) :- % handle a list [X|T] instead of just X
remove_at(T, Xs, 1, L).
remove_at(X, [Y|Xs], K, [Y|Ys]) :- % same as before :)
K > 1,
K1 is K - 1,
remove_at(X, Xs, K1, Ys).
insert_at(X, L, K, R) :- remove_at(X, R, K, L).
The second remove_at/4 base case says that if the list I want to remove from is empty, then the result is empty and it succeeds. That means insert_at/4 will succeed if K is greater than the length of L and it will return the original list, L, as the solution.
If you want the insert_at/4 to succeed when K is greater than the length of the list and instantiate R with X appended to L (rather than just L itself), you can replace remove_at(_, [], _, []) :- !. with remove_at(X, X, _, []) :- !.
The best thing I could come up with so far is this function:
numberFromList([X], X) :-
digit(X), !.
numberFromList(List, N) :-
member(X, List),
delete(List, X, LX),
numberFromList(LX, NX),
N is NX * 10 + X.
where digit/1 is a function verifying if an atom is a decimal digit.
The numberFromList(List, N) finds all the numbers that can be formed with all digits from List.
E.g. [2, 3] -> 23, 32.
but I want to get this result: [2, 3] -> 2, 3, 23, 32
I spent a lot of hours thinking about this and I suspect you might use something like append(L, _, List) at some point to get lists of lesser length.
I would appreciate any contribution.
You are missing case when you skip digit from list.
numberFromList([X], X) :-
digit(X), !.
numberFromList(List, N) :-
member(X, List),
delete(List, X, LX),
numberFromList(LX, NX),
( % use X
N is NX * 10 + X
; % skip X
N = NX
).
BTW, as #Roland Illig mentioned there is select(X, List, LX) to replace member(X, List), delete(List, X, LX)
The predicate unique/3 generates all lists of length up to MaxLen consisting of symbols from Symbols. The generated lists are stored in L, once at a time.
unique(MaxLen, Symbols, L) :-
between(0, MaxLen, Len),
length(L, Len),
unique(Symbols, L).
The helper predicate for generating the lists.
unique(_, []).
unique(Set, [H|R]) :-
select(H, Set, ReducedSet),
unique(ReducedSet, R).
A simple program for demonstrating the above predicate:
main :-
unique(5, [2,3], L),
write(L), nl, fail.
Here's one way, using SWI-PROLOG built-ins for atomic_list_concat/2, atom_number/2 and select/3. Firstly, the entry point refers to an implementation using an initially empty accumulator:
numberFromList(L, N) :-
numberFromList(L, [], N).
The predicate numberFromList/3 either accumulates digits (unchecked) from the list, or not, leaving choicepoints:
numberFromList([_|Cs], Acc, N) :-
numberFromList(Cs, Acc, N).
numberFromList([C|Cs], Acc, N) :-
numberFromList(Cs, [C|Acc], N).
The final clause of numberFromList/3 permutes the accumulated list of digits and concatenates them into an atom, which is then converted to a number as required:
numberFromList([], [C|Cs], N) :-
permute([C|Cs], PermutedAcc),
atomic_list_concat(PermutedAcc, AN),
atom_number(AN, N).
Sometimes permute/2 (as defined manually below) may be available as a built-in, such as permutation/2. Here is a manual definition using select/3:
permute([], []).
permute([E|Es], [E0|PL]) :-
select(E0, [E|Es], Rem),
permute(Rem, PL).
If you want a list of all the results and don't want numberFromList/2 to backtrack itself, you could wrap the call to numberFromList/3 (with the empty accumulator in the first clause of numberFromList/2) in a findall/3 call.