filling list with the same integer in prolog - list

I want to write a function that fill in the list with the same number on prolog. For example, I want the list [_,_,1,_] to be [1,1,1,1] or if the list is all empty [_,_,_,_] it will result in a number of my choice, 5 for example. Can anyone help me with that?

Simplest:
?- L = [_,_,1,_], maplist(=(_), L).
L = [1,1,1,1].

Simple:
all(_,[],[]).
all(H,[H|T],[H|T]) :- all(H,T,T).
That gives me:
?- all(_,[_,_,1,_],Xs).
Xs = [1, 1, 1, 1].
?- all(5,[_,_,_,_],Xs).
Xs = [5, 5, 5, 5].
?- all(5,[_,_,1,_],Xs).
false.
?- all(_,[3,_,1,_],Xs).
false.

:- use_module(library(clpfd)).
fill(Ls, Value) :-
chain(Ls, #=),
Ls = [Value|_].
e.g.
?- Ls = [_,_,1,_], fill(Ls, V).
Ls = [1, 1, 1, 1],
V = 1
?- Ls = [_,_,_,_], fill(Ls, 5).
Ls = [5, 5, 5, 5]
?- Ls = [_,_,1,_], fill(Ls, 7).
false

Related

replace an element in list with its first occurence but keep replacing for all occurences- Prolog

I have just started programing in Prolog, using tkeclipse. What I want to do, is to replace an element of the list with another element on the first place that it occurs. However, when I press the more button (;) I want the query to return also the other solutions. Example:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3]
Yes
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
No
What I wrote so far, works fine, but in the end, after [1,2,1,a,3], I also get [1,2,1,1,3] instead of no. My code is as follows:
%%% replace/4
replace(_,_,[],[]).
replace(X,Y,[X|T],[Y|T]).
replace(X,Y,[H|T],[H|T2]) :-
replace(X,Y,T,T2).
Just delete the first clause
replace(_,_,[],[]).
and you should be fine.
You [1,2,1,1,3] because:
replace(1,a,[1,2,1,1,3],[1,2,1,1,3]) is successful by
always taking the third clause, reducing the pre-replacement-list and the result-of-the-replacement list element by element
succeeding on the empty list by taking the first clause
You want:
Success on the empty list (0 replacements); and also
A stream of of exactly-one-replacements
And so:
replace(_,_,[],[]) :- !. % make this deterministic with a a cut
replace(X,Y,PreList,PostList) :-
replace_2(X,Y,PreList,PostList).
% replace_2/4 is the same as replace/4 but does NOT succeed for the empty list
replace_2(X,Y,[X|T],[Y|T]).
replace_2(X,Y,[H|T],[H|T2]) :-
replace_2(X,Y,T,T2).
And so:
?- replace(1,a,[1,2,3],R).
R = [a, 2, 3] ;
false.
?- replace(1,a,[1,2,1,1,3],R).
R = [a, 2, 1, 1, 3] ;
R = [1, 2, a, 1, 3] ;
R = [1, 2, 1, a, 3] ;
false.
?- replace(foo,a,[1,2,1,1,3],R).
false.
?- replace(foo,a,[],R).
R = [] ;
false.

Insert into open-ended list without binding its tail variable

