replacing elements between two lists using prolog - list

My task is to make myReplace(E1,L1,E2,L2) such that the very first occurrence of E1 in L1 gets replaced by E2 and is returned in L2. I have written the below described code and it is working properly.
myReplace(E1,[],E2,[]).
myReplace(E1,[E1|Xs],E2,[E2|Ys]):-
myReplace(E1,Xs,E1,Ys).
myReplace(E1,[H|Hs],E2,[H|Ts]):-
E1 \= H,
myReplace(E1,Hs,E2,Ts).
However, For example myReplace(2,[1,2,3,2,1],5,X) should give X = [1,5,3,2,1] and X = [1,2,3,5,1]. But my code is only giving one solution which is X = [1,5,3,2,1].
Similarly, when myReplace(2,X,5,[1,5,3,5,1]) should backtrack over the solutions X = [1,2,3,5,1] and X = [1,5,3,2,1] only, but my solution gives me one more solution as X = [1,5,3,5,1].
Could you please help me resolve this.
Thank you :)

What about
myReplace(E1,[E1|Xs],E2,[E2|Xs]).
myReplace(E1,[H|Hs],E2,[H|Ts]):-
myReplace(E1,Hs,E2,Ts).
?
If I'm not wrong, this impose one (and only one) replacement.
Take in count that you have to delete
myReplace(E1,[],E2,[]).
otherwise you get L1 = L2 (no replacement) as a solution.
And observe that, as pointed by Lurker, this isn't "the very first occurrence of E1 in L1 gets replaced".

If I understand your question, you want to get all answers from substituting each one occurrence of E1 in L1. You can get the backtracking for free if you use append/3 for this:
my_replace(X, As, Y, Bs) :-
append(As_front, [X|As_back], As),
append(As_front, [Y|As_back], Bs).
With this definition I get:
?- my_replace(2,[1,2,3,2,1],5,X).
X = [1, 5, 3, 2, 1] ;
X = [1, 2, 3, 5, 1] ;
false
See the other solution to see how to see what the problem with your original code was.

Related

Prolog: compare list elements and sum

