I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.
positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (x',i) <- zip xs [0..], x == x']
i need to create a Test function for the positions function, which passes the quickcheck.
Does someone has an idea?
A possible test could perform the following operations:
randomly generate xs, ys :: [Int] and y :: Int
define list = xs ++ y : ys
test length xs `elem` positions y list
You might also want to write tests for missing elements.
That being said, it's weird to craft tests from the code. One should design test using the specification used to write the code instead. Otherwise, if the code has some quirks, they end up in tests as well: instead of checking for what the code should do, we check for what the code does, which can be pointless.
Good question! I had a bit of trouble with this too when I started using QuickCheck, but as I used it more I started to get a feel for what sort of properties you should test. Often, a good place to start is to think about what sort of relationships should hold between the input(s) and output. Your function finds the indices of an element in a list; now what properties should hold in this case? Here's two which I can think of:
The list of indices should have the same number of elements as there are occurrences of the value in the list.
Each index should correspond to the correct value.
And here's an outline of how these properties could be tested:
Generate a random list, apply positions to it, then count the number of indices returned and check that it matches with the number of occurrences of the searched value.
Generate a random list, then apply positions to it and check that the element at each of the returned indices is the value which was searched for.
I also think that #chi's answer makes a good point in saying that you should design tests from the specification rather than the code; this ties in with what I was saying above, in that a specification can help you find relationships between input(s) and output which may not be immediately apparent from the code.
So i am currently working with Haskell at my college, but kinda struggling with pattern-matching and to be more specific i'll give the program, that i am to solve:
My function is awaiting a list of lists ( with each list containing at least 3 elements ) and in each list the second element is replaced with the number of the third element.
Example:
[[1,2,3],[4,5,6,7],[8,9,10]] should become [[1,3,3],[4,6,6,7],[8,10,10]
So far I've made the following:
f [] = []
f [[x]] = []
f [[x,y]] = []
f [[x,y,z]] = [[x,z,z]]
f ([x,y,z]:xs) = [x,z,z]:f(xs)
My questions are:
How can i identify, that some lists may contain more than 3 elements and that the list must remain the same, only the 2nd element changes.
How can i make the recursion, so that it handles exceptions (for example the first list has 4 elements).
Thank you in advance!
It may help to first write the function that swaps the second value in a list with the third.
swap (x:y:z:rest) = x:z:z:rest
swap xs = xs
In the above, x:y:z:rest matches a list of at least length 3. The value of rest, since it is at the end of the pattern, will match any kind of list, both empty and full. The second pattern match of xs is a catch-all for any other type of list, which will just return the same list if it is less than 3 items long.
From there, you can write f in terms of mapping over the outer list and applying swap:
f = map swap
I am very bad at wording things, so please bear with me.
I am doing a problem that requires me to generate all possible numbers in the form of a lists of lists, in Haskell.
For example if I have x = 3 and y = 2, I have to generate a list of lists like this:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
x and y are passed into the function and it has to work with any nonzero positive integers x and y.
I am completely lost and have no idea how to even begin.
For anyone kind enough to help me, please try to keep any math-heavy explanations as easy to understand as possible. I am really not good at math.
Assuming that this is homework, I'll give you the part of the answer, and show you how I think through this sort of problem. It's helpful to experiment in GHCi, and build up the pieces we need. One thing we need is to be able to generate a list of numbers from 1 through y. Suppose y is 7. Then:
λ> [1..7]
[1,2,3,4,5,6,7]
But as you'll see in a moment, what we really need is not a simple list, but a list of lists that we can build on. Like this:
λ> map (:[]) [1..7]
[[1],[2],[3],[4],[5],[6],[7]]
This basically says to take each element in the array, and prepend it to the empty list []. So now we can write a function to do this for us.
makeListOfLists y = map (:[]) [1..y]
Next, we need a way to prepend a new element to every element in a list of lists. Something like this:
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
(I used 99 here instead of, say, 1, so that you can easily see where the numbers come from.) So we could write a function to do that:
prepend x yss = map (x:) yss
Ultimately, we want to be able to take a list and a list of lists, and invoke prepend on every element in the list to every element in the list of lists. We can do that using the map function again. But as it turns out, it will be a little easier to do that if we switch the order of the arguments to prepend, like this:
prepend2 yss x = map (x:) yss
Then we can do something like this:
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
So now we can write that function:
supermap xs yss = map (prepend2 yss) xs
Using your example, if x=2 and y=3, then the answer we need is:
λ> let yss = makeListOfLists 3
λ> supermap [1..3] yss
[[[1,1],[1,2],[1,3]],[[2,1],[2,2],[2,3]],[[3,1],[3,2],[3,3]]]
(If that was all we needed, we could have done this more easily using a list comprehension. But since we need to be able to do this for an arbitrary x, a list comprehension won't work.)
Hopefully you can take it from here, and extend it to arbitrary x.
For the specific x, as already mentioned, the list comprehension would do the trick, assuming that x equals 3, one would write the following:
generate y = [[a,b,c] | a<-[1..y], b<-[1..y], c <-[1..y]]
But life gets much more complicated when x is not predetermined. I don't have much experience of programming in Haskell, I'm not acquainted with library functions and my approach is far from being the most efficient solution, so don't judge it too harshly.
My solution consists of two functions:
strip [] = []
strip (h:t) = h ++ strip t
populate y 2 = strip( map (\a-> map (:a:[]) [1..y]) [1..y])
populate y x = strip( map (\a-> map (:a) [1..y]) ( populate y ( x - 1) ))
strip is defined for the nested lists. By merging the list-items it reduces the hierarchy so to speak. For example calling
strip [[1],[2],[3]]
generates the output:
[1,2,3]
populate is the tricky one.
On the last step of the recursion, when the second argument equals to 2, the function maps each item of [1..y] with every element of the same list into a new list. For example
map (\a-> map (:a:[]) [1..2]) [1..2])
generates the output:
[[[1,1],[2,1]],[[1,2],[2,2]]]
and the strip function turns it into:
[[1,1],[2,1],[1,2],[2,2]]
As for the initial step of the recursion, when x is more than 2, populate does almost the same thing except this time it maps the items of the list with the list generated by the recursive call. And Finally:
populate 2 3
gives us the desired result:
[[1,1,1],[2,1,1],[1,2,1],[2,2,1],[1,1,2],[2,1,2],[1,2,2],[2,2,2]]
As I mentioned above, this approach is neither the most efficient nor the most readable one, but I think it solves the problem. In fact, theoritically the only way of solving this without the heavy usage of recursion would be building the string with list comprehension statement in it and than compiling that string dynamically, which, according to my short experience, as a programmer, is never a good solution.
I was trying to write a function to get all subsequences of a list that are of size n, but I'm not sure how to go about it.
I was thinking that I could probably use the built-in Data.List.subsequences and just filter out the lists that are not of size n, but it seems like a rather roundabout and inefficient way of doing it, and I'd rather not do that if I can avoid it, so I'm wondering if you have any ideas?
I want it to be something like this type
subseqofsize :: Int -> [a] -> [[a]]
For further clarification, here's an example of what I'm looking for:
subseqofsize 2 [1,2,3,3]
[[1,2],[1,3],[2,3],[1,3],[2,3],[3,3]]
Also, I don't care about the order of anything.
I'm assuming that this is homework, or that you are otherwise doing this as an exercise to learn, so I'll give you an outline of what the solution looks like instead of spoon-feeding you the correct answer.
Anyway, this is a recursion question.
There are two base cases:
sublistofsize 0 _ = ...
sublistofsize _ [] = ...
Then there are two recursive steps:
sublistofsize n (x : xs) = sublistsThatStartWithX ++ sublistsThatDon'tStartWithX
where sublistsThatStartWithX = ...
sublistsThatDon'tStartWithX = ...
Remember that the definitions of the base cases need to work appropriately with the definitions in the recursive cases. Think carefully: don't just assume that the base cases both result in an empty list.
Does this help?
You can think about this mathematically: to compute the sublists of size k, we can look at one element x of the list; either the sublists contain x, or they don't. In the former case, the sublist consists of x and then k-1 elements chosen from the remaining elements. In the latter case, the sublists consist of k elements chosen from the elements that aren't x. This lends itself to a (fairly) simple recursive definition.
(There are very very strong similarities to the recursive formula for binomial coefficients, which is expected.)
(Edit: removed code, per dave4420's reasons :) )