I'm new to prolog and I'm trying to figure out how I can use if/else statement and recursion. To illustrate, I've written a simple prolog program. The program is useless (in that its functionality is useless), but it helps me illustrate my problem. The program takes a list, examines the head of the list, sees if it's the last element; if it's not, it adds the head to a temporary list variable and runs the program in recursion using the Tail of the list. It should output the list in the end. The program:
gothrough([H|T], B, C):-
append(B,H,B),
( (T == [])
-> C=B
; gothrough(T, B, C)
).
The call: gothrough([sample, phrase, here], [], C).
Expected output: C = [sample, phrase, here]
Current output: no
Any help on what I'm doing wrong?
Thanks!
From your comments I understand that you misunderstand how append (and Prolog in general) works.
This is not true at all: "if B = [yesterday] and H = [today], then append(B, H, B) = [yesterday, today]".
append(B, H, B) means "appending H to B yields B again". This is only possible if H is an empty list.
The key thing to understand is that both Bs in append(B, H, B) are the same, they must have the same value. It's like variables in algebra - all Xs in an equation means the same value.
You should use different name for the output variable, like append(B, H, Bnew) - then it will make more sense.
The first problem is append(B, H, B) which for most inputs doesn't make sense.
The second problem is that the consequence and alternative of an if-then-else, i.e. the parts after -> and after ; must both be Prolog goals (statements). C is not a goal. You may have meant C=B, though it's hard to tell because I find it hard to understand what your program is doing.
You're getting a no because append(B,H,B) fails unless H is []; remember, these are clauses, not assignments. And since you never bind anything to C, it will never have a value in it if your statement was ever proved.
This will accomplish your task:
gothrough([],L,L).
gothrough([H|T], B, C) :- gothrough(T,B,Cx), append([H],Cx,C).
This can be done even more simply:
gothrough([], []).
gothrough([H|T], [H|X]) :-
gothrough(T, X).
The first rule matches your empty list condition, which then forces the end of the recursion/the list to be built.
The second rule matches everything but an empty list, in which case the head H is appended onto X, where X is the result of list obtained from recursing the tail. ie. you don't need to use the append predicate - list appending is built into prolog.
?- gothrough([simple, phrase, here], X).
X = [simple, phrase, here].
This solution also uses one less variable.
Related
I'm still learning the concept of recursion.
I want to add elements of one list to the head of another list recursively while eliminating any duplicates. The code I used work fine for an atom. This is the code without recursion:
insert(H,L,[H|L]):-
not(member(H,L)).
insert(H,L,L):-
member(H,L).
However when I try recursion, I don't get the expected output. I understand I'm writing the insert/3 predicate wrong.
insert([H|T],[H1|T1],[H,H1|T1]):-
not(member(H,[H1|T1])):-
insert(T,[H,H1|T1],L).
insert([H|T],[H1|T1],[H1|T1]):-
member(H,[H1|T1]),
insert(T,[H1|T1],L).
insert([],L,L).
I'd appreciate any ideas on how to rectify the error in the above code.
Your original insert could be composed within another "insert_all" clause. For example...
% insert_all(NEW_ELEMENTS, LIST_TO_ADD_ELEMENTS_TO, OUTPUT)
insert_all([], O, O).
insert_all([X | T], I, O) :-
insert(X, I, ITMP),
insert_all(T, ITMP, O).
Example output:
1 ?- insert_all([a,b,c], [1,2,c], O).
O = [b, a, 1, 2, c].
You could also simplify insert to avoid having to do the not(member(...)) check...
insert(H,L,L):-
member(H,L), !.
insert(H,L,[H|L]).
The "cut" tells Prolog to not bother trying alternatives if preceding sub-clauses in the insert clause succeed. So if member fails, it will just do the second clause.
I'm a new programmer and using Haskell. I've found a line of code called find that matches up a String with its corresponding pair in a list. Like so
find a b = [x|(y,x) <- b, a==y]
I don't understand fully what this program is saying, for the list comprehension, as I've never seen the x|(y,x) used in such a way before, I've mainly seen it used as x|x or x|x^2. So, does this mean that find the string A, from your input list B = a list comprehension of x, where x is a pair of (String, Char) from your B, and for which the y equals your inputted a? A little confused here.
I would pronounce that comprehension
The list of all x such that (y, x) is drawn from b and a == y.
Another way to read it, more sequentially:
Draw pairs (y, x) from b. For each such pair, check whether a == y. If so, produce x; otherwise, move on to the next one.
I should also note that the variable names are a bit confusing. It's idiomatic in Haskell to give lists or other containers plural names. So something more like
find a abs = [x | (y, x) <- abs, a == y]
You seem to view "x|x" as a thing. Rather, list comprehensions work like this:
[ expression to return | stuff to iterate over ]
What your example basically says is "draw (x, y) from b, throw away anything which doesn't satisfy a == y, and then return x".
Lets give you an example in order to visualize it:
find a b = [x|(y,x) <- b, a==y]
Let a=2, b=[(1,3),(2,4),(3,5),(2,7)]
(y,x) will get each of (1,3),(2,4),(3,5),(2,7) as a couple and check if the first element equals 2 (we said that a equals 2). If True, the function will return the second element of that couple - x, and put it in a list with the rest of the answers.
So the output for that function would be [4,7]
I've written a small Prolog program that's supposed to check a list and see whether the head Ha is greater than K, if it is, it is supposed to append it to a list R and after checking the whole list give back R which then would consist of bigger than K integers.
This code returns R = [].
teilliste_grK([],_,_).
teilliste_grK([Ha|Ta], K, R) :-
Ha =< K,
teilliste_grK(Ta,K,R).
teilliste_grK([Ha|Ta], K, R) :-
Ha > K,
append(R, [Ha], C),
teilliste_grK(Ta, K, C).
Any help?
you should write out how do you want to call this predicate with some sample data, and what you're expecting to get back from it. this is important. :)
okay, I'll do it: teilliste_grK([1,4,2,5,3,6],3,X) should succeed, instantiating X to [4,5,6], correct? Now try to see which of the clauses does it match with.
So it matches with the second, 1 is indeed =< 3, and the last line says, continue without the head element (that was smaller than the given K), and whatever R we get from there, is our R as well – R is R after all.
Good. So when we come to 4 next, what happens? The 2nd clause matches but is then rejected with 4 =< 2. Good. On to the third clause.
Again it matches, and the inequality holds, but then you do something strange. You first say that C is one element longer than R, and that C you get from the shorter list - the tail Ta of your input. Whatever you set your R in the final clause (the first one), this just can't be.
You want your C to be shorter than R, which is to start with the same head Ha which has just passed the test, so the arguments just need to be put in a different order:
append([Ha], C, R),
(you can write this shorter and simpler though, without any call to append – what is it?).
Now what about that final (3rd, i.e. []) clause? If you call teilliste_grK([],3,X), what should X be?
Ho do I square numbers in a list in prolog?
The list can contain numbers, atoms and lists.
for example: [a,b,2,3,4,[3],[c,d,9]] and the answer should be [a,b,4,9,16,[3],[c,d,9]].
As we see in the answer it should be a shallow squaring of the values in the list.
2->4
3->9
4->16
What I have tried so far,
square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).
X will contain squared values. Base case is when empty list is received. I check if head (A) is a number then I go ahead square the number and change A to A * A. Then go ahead and call the square function for remaining part B.
Please suggest where I am doing wrong.
EDIT: Correct answer as follows. By aBathologist. Please read his comment for detailed explanation.
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
And
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).
We're defining a predicate which describes the relationship between one list, A, and another list, B: B should have all the same elements as A, except that any number in A should be squared in B.
Where you've gone wrong:
Your ground condition, square([],X), says that when A is empty, then B is anything (so, for instance, even something like square([], 15) is true). But this doesn't capture the meaning we're after, since the second argument should be a list with the same number of members as the first. That is, when the first list is empty then the second list should be empty.
The same problem occurs with your recursive rule, since, at each iteration, an undetermined variable is passed along, and there is never anything said about the relationship between the first list and the second.
This rule will only succeed if the first element of alist is a number. In the case where the first element is, e.g., a (like in your example), number(a) will be false. Since there are no additional rules for the predicate, it will simply be false unless every member of the first list is a number.
Variables in Prolog must always have the same, consistent value throughout the context in which they appear. They function like variables in arithmetic formula. The formula a + b - b = a is true for any values of a and b but *only if a and b are each assigned one, consistent value throughout the equation. The same is true in Prolog statements of the form <variable> is <expression>. What you've written says a = a * a which cannot be the case.
*What you're definition says is, roughly, this: The list B is a squared version of the list A if A is an empty list and B is anything OR if the first element of A is a number, and that number is equal to itself squared, and B is a squared version of the rest of A.
Here's one possible solution:
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
Notice that this definition is able to establish a meaningful relationship between the two lists by having them either share variables, or contain elements related by a chain of relations between variables (i.e., SqrdL is related to L by virtue of being L * L). This definition has one more clause then yours, which enables it to take account of the members of a list which are not numbers: those are added to the second list unaltered.
An alternative definition, using If-Then-Else notation for cleaner expression, would be the following:
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).
I'm trying to write a predicate is_multi(M), defined as:
every element of M has the form X / N, where X is an atom, and N is an integer greater than 0;
M does not contain two elements with the same atom, for what
is_multi([]).
is_multi([a / 2, b / 2]).
are satisfied, but
is_multi([a, b/2]).
is_multi([a/0, b/2]).
is_multi([a/2, 2/4])
is_multi([a/2, b/3, a/2])
is_multi([a/3, b/-4, c/1])
are not.
Here's what I have written so far:
is_multi(M) :- M = [].
is_multi(M) :-
M = [Head|Tail],
Head = X/N,
integer(N),
N > 0,
is_multi(Tail).
But it does not compare two elements if with the same atom. For example, is_multi([a/2, a/3]) is not satisfied. I got stuck for one day with this; could somebody give me some hints?
First, you can simplify your code considerably by moving some of your unifications from the body to the head.
is_multi([]).
is_multi([X/N|Tail]) :-
integer(N), N > 0,
is_multi(Tail).
Cleaning it up reveals one thing you're not doing here which is in your spec is checking that X is an atom. Fix by adding atom(X) to the body.
OK, so this takes care of the basic form, but doesn't ensure that the atoms do not repeat. The simplest thing to do would be to split this into two checks, one that checks that each item is well-formed, and one that checks that the list is well-formed. In fact, I would be inclined to use maplist/2 with a predicate that checks a single element. But all you really have to do is something like this:
is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).
This just says that the empty list is valid, and if the tail is valid, a list is valid if X over something doesn't occur in the tail.
If that's all you wanted, stop reading there. If you want to refactor, this is how I would approach it:
well_formed(X/N) :- atom(X), integer(N), N > 0.
no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).
is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
Just to complete Daniel's instructive answer (+1 by me), I want to showcase how your task could be solved by means of some library predicates:
is_multi(L) :-
forall(select(E, L, R),
(E = A/N, atom(A), integer(N), N > 0, \+memberchk(A/_, R))).