Prolog append variable to list - list

I want to append to a list a variable, N, that's bound to a number.
N = 1.
append([N], [2,3,4], Z).
Z = [N,2,3,4]. //Wrong output!
I want to get Z = [1,2,3,4]
How do I append the number part of a variable, not the actual variable itself?

I'm afraid Prolog doesn't have variable assignment like you're used to, just variable binding. So the "statements"
N = 1.
append([N], [2,3,4], Z).
actually constitute two completely unrelated queries. Fortunately, the effect you desire can be achieved by combining your queries:
N = 1, append([N], [2,3,4], Z).
If you truly need a global variable, you can always use a fact or asserta/1 to define one dynamically.
Also note: in the future, you'll probably want to make sure you use is instead of = when dealing with numbers.

Which Prolog are you using? All Prologs I am aware of, will produce an answer for N = 1 first. This should make it clear, that Prolog has first answered the query N = 1 with N = 1, which might look a little odd at first. E.g., here is GNU:
| ?- N = 1.
N = 1
yes
| ?-
append([N], [2,3,4], Z).
Z = [N,2,3,4]
yes

Related

Member of a list, sum previous members list prolog

I want to verify if a member of list, is the sum of the previous numbers.
Example: [0,1,3,4,18,19]. This is TRUE because 0+1+3 = 4
sum_([],0).
sum_([X|XS],R):- suma(XS,R1), R is X + R1.
existsSum(L,[X|C]):-append(A,[X|B],L),
append(A,B,C),
sum_(C,X).
I am stuck here. Any idea? Thanks.
Why append(A,[X|B],L),append(A,B,C),sum_(C,X)? In this way you want the sum of all elements except X to be equal to X.
It is not clear what the arguments of existsSum should be. Supposing existsSum(InputList, SubList, Element):
existsSum(L,A,X) :- append(A,[X|_B],L), sum_(A,X).
With your example produces these results:
?- existsSum([0,1,3,4,18,19], Sublist, Element).
Sublist = [],
Element = 0 ;
Sublist = [0, 1, 3],
Element = 4 ;
false.
Note: also [] and 0 is a solution because of how you defined the sum_ predicate, i.e. the sum of [] is 0.
If you change the sum_ predicate in this way:
sum_([X],X).
sum_([X|XS],R):- sum_(XS,R1),R is X + R1.
it is defined only for non-empty lists, and in this case you get only one result from your example:
?- existsSum([0,1,3,4,18,19], Sublist, Element).
Sublist = [0, 1, 3],
Element = 4 ;
false.
I think your problem is ill-stated (or your example should not start with zero) because I think you basically have two ways you can process the list: either you process the entire list every time (and your example fails because 0+1+3+4+18 != 19) or you stop as soon as your expected value matches the head of the list, in which case [0] is already successful.
In the end, there aren't that many ways to process a list. You have to make a decision when you have an element, and you have to make a decision when you are out of elements. Suppose we want to succeed as soon as we have reached a value that matches the sum-so-far. We can model that fairly simply like this:
exists_sum(List) :- exists_sum(0, List).
exists_sum(RunningTotal, [RunningTotal|_]).
exists_sum(RunningTotal, [H|T]) :-
NewRunningTotal is RunningTotal + H,
exists_sum(NewRunningTotal, T).
Note that with this formulation, [0|_] is already successful. Also note that I have no empty list case: if I make it to the end of a list without having succeeded already, there is no solution there, so there's nothing to say about it.
The other formulation would be to require that the entire list is processed, which would basically be to replace the first exists_sum/2 clause with this:
exists_sum(Total, [Total]).
This will fail to unify exists_sum(4, [4|_]) which is the case you outline in the question where [0,1,3,4...] succeeds.
There may be other formulations that are more complex than these, but I don't see them. I really think there are only a couple ways to go with this that make sense.

Prolog outputs that a variable's value is the name of the other variable if they have the same value rather than the value

I am having a LOT of trouble with prolog because the professor is requiring us not to use base cases. I finally got my segregate predicate to work except that it says Even = Odd rather than Even = [] like it is supposed to. Is there any way around this?
segregate(List, Even, Odd) :-
(not(length(List, 0)) ->
% segregate the list
;
Even = [],Odd = [], true).
?- segregate([], Even, Odd).
Even = Odd, Odd = []

swi-prolog Combination of lists whose heads are unique