Is it possible to solve the following problem in Prolog?
Let A and B be lists of numbers and let N be a number. It is known that B is sorted decreasingly. Check if N can be inserted into A so that the result is B, but do not bind any variable that occurs as a tail in either A nor B.
For example
?- insertable(34, [78, 72, 11 | Z], [78, 72, 34, 11 | Z]).
true.
?- insertable(34, [78, 72, 11 | Z], L).
L = [78, 72, 34, 11 | Z].
Can anyone help me? :)
EDIT 1: This is what I came up with.
insertable(X, List1, List2):- select(X, List2, List1), sorted(List2).
sorted([]).
sorted([_]).
sorted([X, Y | Rest]) :-
X > Y,
sorted([Y | Rest]).
However, even though it works as expected when the arguments are fully instantiated, it binds variables located in tails:
?- insertable(11, [5, 3, 2], [11, 5, 3, 2]).
true .
?- insertable(11, [5, 3, 2 | X], [11, 5, 3, 2 | X] ).
X = [] .
?- insertable(11, [5, 3, 2 | X], L ).
X = [],
L = [11, 5, 3, 2] .
EDIT 2: Here's another approach that I tried.
in(X, [], [X]).
in(X, [Head | Tail1], [Head | Tail2]) :-
X =< Head,
in(X, Tail1, Tail2).
in(X, [Head | Tail], [X, Head | Tail]) :-
X > Head.
The problem is still there:
?- in(1, [3, 2], [3, 2, 1]).
true ;
false.
?- in(1, [3, 2], L).
L = [3, 2, 1] ;
false.
?- in(1, [3, 2 | X], L).
X = [],
L = [3, 2, 1] ;
ERROR: =</2: Arguments are not sufficiently instantiated
Exception: (9) in(1, _G8394089, _G8394190) ? abort
% Execution Aborted
?- in(1, [3, 2 | X], [3, 2, 1 | X]).
X = [] ;
X = [1] ;
X = [1, 1] ;
X = [1, 1, 1] ;
X = [1, 1, 1, 1] ;
X = [1, 1, 1, 1, 1] ;
X = [1, 1, 1, 1, 1, 1] ;
X = [1, 1, 1, 1, 1, 1, 1] .
The trick for this exercise are the metalogical predicates var/1 and nonvar/1 which are true if the argument is a variable or not (also have a look at ground/1, atom/1 and integer/1). To make the difference is a little clumsy because we need to keep the list L1 in the head and unify after we know it is a variable or not.
What also might have confused you is the error message of the arithmetic comparison. For that to work, both arguments must be ground. When you don't test for non-var of the tail, the unification automatically instantiates the tail with [Head|Tail1]. That always leads to a comparison number <= Head which leads to the error you had.
The following code assumes you would also like to insert into lists that have a closed tail. If not, the first rule needs to be removed.
in(X, L1, [X]) :- % terminal case for empty list (i.e. tail is not a variable)
nonvar(L1),
L1 = [].
in(X, Xs, [X | Xs]) :- % terminal case if the tail is a variable
var(Xs).
in(X, L1, [N | Zs]) :- % recursive case X =< N
nonvar(L1),
L1 = [N | Ys],
X =< N,
in(X, Ys, Zs).
in(X, L1, [X, N | Ys]) :- % recursive case X > N
nonvar(L1),
L1 = [N | Ys],
X > N.
When we test we can insert 1 in front of a variable tail (after the first result, there are still paths to test but all fail, leading to the false after continuing the query):
?- in(1,Xs,Ys).
Ys = [1|Xs] ;
false.
Also, the inserted element must be 1, so this one should fail:
?- in(1,Xs,[2|Ys]).
false.
It seems the recursion properly propagates to the end:
?- in(1,[3, 2 | Xs], Zs).
Zs = [3, 2, 1|Xs] ;
false.
Inserting in the middle also works:
?- in(2,[3,1 |Xs],Zs).
Zs = [3, 2, 1|Xs].
And finally the test case you tried to solve before:
?- in(34, [78, 72, 11 | Z], [78, 72, 34, 11 | Z]).
true ;
false.
What still doesn't work is if you have variables occurring in your list:
?- in(2,[3,A,1|Xs],Zs).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [10] 2=<_8374
ERROR: [9] in(2,[_8406,1|_8414],[_8418|_8420]) at ./prolog/so-3.pl:9
ERROR: [8] in(2,[3,_8458|...],[3,_8470|_8472]) at ./prolog/so-3.pl:10
ERROR: [7] <user>
Exception: (9) in(2, [_7488, 1|_7496], _7820) ? a
An easy way out would be to guard the comparison with an integer(N) to get
?- in(2,[3,A,1|Xs],Zs).
false.
But then we should also guard against the inserted element being non-integer and the lists having decending integers followed with a variable tail. Alternatively, we could throw a better exception in these cases.

How can I delete every occurrence of a sublist from a list in prolog?

