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]
Related
I am writing a function that will take a list of list and merge it into sorted pairs of list. For example [[1],[9],[8],[7],[4],[5],[6]] would return [[1,9],[7,8],[4,5],[6]]. This is my first attempt at SML. I keep getting this error: operator and operand don't agree [overload conflict].
fun mergePass[] = []
| mergePass(x::[]) = x::[]
| mergePass(x::y::Z) =
if x<y
then (x # y)::mergePass(Z)
else (y # x)::mergePass(Z);
Edit: If mergePass is called on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]].
This merge function takes two sorted lists
fun merge([],y) = y
| merge(x,[]) = x
| merge(a::x,b::y) =
if a < b then a::merge(x,b::y)
else b::merge(a::x,y);
You seem reasonably close. A few hints/remarks:
1) Aesthetically, using nil in one line and [] in others seems odd. Either use all nil or use all []
2) Since the input are lists of lists, in x::y::z, the identifiers x and y would be lists of integers, rather than individual integers. Thus, x<y wouldn't make sense. You can't compare lists of integers using <.
3) Your problem description strongly suggests that the inner-lists are all 1-element lists. Thus you could use the pattern [x]::[y]::z to allow you to compare x and y. In this case, x#y could be replaced by [x,y]
4) If the inner lists are allowed to be of arbitrary size, then your code needs major revision and would probably require a full-fledged sort function to sort the result of concatenating pairs of inner lists. Also, in this case, the single list in the one inner list case should probably be sorted.
5) You have a typo: mergeP isn't mergePass.
On Edit:
If the sublists are each sorted (and the name of the overall function perhaps suggests this) then you need a function called e.g. merge which will take two sorted lists and combine them into a single sorted list. If this is for a class and you have already seen a merge function as an example (perhaps in a discussion of merge-sort) -- just use that. Otherwise you will have to write your own before you write this function. Once you have the merge function, skip the part of comparing x and y and instead have something as simple as:
| mergePass (xs::ys::zss) = (merge xs ys) :: mergePass zss
If the sublists are not merged, then you will need a full-fledged sort in which case you would use something like:
| mergePass (xs::ys::zss) = sort(xs # ys) :: mergePass zss
I'm coding in haskell and want to know how find a certain element in mutiple list.
Here an example let say:
x = [(1,2,3,4,5),
(3,4,5,6,6),
(5,6,2,1,1),
(1,2,5,6,2)];
Let say I want to find the 3rd element of each list.
So the program will print out 4,6,1,6
I know about the !! but when I do something like x !! 3, it prints out the third row(1,2,5,6,2).
I want it so it print out the 3rd element of each list.
What you've provided is not actually a list of lists, but a list of tuples. Tuples have a special type based on the number and type of their elements, so the type of your x above is [(Int,Int,Int,Int,Int)].
Unlike lists, which allow us to extract values by index with the !! operator (ex. [1,2,3] !! 1 = 2), in order to extract specific values from a tuple we must pattern match the entire tuple, giving some name to the value we wish to extract and using it in our return value. To extract the fourth value from a tuple of holding 5 values, we could write a function like this:
f (a,b,c,d,e) = d
Or, as an anonymous function (because, if we are only going to use it when mapping over the list, it's nice to not bother assigning it a name):
(\(a,b,c,d,e) -> d)
Since we only care about the fourth value, we can choose to discard all others (you said third but meant index 3 -> 4th term above?):
(\(_,_,_,x,_) -> x)
Now we have a list of such tuples, and we'll want to apply it to each. We can do this with map, which will apply the function to each and return a list of the third value from each tuple:
f xs = map (\(_,_,_,x,_) -> x) xs
Or, with eta-reduction:
f = map (\(_,_,_,x,_) -> x)
Example usage:
gchi>> f [(1,2,3,4,5),(3,4,5,6,6),(5,6,2,1,1),(1,2,5,6,2)]
[4,6,1,6]
I've been trying to solve the following problem for a while now, but can't seem to find the right solution.
Lets say there is a function test(X,Y,Z) such that X is a single pair of numbers, Y is a list of pairs, and Z is the resulting list of transitive pairs.
For example:
test((1,5), [(7,3),(5,2),(5,9)], Z).
Z = [(1,2),(1,9)]
(because of transitivity 1->5->2 and 1->5->9)
So far I've managed to create the following code:
test(_,[],_):- false.
test((X1,C),[(C,Y2)|_],(X1,Y2)).
test((X1,X2),[_|YT],Result) :- test((X1,X2),YT,Result).
It returns each individual result pair like so:
Z = (1, 2) ;
Z = (1, 9) ;
But I can't seem to return them all into a single list like in the example above:
Z = [(1,2),(1,9)]
Any help would be greatly appreciated.
I think the problem is that you're not building the list of transitive pairs. You're just returning a single pair as the third argument of test/3.
Here's one possible solution:
I made a predicate to handle comparing pairs and describing their transitive marriage, so that i didn't have to juggle those tuples in the subsequent rules:
transit((X,T), (T,Y), (X,Y)).
Then it's just a matter of standard list processing with recursive predicates:
t(_, [], []).
t(X, [T|ToTransit], [Y|Transited]) :-
transit(X,T,Y),
t(X,ToTransit,Transited).
t(X, [T|ToTransit], Transited) :-
\+ transit(X,T,_),
t(X,ToTransit, Transited).
Of course, once you have a predicate like transit/3 that defines the relation, you can also do something like
findall( TP,
( member(T, [(2,2), (2,5), (1,5)]), transit((1,2), T, TP) ),
Tps).
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.
This is another prolog task that I can't solve at this moment. I have to write a predicat p(X,Y), where X is list of lists of number and Y is a list of numbers. The predicat has to verify:
1) if X can be presented as a concatenation between 2 elements from Y.
2) X has a odd number of elements.
3) Sum of all elements in X is last element in Y.
Maybe as a separate tasks 2, 3 could be written easy. Problem is at 1)
Thank you in advance. I feel sorry for posting such an easy tasks, but prolog really drives me crazy. I have read all my lections over and over again. But the situation is similar to this:
school: 3+x=5, x = ?
exam: cos(x+y+z) + lim (5x+y)/t = .... If you know what I mean. Thank you once again!
Checking for concatenations is done with append/3, which is more commonly used to build them but like many Prolog predicates works "in the opposite direction" as well. More specifically, append(A,B,C) checks whether C is the concatenation of A and B. So,
member(A, Y),
member(B, Y),
append(A, B, X)
checks whether there is a element A in Y and a element B in Y such that their concatenation unifies with X.
(Note that this does not check whether A and B are distinct elements of Y.)