New to prolog and trying to implement the following function that takes 3 lists:
True if lists are the same length
True if elements of third list is sum of the two lists
Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.
This is what I have so far:
fn([],[],[]).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.
From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)
Thanks for any help and explanations!
In addition to #GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...
:- use_module(library(apply)). % for maplist/4
num_num_sum(X,Y,S) :-
S is X+Y.
... and subsequently use maplist/4 to apply it to entire lists:
fn(X,Y,Z) :-
maplist(num_num_sum,X,Y,Z).
This predicate yields the desired results if the first two lists are fully instantiated:
?- fn([1,2,3],[4,5,6],X).
X = [5,7,9]
However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:
?- fn([1,A,3],[4,5,6],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is _+B: expected bound value
?- fn([1,2,3],[4,5,A],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is A+B: expected bound value
If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:
:- use_module(library(apply)).
:- use_module(library(clpfd)). % <- use CLP(FD)
int_int_sum(X,Y,S) :-
S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2
fnCLP(X,Y,Z) :-
maplist(int_int_sum,X,Y,Z).
With this definition the previously problematic queries work as well:
?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6
Even the most general query yields results with this version:
?- fnCLP(X,Y,Z).
X = Y = Z = [] ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.
Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:
label the lists
restrict the domain | |
v v v v
?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = [] ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.
On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.
From what I understand, the error is due to the base case.
I don't see it that way.
The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.
When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.
e.g. for length of list you would have
ln([],N,N).
ln([_|T],N0,N) :-
N1 is N0+1,
ln(T,N1,N).
ln(L,N) :-
ln(L,0,N).
The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln([],N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.
Now back to your problem.
The base case is fine
fn([],[],[]).
There are three list and for each one look at the list as [H|T]
fn([H1|T1],[H2|T2],[H3|T3])
and the call to do the recursion on the tail is
fn(T1,T2,T3)
all that is left is to process the heads which is
H3 is H1 + H2
putting it all together gives us
fn([],[],[]).
fn([H1|T1], [H2|T2], [H3|T3]) :-
H3 is H1 + H2,
fn(T1,T2,T3).
and a quick few checks.
?- fn([],[],[]).
true.
?- fn([1],[1],[2]).
true.
?- fn([1,2],[3,4],[4,6]).
true.
?- fn([1,2],[3,4,5],[4,6,5]).
false.
With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.

Using Pattern Matching in Prolog to Find Submultisets

I am new to prolog and I was wondering if anyone could help me with this problem. The problem: given the integers 1,2,3,4, and the predicates mult/2, div/2, div/2, minus/2, and minus/2, and eval/2, I need to write a predicate solutions/1 that, when called like this:
?- solutions(L).
it should terminate with the variable L unified to a list of expressions with value 6. Expressions are of the form:
X, Y, exp/2
But my code is not working. I have two versions. The first freezes up SWI-Prolog, not returning any answer after I type a period, and not letting me evaluate anything else afterward:
eval(1,1.0).
eval(2,2.0).
eval(3,3.0).
eval(4,4.0).
eval(mult(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A*B.
eval(div(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A/B.
eval(minus(X,Y),Z) :-
eval(X,A),
eval(Y,B),
Z is A-B.
solutions(L) :-
setof(X,eval(X,6),L),
print(L).
The second version just returns false when I type ?- solutions(L).:
solutions(L) :-
setof([exp,X,Y],eval(exp(X,Y),6),L),
print(L).
Thank you so much for taking the time to help!
Maybe you're looking for something like
solutions(L) :-
Ns = [1,2,3,4],
Ex = [*,/,-],
findall((X,Y,E),
(member(X,Ns),member(Y,Ns),member(E,Ex),F=..[E,X,Y],6=:=F),
L).
that yields
?- solutions(L).
L = [(2, 3, (*)), (3, 2, (*))].
Expressions are usually recursive, that is, arguments could be expressions instead of plain numbers. But then, in my opinion your problem is underspecified, as we need criteria to stop the infinite flow of solutions resulting - for instance - by repeated application of operations that don't change the value. Like multiply or divide by 1.
The problem is that your code is going in infinite recursion with eval/2 predicate.
You can try this solution:
num(1).
num(2).
num(3).
num(4).
eval(mult(A,B),Z) :-
num(A),
num(B),
Z is A*B.
eval(div(A,B),Z) :-
num(A),
num(B),
Z is A/B.
eval(minus(A,B),Z) :-
num(A),
num(B),
Z is A-B.
test(L) :-
setof(X,eval(X,6),L),
print(L).
Which yields:
?- test(L).
[mult(2,3),mult(3,2)]
L = [mult(2, 3), mult(3, 2)].

What is the explanation of this code?

I am trying to learn Prolog. I have a problem and the solution for that in Prolog. Though I am unable to understand the code completely.
The problem is -
Write a procedure mydelete( X, HasXs, OneLessXs ) that returns
% ?- mydelete( 2, [1,2,3,4], L ) . --> L = [1,3,4]
% ?- mydelete( 2, [1,2,3,2], L ) . --> L = [1,3,2] ; L = [1,2,3]
Basically, the problem is t remove the member one by one which matches X and print the result after each removal.
I have a solution , but, I am exactly, not sure how this code is working.
mydelete(X,[X|T],T).
mydelete(X,[H|T1],[H|T2]) :- mydelete(X,T1,T2).
As per my understanding, the first line, displays the L = ... when it finds a match with X in the head of the list.
In the second line of the code, it simply pops out the head from the input list and send that updated list recursively.
But, here, we haven't defined T2.
Let us consider an example for that.
mydelete( 2, [1,2,3,4], L ) . --> this is the call.
X=2, list is = [1,2,3,4], so, H=1, T=[2,3,4].
So, it does not execute line 1 of the code. Now, it comes to the second line of the code.
mydelete(X,[H|T1],[H|T2]) :- mydelete(X,T1,T2).
Here also X=2, H =1, T1=[2,3,4], T2= .
So, on the next recursion,
X=2, list = [2,3,4], H matches X, thus line 1 will get executed.
Therefore, X=2, T=[3,4]
So, it should print = [3,4].(I know, [1,3,4] is the right answer. I am not able to understand the explanation behind this code)
My, question is, what is wrong in my understanding?
And, what is the use of [H|T2] in
mydelete(X,[H|T1],[H|T2]) :- mydelete(X,T1,T2).
Thanks! Please help me out!
edit: I tried removing H from [H|T2]. It is printing [3,4]. How H is adding 1 as the prefix to the list [3,4] ?
The best way to think of this as an imperative programmer is that the last argument is kind of the return value. You see that the first call you make "returns" [H|T2], not merely T2 this is how the first element of the list remains: after recursing to compute the value of T2, mydelete is adding H (which happens to equal 1 in this case) to the start of the returned list.
What is the use of [H|T2]?
In your explanations, you forgot to consider that the third argument, L, is being unified with [H|T2]. Up to this point, L was free (in your case), and now you know that it is a list starting with H. The rest of the list T2 is now the third argument to the recursive call and will be unified likewise, until you reach the base case.
By the way, what happens when your list is empty?

Prolog: How "length(+,-)" delete unassigned tail of the list keeping the list?

Again a Prolog beginner :-}
I build up a list element by element using
(1)
member(NewElement,ListToBeFilled).
in a repeating call,
(2)
ListToBeFilled = [NewElement|TmpListToBeFilled].
in a recursive call like
something(...,TmpListToBeFilled).
A concrete example of (2)
catch_all_nth1(List, AllNth, Counter, Result) :-
[H|T] = List,
NewCounter is Counter + 1,
(
0 is Counter mod AllNth
->
Result = [H|Result1]
;
Result = Result1
),
catch_all_nth1(T,AllNth,NewCounter,Result1),
!.
catch_all_nth1([], _, _, _).
As result I get a list which looks like
[E1, E2, E3, ..., Elast | _G12321].
Of course, the Tail is a Variable. [btw: are there better method to fill up the
list, directly avoiding the "unassigned tail"?]
I was now looking for a simple method to eliminate the "unassigned tail".
I found:
Delete an unassigned member in list
there it is proposed to use:
exclude(var, ListWithVar, ListWithoutVar),!,
[Found this too, but did not help as I do not want a dummy element at the end
Prolog list has uninstantiated tail, need to get rid of it ]
What I noticed is that using length\2 eliminate the "unassigned tail", too, and in addtion
the same List remains.
My Question is: How does it work? I would like to use the mechanism to eliminate the unassigned tail without using a new variable... [in SWI Prolog 'till now I did not get the debugger
entering length() ?!]
The example:
Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.
13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .
I thought X, once initialized can not be changed anymore and you need
a new variable like in exclude(var, ListWithVar, ListWithoutVar).
Would be happy if someone explain the trick to me...
Thanks :-)
You're right about the strange behaviour: it's due to the ability of length/2 when called with unbound arguments
The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound.
example:
?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...
For your 'applicative' code, this tiny correction should be sufficient. Change the base recursion clause to
catch_all_nth1([], _, _, []).
here are the results before
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].
and after the correction:
5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].
But I would suggest instead to use some of better know methods that Prolog provide us: like findall/3:
?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].
I think this should do it:
% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :-
var(Uninstantiated_Var), !,
Uninstantiated_Var = '[]'.
% case 2: not the end, recurse
close_open_list([_|Tail]) :-
close_open_list(Tail).
?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].
Note that only variable X is used.. it simply recurses through the list until it hits the var at the end, replaces it with an empty list, which closes it. X is then available as a regular 'closed' list.
Edit: once a list element has been assigned to something specific, it cannot be changed. But the list itself can be appended to, when constructed as an open list ie. with |_ at the end. Open lists are a great way to build up list elements without needing new variables. eg.
X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]
In the example above, memberchk tries tries to make '4', then '5' members of the list, which it succeeds in doing by inserting them into the free variable at the end in each case.
Then when you're done, just close it.

Prolog append to head

I am learning Prolog right now and I am trying to write a predicate newhead/3 that simply appends the second parameter to the first parameter that represents a list.
So newhead([1,2],3,R) should yield R = [3,1,2].
I wrote the following and I am confused as to what this error message says as well as why the logic of my code does not seem to be correct.
newhead([H|T],E,R) :-
L is [H|T],
R is [E|L].
Or:
newhead(L,E,R) :-
R is [E|L].
Also doesn't work. This seems like it should be a pretty trivial operation but I can't believe that it could need recursion.
I appreciate any help.
You can simply write:
new_head(Tail, Head, [Head| Tail]).
You can use the predicate 'append/3'.
apped([3],[1,2],R).
R = [3,1,2]
or
append([X],[1,2],R), X=3.
R = [3,1,2]
I am sure that you already found your answer :) but I want to explain my answer too.
My understanding: first parameter is list and aim is the make the second argument head of the list.
Here is code:
new([],F,[F]). % if your list is empty.
new([X|XS],F,[F,X|XS]):-
new(XS,F,YS).
Output:
?- new([2,3],1,R).
R = [1, 2, 3].
?- new([],1,R).
R = [1].
?- new([2,3],[1],R).
R = [[1], 2, 3].