This is the code for deleting or removing an element from a given list:
remove_elem(X,[],[]).
remove_elem(X,L1,L2) :-
L1 = [H|T],
X == H,
remove_elem(X,T,Temp),
L2 = Temp.
remove_elem(X,L1,L2) :-
L1 = [H|T],
X \== H,
remove_elem(X,T,Temp),
L2 = [H|Temp].
How can I modify it, so that I can delete every occurrence of a sub list from a list?
When I tried to put a list in an element, it only deletes the element and only once.
It should be this:
?- remove([1,2],[1,2,3,4,1,2,5,6,1,2,1],L).
L = [3,4,5,6,1]. % expected result
Inspired by #CapelliC's implementation I wrote the following code based on
and_t/3:
append_t([] ,Ys,Ys, true).
append_t([X|Xs],Ys,Zs,Truth) :-
append_aux_t(Zs,Ys,Xs,X,Truth).
append_aux_t([] ,_ ,_ ,_,false). % aux pred for using 1st argument indexing
append_aux_t([Z|Zs],Ys,Xs,X,Truth) :-
and_t(X=Z, append_t(Xs,Ys,Zs), Truth).
One append_t/4 goal can replace two prefix_of_t/3 and append/3 goals.
Because of that, the implementation of list_sublist_removed/3 gets a bit simpler than before:
list_sublist_removed([] ,[_|_] ,[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(append_t([L|Ls],Xs0,[X|Xs]),
(Zs = Zs0 , Xs1 = Xs0),
(Zs = [X|Zs0], Xs1 = Xs)),
list_sublist_removed(Xs1,[L|Ls],Zs0).
Still deterministic?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1].
Yes! What about the following?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3,4,5,6,1]).
X = [1,2] ; % succeeds with useless choice-point
false.
Nope. So there is still room for potential improvement...
This logically pure implementation is based on the predicates if_/3 and (=)/3.
First, we build a reified version of prefix_of/2:
prefix_of_t([],_,true).
prefix_of_t([X|Xs],Zs,T) :-
prefix_of_t__aux(Zs,X,Xs,T).
prefix_of_t__aux([],_,_,false).
prefix_of_t__aux([Z|Zs],X,Xs,T) :-
if_(X=Z, prefix_of_t(Xs,Zs,T), T=false).
Then, on to the main predicate list_sublist_removed/3:
list_sublist_removed([],[_|_],[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(prefix_of_t([L|Ls],[X|Xs]), % test
(Zs = Zs0, append([L|Ls],Xs0,[X|Xs])), % case 1
(Zs = [X|Zs0], Xs0 = Xs)), % case 2
list_sublist_removed(Xs0,[L|Ls],Zs0).
A few operational notes on the recursive clause of list_sublist_removed/3:
First (test), we check if [L|Ls] is a prefix of [X|Xs].
If it is present (case 1), we strip it off [X|Xs] yielding Xs0 and add nothing to Zs.
If it is absent (case 2), we strip X off [X|Xs] and add X to Zs.
We recurse on the rest of [X|Xs] until no more items are left to process.
Onwards to some queries!
The use case you gave in your question:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1]. % succeeds deterministically
Two queries that try to find the sublist that was removed:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[ 3,4,5,6,1]).
Sub = [1,2] ? ;
no
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[1,3,4,5,6,1]).
no
Next, let's find a suitable Ls in this query:
?- list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
% a lot of time passes ... and nothing happens!
Non-termination! This is unfortunate, but within expectations, as the solution set is infinite. However, by a-priori constraining the length of Ls, we can get all expected results:
?- length(Ls,_), list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
Ls = [ 3,4,5,6,1] ?
; Ls = [1,2, 3,4,5,6,1] ?
; Ls = [3, 1,2, 4,5,6,1] ?
; Ls = [3,4, 1,2, 5,6,1] ?
; Ls = [3,4,5, 1,2, 6,1] ?
; Ls = [3,4,5,6, 1,2, 1] ?
; Ls = [3,4,5,6,1, 1,2 ] ?
; Ls = [1,2, 1,2, 3,4,5,6,1] ? ...
<rant>
So many years I study Prolog, still it deserves some surprises... your problem it's quite simple to solve, when you know the list library, and you have a specific mode (like the one you posted as example). But can also be also quite complex to generalize, and it's unclear to me if the approach proposed by #repeat, based on #false suggestion (if_/3 and friends) can be 'ported' to plain, old Prolog (a-la Clocksin-Mellish, just to say).
</rant>
A solution, that has been not so easy to find, based on old-school Prolog
list_sublist_removed(L, S, R) :-
append([A, S, B], L),
S \= [],
list_sublist_removed(B, S, T),
append(A, T, R),
!
; L = R.
some test:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3, 4, 5, 6, 1].
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3, 4, 5, 6, 1]).
X = [1, 2].
?- length(X,_), list_sublist_removed(X,[1,2],[3, 4, 5, 6, 1]).
X = [3, 4, 5, 6, 1] ;
X = [3, 4, 5, 6, 1, 2, 1] ...

prolog two lists are exactly the same

