Related
I'm working on this prolog assignment where I must parse an user-inputted list of string characters (specifically "u"), and determine if all the elements are equal to the string "u". If they are, then it returns the number of elements, if not, it returns false. For example:
uA(-Length,+String,+Leftover) //Prototype
?- uA(L,["u","u","u"],[]).
L = 3 .
?- uA(L,["u","u","d"],[]).
false.
I have a decent grasp on how prolog works, but I'm confused about how lists operate. Any help would be greatly appreciated. Thanks!
Edit: I made some headway with the sort function (thank you!) but I've run into a separate problem.
uA(Length, String) :-
sort(String, [_]),
member("u", String),
length(String, Length).
This does mostly what I need it to, however, when I run it:
?- uA(L, ["u", "u", "u"]).
L = 3 ;
L = 3 ;
L = 3.
Is there any way to make it such that it only prints L = 3 once? Thanks!
If you want to state that all list items are equal, there is no need to sort the list first.
Simply use library predicate maplist/2 together with the builtin predicate (=)/2:
?- maplist(=(X), Xs).
Xs = []
; Xs = [X]
; Xs = [X, X]
; Xs = [X, X, X]
; Xs = [X, X, X, X]
… % ... and so on ...
First of all, be careful with double-quoted terms in Prolog. Their interpretation depends on the value of the standard double_quotes flag. The most portable value of this flag is codes, which makes e.g. "123" being interpreted as [49,50,51]. Other possible values of this flag are atom and chars. Some Prolog systems, e.g. SWI-Prolog, also support a string value.
But back to your question. A quick way to check that all elements in a ground list are equal is to use the standard sort/2 predicate (which eliminates duplicated elements). For example:
| ?- sort(["u","u","u"], [_]).
yes
| ?- sort(["u","u","d"], [_]).
no
As [_] unifies with any singleton list, the call only succeeds if the the sorting results in a list with a single element, which only happens for a non-empty ground list if all its elements are equal. Note that this solution is independent of the value of the double_quotes flag. Note also that you need to deal with an empty list separately.
My approach is to check if every element in the list is the same or not (by checking if the head of the list and it's adjacent element is the same or not). If same then return True else false. Then calculate the length of every element is the same in the list.
isEqual([X,Y]):- X == Y , !.
isEqual([H,H1|T]):- H == H1 , isEqual([H1|T]).
len([],0).
len([_|T],L):- len(T,L1) , L is L1+1.
goal(X):- isEqual(X) , len(X,Length) , write('Length = ') , write(Length).
OUTPUT
?- goal(["u","u","u"]).
Length = 3
true
?- goal(["u","u","a"]).
false
you can do it this way. Hope this helps you.
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.
I have a Matrix like this:
[[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]]
and I need a list that saves the index when a row is not [0,0,0].
So the result in my example should be:
[2,3,4,5,7,8]
I have problems to program recursive in Prolog because i haven`t really figured out how it works.
Would it maybe help to first convert the matrix into a vector? It doesn't matter if its [1,0,0] or [0,1,0]. The only thing that is important is that it's not [0,0,0].
Since you want to describe a list, you could opt to use DCGs. They usually yield quite easily readable code:
matrix_indices(M,I) :-
phrase(indices(M,0),I). % the list I is described by the DCG indices//2
indices([],_) --> % if M is empty
[]. % I is empty too
indices([[0,0,0]|Ls],I0) --> % if the head of M is [0,0,0]
{I1 is I0+1}, % the current index is calculated but is not in I
indices(Ls,I1). % the same holds for the tail
indices([L|Ls],I0) --> % if the head of the list
{dif(L,[0,0,0])}, % differs from [0,0,0]
{I1 is I0+1}, % the current index is calculated
[I1], % and is in the list I
indices(Ls,I1). % the same holds for the tail
Note that the goals enclosed in braces are normal Prolog-goals. If you query this predicate with your given example you get the desired solution:
?- matrix_indices([[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],I).
I = [2,3,4,5,7,8] ? ;
no
You can also use the predicate in the other direction but you have to ask for a concrete length or prefix a goal length(M,_)to prevent the predicate from looping. For example the query...
?- length(M,_), matrix_indices(M,[2,3,4,5,7,8]).
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0],[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ?
.
.
.
... yields infinitely many answers as expected.
How I would solve using findall/3 and nth1/3:
?- M = [[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],
findall(I, (nth1(I,M,E), E\=[0,0,0]), L).
L = [2, 3, 4, 5, 7, 8]
I am trying to return the first k elements of a list xs. For example take 2 [1; 2; 3] should output [1; 2].
I wrote a function, but instead of returning the first k elements it returns the last k elements, and instead of returning the whole list if k equals to length of the list, it fails.
This is my code
let rec take k = function
|[] -> failwith "take"
|x :: xs -> if k = List.length xs then xs else take (List.length xs - k) xs
How can I fix this?
You need to answer the two basic questions for writing recursively:
What cases are so trivial that the answer is obvious?
If given a non-trivial case, how do I make a smaller instance of it, so I can get the answer for that smaller instance just by using this same function that I am writing1, and then find my full answer from that smaller answer by some simple steps?
For this problem, the trivial cases (I would say) are when k is 0, and when the given list is an empty list.
For the non trivial case, the insight seems to be that I can get the first k elements of a list (for k > 0) by getting the first (k - 1) elements of the tail of the list, and then adding the head of the original list onto that 2.
This is not what your code does, so that's basically why it doesn't work :-)
As a side comment, I wouldn't consider it an error to ask for the first 0 elements of any list (including the empty list).
1 and the essence of recursion method is to assume you already have it at your disposal.
2 this is because of the identity length (x :: xs) = 1 + length xs.
Just a different way :
let take k l =
let v =Array.of_list l in
let v'=Array.make k 0 in
Array.blit v 0 v' 0 k;
Array.to_list v';;
test:
# take 2 [1;2;3];;
- : int list = [1; 2]
# take 0 [1;2;3];;
- : int list = []
# take 4 [1;2;3];;
Exception: Invalid_argument "Array.blit".
Im trying to swap the first and last element of a list in haskell. I've tried pattern matchnig, expressions, functions, etc. This is my last attempt:
cambio xs = [ cabeza++([x]++cola)|x<-xs, cabeza <- init x, cola <- last x, drop 1 x, drop 0 ([init x])]
My compiler throws the next error:
Couldn't match expected type `Bool' with actual type `[a0]'
In the return type of a call of `drop'
In the expression: drop 1 x
In a stmt of a list comprehension: drop 1 x
Can anyone help me? I've tried to do this for 2 days
Here are a few hints:
You can't solve this with list comprehension.
Identify the base (trivial) cases - empty list and list of one element. Write equations that cover those cases.
In all other cases the length of the input list will be >= 2. The list you want is
[z] ++ xs ++ [a]
where z is the last element, a the first element of the input list and xs the middle part of the input.
Now tell me (or yourself), how long will xs be, if the length of the input string was k?
Write the equation that covers the case of lists with more than 1 elements. You can use functions like head, last, length, drop or take.
I think that lists aren't the best data structure for doing this, but here it goes:
swap list = last list : (init . tail $ list) ++ [head list]
This is going to require traversing the list and will be slow on long lists. This is the nature of linked lists.
Updated with base cases from question asker:
swap [] = []
swap [a] = [a]
swap list = last list : (init . tail $ list) ++ [head list]
This is a fairly straightforward thing to do, especially with the standard list functions:
swapfl [] = []
swapfl [x] = [x]
swapfl (x:xs) = (last xs : init xs) ++ [x]
Or without them (although this is less readable and usually not done, and not recommended):
swapfl' [] = []
swapfl' [x] = [x]
swapfl' (x:xs) = let (f, g) = sw x xs in f:g
where sw k [y] = (y, [k])
sw k (y:ys) = let (n, m) = sw k ys in (n, y:m)
Or one of many other ways.
I hope that helps ... I know I didn't do much explaining, but frankly, it's hard to tell exactly what you were having trouble with as far as this function is concerned, seeing as you also seem to completely misunderstand list comprehensions. I think it might be most beneficial if I explain those instead?
And why this cant be solved with a list comprehension? I tough they were like functions but with a different form
Not really. List comprehensions are useful for easily defining lists, and they're very closely related to set-builder notation in mathematics. That would not be useful for this particular application, because, while they're very good at modifying the elements of a list, comprehensions are not very good at reordering lists.
In a comprehension, you have three parts: the definition of an element in the list, one or more input lists, and zero or more predicates:
[ definition | x <- input1, y <- input2, predicate1, predicate2 ]
The definition describes a single element of the list we're making, in terms of the variables the arrows in the inputs are pointing at (x and y in this case). Each input has a list on the right of the arrow, and a variable on the left. Each element in the list we're making is built by extracting each combination of elements from the input lists into those variables, and evaluating the definition part using those values. For example:
[ x + y | x <- [1, 3], y <- [2, 4] ]
This generates:
[1 + 2, 1 + 4, 3 + 2, 3 + 4] == [3, 5, 5, 7]
Also, you can include predicates, which are like filters. Each predicate is a boolean expression defined in terms of the input elements, and each is evaluated whenever a new list element is. If any of the predicates come out to be false, those elements aren't put in the list we're making.
Let's look at your code:
cambio xs = [ cabeza++([x]++cola) | x<-xs, cabeza <- init x, cola <- last x,
drop 1 x, drop 0 ([init x])]
The inputs for this comprehension are x <- xs, cabeza <- init x, and cola <- last x. The first one means that every element in xs is going to be used to define elements for the new list, and each element is going to be named x. The other two don't make any sense, because init and last are type [a] -> a, but are on the right side of the arrow and so must be lists, and x must be an element of a list because it's on the left side of its arrow, so in order for this to even compile, xs would have to be type [[[a]]], which I'm sure is not what you want.
The predicates you used are drop 1 x and drop 0 [init x]. I kind of understand what you were trying to do with the first one, dropping the first element of the list, but that wouldn't work because x is just an element of the list, not the list itself. In the second one, drop 0 means "remove zero elements from the beginning of the following list", which would do absolutely nothing. In either case, putting something like that in a predicate wouldn't work because the predicate needs to be a boolean value, which is why you got the compiler error. Here's an example:
pos xs = [ x | x <- xs, x >= 0 ]
This function takes a list of numbers, removes all the negative numbers, and returns the result. The predicate is the x >= 0, which is a boolean expression. If the expression evaluates to false, the element being evaluated is filtered out of the resulting list.
The element definition you used is cabeza ++ [x] ++ cola. This means "Each element in the resulting list is itself a list, made up of all elements in the list cabeza, followed by a single element that contains x, followed by all elements in the list cola", which seems like the opposite of what you were going for. Remember that the part before the pipe character defines a single element, not the list itself. Also, note that putting square brackets around a variable creates a new list that contains that variable, and only that variable. If you say y = [x], this means that y contains a single element x, and doesn't say anything about whether x is a list or not.
I hope that helps clear some things up.