I tried to modify this combination predicate:
comb(+PairCount,+List,-Combination)/3
comb(0,_,[]).
comb(N,[X|T],[X|Comb]):-N>0,N1 is N-1,comb(N1,T,Comb).
comb(N,[_|T],Comb):-N>0,comb(N,T,Comb).
To make it include only lists with unique heads so that when I run this:
?- comb(2, [[1,2],[1,3],[2,4]], L].
I should get:
L= [[1,2],[2,4]];
L= [[1,3],[2,4]].
I tried something like this but since I can't get current CombinationList, I can't restrict it by this way:
comb(0,_,[]).
comb(N,[X|T],[X|Comb]):-
N>0, N1 is N-1,
+ X = [H|_],
+ % H is not head of any of the current CombinationList's items,
comb(N1,T,Comb).
comb(N,[_|T],Comb):-
N>0,
comb(N,T,Comb).
I may be thinking unnecessarily procedural, but here it is. It would be also fine if you propose a whole different solution instead of modifying my given predicate.

Finding Length of List in Prolog

I'm running Prolog and trying to write a small function returning the length of a list:
len([],0).
len([XS], Y) :-
len([X|XS], M),
Y is M+1.
My logic is that the recursive call should include the tail of the list (XS) and increase 1 to the previous length (Y is M+1.)
This always returns false.
Any thoughts?
Here is a general methodology for debugging and testing Prolog predicates:
Start with the most general query!
Think of it: In Prolog you do not need to make up some test data. You don't even need to understand a predicate at all: Just hand in free variables! That is always a professional move!
So in your case, that's
?- len(L,N).
L = [], N = 0
; loops.
Your definition is not that bad as you claim: At least, it is true for the empty list.
Now, maybe look at the compiler warnings you probably received:
Warning: user://1:11:
Singleton variables: [X]
Next read the recursive rule in the direction of the arrow :- that is, right-to-left:
Provided len([X|Xs], M) is true and Y is M+1 is true, provided all that is true, we can conclude that
len([XS], Y) is true as well. So you are always concluding something about a list of length 1 ([Xs]).
You need to reformulate this to len([X|Xs], M) :- len(Xs, N), Y is M+1.
And here is another strategy:
Generalize your program
By removing goals, we can generalize a program1. Here is my favorite way to do it. By adding a predicate (*)/1 like so:
:- op(950,fy, *).
*_.
Now, let's remove all goals from your program:
len([],0).
len([XS], Y) :-
* len([X|XS], M),
* Y is M+1.
What we have now is a generalization. Once again, we will look at the answers of the most general query:
?- len(L, N).
L = [], N = 0
; L = [_].
What? len/2 is only true for lists of length 0 and 1. That means, even len([1,2], N) fails! So now we know for sure: something in the visible remaining part of the program has to be fixed. In fact, [XS] just describes lists of length 1. So this has to be removed...
Fine print:
1 Certain restrictions apply. Essentially, your program has to be a pure, monotonic program.

Prolog Finding Kth element in a list

I am trying write a predicate in prolog to find Kth element in a list.
Example:
?- element_at(X,[a,b,c,d,e],3).
X = c
my code as follows
k_ele(X,[X|_],1).
k_ele(X,[_|T],Y) :- Y > 1,Y is Y - 1, k_ele(X,T,Y).
But no use, I found solution on Internet as
element_at(X,[X|_],1).
element_at(X,[_|L],K) :- K > 1, K1 is K - 1, element_at(X,L,K1).
Which is same as my logic except they used one extra variable K1.
What is wrong with my code, why I need another variable ?
The reason your code does not work is that unification is not an assignment. When you say
Y is Y - 1
you are trying to unify a value of Y with the value of Y-1, which is mathematically impossible. This is roughly the same as saying 4 is 3 or 1001 is 1000. The entire condition fails, leading to the failure to find the element in the list.
The fixed solution that you have found on the internet introduces a separate variable K1, which is unified with K - 1. This is very much doable: K1 gets the value to which K-1 evaluates, the condition succeeds, and the clause moves on to the recursive invocation part.
Because variables in prolog are write-once critters. Having been [assigned|unified with|bound to] a non-variable value, it ceases to be variable. It is henceforth that value. Unlike more...conventional...programming languages, once bound, the only way to reassign a prolog variable is to backtrack through the assignment and undo it.
It should be noted, though, that a variable can be unified with another variable: Given a predicate something like
foo(X,Y) :- X = Y .
and something like
shazam(X,Y) :- bar(X,Y) , X = 3.
will result in both X and Y being 3. Having been unified, X and Y are both the same variable, albeit with different names.
I imagine you're working with the exercises from this link:
http://www.ic.unicamp.br/~meidanis/courses/problemas-prolog/
Note, in my opinion the original solution is not the best either.
For example, a query:
element_at(X,[a,b,c],Y).
would crash, even if there are 3 solutions:
X = a, Y = 1;
X = b, Y = 2;
X = c, Y = 3;
I believe writing in an alternative way:
element_at(H, [H | _], 1).
element_at(H, [_ | T], N) :- element_at(H, T, NMinus1), N is NMinus1 + 1.
would give better results. It's less efficient as one can not apply the last call optimization, but the logic becomes more general.