I want to write a function that returns true if two lists are exactly the same(order of elements matters).
I tried it this way:
same([ ], [ ]).
same([H1|R1], [H2|R2]):-
H1 == H2,
same(R1, R2).
It returns true while two lists are the same, also I expect if I have
?- same(X, [1, 2, 3]).
I want it to return
X = [1, 2, 3].
But it doesn't work if input is like this. Here are some sample outputs I got:
?- same([1, 2], [1, 2]).
true.
?- same([2, 1], [1, 2]).
false.
?- same(X, [1, 2, 3]).
false.
?- same([1, 2, 3], [1, 2, X]).
false.
How to fix it?
The problem is that you're using ==/2 (checking whether two items are instantiated the same) rather than =/2 (checks if two items are unified or unifiable). Just change to unification:
same([], []).
same([H1|R1], [H2|R2]):-
H1 = H2,
same(R1, R2).
Then this will have the behavior you're looking for:
| ?- same(X, [1, 2, 3]).
X = [1,2,3] ? a
no
| ?- same([1, 2], [1, 2]).
(1 ms) yes
| ?- same([2, 1], [1, 2]).
no
| ?- same([1, 2, 3], [1, 2, X]).
X = 3
(1 ms) yes
| ?- same([A,B,C], L).
L = [A,B,C]
yes
% In this last example, A, B, and C are variables. So it says L is [A,B,C],
% whatever A, B, and C are.
If you query X == 3 in Prolog, and X is not bound to the value 3, or it is just unbound, it will fail. If X is unbound and you query, X = 3, then Prolog will unify X (bind it) with 3 and it will succeed.
For more regarding the difference between =/2 and ==/2, see What is the difference between == and = in Prolog?
You can also use maplist for a nice, compact solution. maplist is very handy for iterating through a list:
same(L1, L2) :- maplist(=, L1, L2).
Here, unification (=/2) is still used for exactly the same reason as above.
Finally, as #Boris points out, in Prolog, the unification predicate will work on entire lists. In this case, this would suffice:
same(L1, L2) :- L1 = L2.
Or equivalently:
same(L, L). % Would unify L1 and L2 queried as same(L1, L2)
This will succeed if the lists are the same, or will attempt to unify them by unifying each element in turn.
| ?- same([1,2,X], [1,2,3]). % Or just [1,2,X] = [1,2,3]
X = 3
yes
| ?- same([1,2,X], [1,2,3,4]). % Or just [1,2,X] = [1,2,3,4]
no
The prior more elaborate approaches are considered an exercise in list processing for illustration. But the simplest and most correct method for comparison and/or unification of lists would be L1 = L2.

How to access list permutations in prolog?

