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.
Related
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.
I'm starting learning haskell and i'm stuck in a problem.
I read from the standard input a string like "1234" or "azer"
and I want to make a list like ["123", "234", "341", "412"] or ["aze", "zer", "era", "raz"].
I probably must use map but i don't know how to proceed.
Is someone can help me to do that ? Thanks
Let's start with a list, [1..4]. Let's repeat it for eternity:
>>> cycle [1..4]
[1,2,3,4,1,2,3,4,1,2,3,4,...
Now let's take a slice of it, at say, the 2nd index:
>>> take 4 $ drop (2-1) $ cycle [1..4]
[2,3,4,1]
We can generalize this by naming a function:
slice n = take 4 $ drop n $ cycle [1..4]
To obtain all possible cyclic permutations, we only need to sample n from 1 to 4:
>>> map slice [1..4]
[[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4]]
Now, how can we make this work with an arbitrary string? Let's redefine slice to accept a string:
slice s n = take (length s) $ drop n $ cycle s
And so our cyclic permutations function can be defined as follows:
cyclicPerms s = map (slice s) [1..(length s)]
Testing:
>>> cyclicPerms "abcde"
["bcdea","cdeab","deabc","eabcd","abcde"]
I had originally posted an answer totally misunderstanding the specification. I, like a Haskell enumeration, read only the first two numbers so I thought it continued as such. Oops. In any event I just adapted a chunks function I wrote to produce the repetitions. When I get home, I think I have another that cycles lists. I'll post it as well if it's not the same. Who knows.
This function allows you to specify the chunk size as well as the list.
cychnks n ls = [take n.drop x$ls2|(x,y) <-zip [0..] ls]
where ls2 = ls++ls
cychnks 5 "abcde"
["abcde","bcdea","cdeab","deabc","eabcd"]
cychnks 3 "abcde"
["abc","bcd","cde","dea","eab"]
I have a list of subjects and weekdays, on which the subject is taught.
subjectDays = [("maths", ["mon", "tue"]),
("science", ["mon", "wed"])]
Now I would like to generate a list of combinations.
The result should look like as follows.
combinations = [[("maths", "mon"), ("science", "mon")],
[("maths", "mon"), ("science", "wed")]
-- etc.
]
Could anyone please help me to write a function in Haskell to produce the above result?
Thank you very much in advance.
From the comment below, I now realize that you want another output than the one I initially understood.
Essentially, you want each sublist to contain each subject (exactly once), paired with one of its days. If we still take combinations as defined below (the "wrong" output) we realize that we want to take the "cartesian product" of all the lists inside combinations. This cartesian product can be obtained using Control.Monad.sequence.
wantedCombinations = sequence combinations
Here's a hint.
First, write a function to expand a single pair of yours into a list.
combs :: (a,[b]) -> [(a,b)]
combs (subject, days) = ...
This could be solved using a list comprehension, for instance. Or map.
Then, we can apply combs to each pair in the list
combinations = map combs subjectDays
write an expand function to work on a single pair
expand :: (a,[b]) -> [(a,b)]
expand (x,[]) = []
expand (x,(y:ys)) = (x,y): expand (x,ys)
map to your structure and take the transpose (Data.List)
transpose $ map expand subjectDays
i was given a homework in Haskell in which i should program a module, which helps detect prime numbers from a list, say :
[2,3,4,5,6,7,8,9,10]
For the homework, I should iterate through every elements of this list, and eliminate all of it's multiples. Example, I go at number 2, I should eliminate 4,6,8,10. Then go to number 3 and delete 6 and 9, and so on until the end, return the list with prime numbers only.
I have an idea of using function map, but I'm stuck at this place (I'm pretty new to Haskell, though)
Yes, it is my homework, but no, i don't have to do it, it's just practicing. So I'm thankful for any help.
Instead of using a map (I don't think that's possible without doing some pre-processing), you can roll your own function:
sieveWith _ [] = []
sieveWith ss (x:xs) | any ((==) 0 . mod x) ss = sieveWith ss xs
| otherwise = x : (sieveWith (x:ss) xs)
and:
sieve = sieveWith []
Now if you call sieve:
*Main> sieve [2,3,4,5,6,7,8,9,10]
[2,3,5,7]
The function works with a variable (the first one) that is passed through the function calls and each time a value is picked, added to the list. A value is picked if no modulo operation on the variable list yields a zero (second guard). In case any of the modulo's yields zero, the value is simply omitted.
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 :) )