I want to access list permutation and pass it as argument to other functions.
This is the permutation code:
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :-
takeout(X,R,S),
write(S).
perm([X|Y],Z) :-
perm(Y,W),
takeout(X,Z,W).
perm([],[]).
To start with, let's redefine your predicates so they don't do any unnecessary I/O:
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
Now you have what could be considered a "pure" permutation function:
?- perm([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 1, 3] ;
X = [2, 3, 1] ;
X = [1, 3, 2] ;
X = [3, 1, 2] ;
X = [3, 2, 1] ;
false.
So, suppose you have a max_heap function that takes a list of values and produces a tree. I'll let you worry about that, so let's just posit that it exists and is called max_heap/2 and let's further posit that you have a way to display this attractively called display_heap/1. To "take" the permutation and "send" it as a parameter to these functions, you're really saying in math-ese: suppose P is a permutation of X, let's make a max_heap with it and display it. Or, suppose P is a permutation of X, H is a max heap made from X, let's display H:
show_heaps(List) :- perm(List, P), max_heap(P, H), display_heap(H).
This says the same thing as my English sentence: suppose P is a permutation of the list, then H is a heap representation of it, then display it. Technically, display_heap/1 is still a predicate which could be true or false for a given heap. In practice, it will always be true, and if you run this you'll still have to hit ; repeatedly to say, give me another solution, unless you use a failure-driven loop or an extralogical predicate like findall/3 to cause all the solutions to be found.
Edit: Let's discuss failure-driven loops and findall/3. First let me add some new predicates, because I don't know exactly what you're doing, but it doesn't matter for our purposes.
double([X|Xs], [Y|Ys]) :- Y is X*2, double(Xs, Ys).
double([],[]).
showlist(Xs) :- print(Xs).
So now I have a predicate double/2 which doubles the values in the list and a predicate showlist/1 that prints the list on standard output. We can try it out like so:
?- perm([1,2,3], X), double(X, Y), showlist(Y).
[2,4,6]
X = [1, 2, 3],
Y = [2, 4, 6] ;
[4,2,6]
X = [2, 1, 3],
Y = [4, 2, 6] ;
[4,6,2]
X = [2, 3, 1],
Y = [4, 6, 2] ;
[2,6,4]
X = [1, 3, 2],
Y = [2, 6, 4] ;
[6,2,4]
X = [3, 1, 2],
Y = [6, 2, 4] ;
[6,4,2]
X = [3, 2, 1],
Y = [6, 4, 2] ;
false.
When you type ; you're saying, "or?" to Prolog. In other words, you're saying "what else?" You're telling Prolog, in effect, this isn't the answer I want, try and find me another answer I like better. You can formalize this process with a failure-driven loop:
?- perm([1,2,3], X), double(X, Y), showlist(Y), fail.
[2,4,6][4,2,6][4,6,2][2,6,4][6,2,4][6,4,2]
false.
So now you see the output from each permutation having gone through double/2 there, and then Prolog reported false. That's what one means by something like this:
show_all_heaps(List) :- perm(List, X), double(X, Y), showlist(Y), nl, fail.
show_all_heaps(_).
Look at how that works:
?- show_all_heaps([1,2,3]).
[2,4,6]
[4,2,6]
[4,6,2]
[2,6,4]
[6,2,4]
[6,4,2]
true.
The other option is using findall/3, which looks more like this:
?- findall(Y, (perm([1,2,3], X), double(X, Y)), Ys).
Ys = [[2, 4, 6], [4, 2, 6], [4, 6, 2], [2, 6, 4], [6, 2, 4], [6, 4, 2]].
Using this to solve your problem is probably beyond the scope of whatever homework it is you're working on though.
We can define list_permutation/2 based on same_length/2 and select/3 like this:
:- use_module(library(lists),[same_length/2,select/3]).
list_permutation(As,Bs) :-
same_length(As,Bs), % redundant goal helps termination
list_permutation_(As,Bs).
list_permutation_([],[]).
list_permutation_([A|As],Bs0) :-
select(A,Bs0,Bs),
list_permutation_(As,Bs).
Thanks to same_length/2, both of the following queries1,2 terminate universally:
?- list_permutation([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.
?- list_permutation(Xs,[1,2,3]).
Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
So far, so good. But what does the answer sequence look like if there are duplicate list items?
?- list_permutation([1,1,1],Ys).
Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; Ys = [1,1,1]
; false.
5/6 answers are redundant! What can we do? We simply use selectd/3 instead of select/3!
list_permuted(As,Bs) :-
same_length(As,Bs),
list_permuted_(As,Bs).
list_permuted_([],[]).
list_permuted_([A|As],Bs0) :-
selectd(A,Bs0,Bs), % use selectd/3, not select/3
list_permuted_(As,Bs).
Let's re-run above query that gave us 5 redundant solutions before!
?- list_permuted([1,1,1],Ys).
Ys = [1,1,1]
; false.
?- list_permuted(Xs,[1,1,1]).
Xs = [1,1,1]
; false.
Better! All redundant answers are gone.
Let's compare the solution set for some sample case:
?- _Xs = [1,2,1,1,2,1,1,2,1],
setof(Ys,list_permutation(_Xs,Ys),Yss),
setof(Ys,list_permuted(_Xs,Ys),Yss),
length(Yss,N).
N = 84, Yss = [[1,1,1,1,1,1,2,2,2],[1,1,1,1,1,2,1,2,2],[...|...]|...].
OK! How about empirical runtime measurements with a problem of a slightly bigger size?
We use call_time/2 for measuring the runtime in milli-seconds T_ms.
?- call_time(\+ (list_permutation([1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 8110.
?- call_time(\+ (list_permuted( [1,2,1,1,1,2,1,1,1,2,1],_),false),T_ms).
T_ms = 140.
OK! And with proper compilation of if_/3 and (=)/3, list_permuted/2 is even faster!
Footnote 1: Using SICStus Prolog version 4.3.2 (x86_64-linux-glibc2.12).
Footnote 2: The answers given by the Prolog toplevel have been post-processed for the sake of readability.
If you just want to explore the permutations without the "False" in the end, this code might be helpful
takeout(X,[F |R],[F|S]) :- F\=X, takeout(X,R,S).
takeout(X,[X|R],R).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
So, the output of perm([a,b],B) would be
B=[a,b]
B=[b,a]