Haskell permutations with the length of the output list - haskell

I have such code for creating permutations:
--unique permutation
perm :: [t] -> [[t]]
perm [] = [[]]
perm (x:xs) = [(y:zs) | (y,ys) <- views (x:xs), zs <- perm ys]
--create all possible views
views :: [t] -> [(t,[t])]
views [] = []
views (x:xs) = ((x,xs) : [ (y,(x:ys)) | (y,ys) <- views xs ])
However I want to limit the output to a certain length. For example, it should take a parameter specifying the number of elements in the ouput of the permutation. I want to create k distinct permutations drawn from a list [0..9].
So, for example, if k will be equal to 3, then the output should be something like this:[1,2,3], [9,8,7], [0,6,8] etc..
Right now if i pass [0..9] to the function it will generate a list with permutations of length 10. I am struggling to come up with a solution.
In the end, the function should look like perm k list
Thank you!
It is connected with this question: Verbal Arithmetics in Haskell (SEND + MORE = MONEY)

Do you mean something like this?
import Data.List (permutations)
choose n list = concatMap permutations $ choose' list [] where
choose' [] r = if length r == n then [r] else []
choose' (x:xs) r | length r == n = [r]
| otherwise = choose' xs (x:r)
++ choose' xs r
Output:
*Main> choose 2 [0..5]
[[1,0],[0,1],[2,0],[0,2],[3,0],[0,3],[4,0],[0,4],[5,0],[0,5],[2,1]
,[1,2],[3,1],[1,3],[4,1],[1,4],[5,1],[1,5],[3,2],[2,3],[4,2],[2,4]
,[5,2],[2,5],[4,3],[3,4],[5,3],[3,5],[5,4],[4,5]]

Will replicateM do what you need?
Prelude Control.Monad> take 10 $ replicateM 3 [0..9]
[[0,0,0],[0,0,1],[0,0,2],[0,0,3],[0,0,4],[0,0,5],[0,0,6],[0,0,7],[0,0,8],[0,0,9]]
Prelude Control.Monad> take 10 $ replicateM 4 [1,3,3,7]
[[1,1,1,1],[1,1,1,3],[1,1,1,3],[1,1,1,7],[1,1,3,1],[1,1,3,3],[1,1,3,3],[1,1,3,7],[1,1,3,1],[1,1,3,3]]
Prelude Control.Monad> take 10 $ replicateM 2 [4,2]
[[4,4],[4,2],[2,4],[2,2]]

Related

Haskell: Make a List of 6-digit lists that gives you all the combinations of [0..9]

So for a project, I have to create, as said a list of lists of all combinations from 0 to 9 but is limited to a list of 6 numbers.
So that the result looks something like this:
Solutions ==> [[0,0,0,0,0,0], [0,0,0,0,0,1], ... [9,9,9,9,9,9]]
Thanks
The text of your question seem to imply that you want to get all possibilities, with digit repetitions allowed and reordered versions being regarded as distinct. That is, you want the Cartesian product of 6 times [0..9].
If so, you are led to expect 106 = 1 million possibilities. As mentioned in the comment by Will Ness, you can use either mapM (const [0..9]) [1..6] or the equivalent expression replicateM 6 [0..9].
Checking under the ghci interpreter:
λ>
λ> import Control.Monad (replicateM)
λ>
λ> length $ mapM (const [0..9]) [1..6]
1000000
λ>
λ> length $ replicateM 6 [0..9]
1000000
λ>
λ> length $ sequence (replicate 6 [0..9])
1000000
λ>
λ> replicateM 6 [0..9] == sequence (replicate 6 [0..9])
True
λ>
However, there is a performance caveat.
Library function replicateM is highly polymorphic. Acting as the list cartesian product is not its sole role in life. Unfortunately, this happens to have the sad side effect that its peak memory consumption can become quite large (exponentially large) if you go beyond toy-sized examples.
Fortunately, there is a known workaround based on an idea by K. A. Buhr:
cartesianProduct :: [[α]] -> [[α]]
cartesianProduct xss =
map reverse (helper (reverse xss))
where
helper :: [[α]] -> [[α]]
helper [] = [[]]
helper (ys:zss) = [y:zs | zs <- helper zss, y <- ys]
Checking:
λ>
λ> length $ cartesianProduct (replicate 6 [0..9])
1000000
λ>
λ> cartesianProduct (replicate 6 [0..9]) == replicateM 6 [0..9]
True
λ>
Alternatively, let's now assume you do need actual combinations. That is, you no longer allow repeated digits, and you want to regard [1,2,3,4,5,6] as identical to [6,5,4,3,2,1]. The number of possibilities thus becomes much smaller.
In such a case, you can use a more restrictive version of the code for cartesianProduct:
combis :: Ord α => Int -> [α] -> [[α]]
combis k xs =
let xss = replicate k xs
helper1 :: [[α]] -> [[α]]
helper1 [] = [[]]
helper1 (ys:zss) = [y:zs | zs <- helper1 zss, y <- ys,
(null zs) || (head zs < y)]
in
map reverse (helper1 xss)
Checking:
λ>
λ> cb = combis 6 [0..9]
λ> length cb
210
λ> div (10*9*8*7*6*5) (6*5*4*3*2*1)
210
λ> take 10 cb
[[0,1,2,3,4,5],[0,1,2,3,4,6],[0,1,2,3,4,7],[0,1,2,3,4,8],[0,1,2,3,4,9],[0,1,2,3,5,6],[0,1,2,3,5,7],[0,1,2,3,5,8],[0,1,2,3,5,9],[0,1,2,3,6,7]]
λ>
Check it out:
ghci> [ [x,y] | x <- [1..3], y <- [1..3] ]
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
Your move.
First of all, what your asking about is not a list of permutations but a list of all possible combinations. In a permutation each digit would appear only once.
Basing on the example you gave one can write a recursive function, generating all combinations for lists of n elements:
combinationsMaker n = if n == 1 then [[digit] | digit <- [0..9]] else [sublist ++ [digit] | digit <- [0..9], sublist <- combinationsMaker (n-1)]
My Haskell is quite rusty, so it might not be the most idiomatic. Possibly one would like to factor out the allowed elements, so its not only all digits.

How can I optimize this shuffle function?

I am trying to create a generic (type-o-polymophism?) shuffle function with Haskell. I needs to sort a couple of thousand elements in a fraction of a second to be deemed "good enough".
evens :: [a] -> [a]
evens l = [l !! i | i <- [0,2..(length l) - 1]]
odds :: [a] -> [a]
odds l = [l !! i | i <- [1,3..(length l) - 1]]
shuffle :: [a] -> [a]
shuffle s | length s == 1 = s
| otherwise = l ++ shuffle r
where l = evens s
r = odds s
A perfect shuffle can be implemented as
perfectShuffle = concat . transpose . chunksOf 2
The speed improvements will come from:
Not calculating the length of the list repeatedly.
Not building up a chain of (++) inefficiently, which will require repeated traversals of the list and give an O(n2) runtime.
Example output:
λ> perfectShuffle [1..10]
[1,3,5,7,9,2,4,6,8,10]
chunksOf is available in the split package. transpose is in Data.List in base.
You should avoid indexing repeatedly into the same list with !! like you do in
evens l = [l !! i | i <- [0,2..(length l) - 1]] -- bad
This takes O(n^2) time where n is the length of l, since l !! i takes O(i) time.
Instead just write something like this:
evens [] = []
evens (x:xs) = x : odds xs
odds xs = evens (drop 1 xs)
Your shuffle itself is fine.

split an arbitrary set s into two subsets of fixed size

In order to split an arbitrary set s into two subsets l and r, in which l has a fixed size n, I have written the following code:
parts :: Int -> [a] -> [([a], [a])]
parts n ls = (filter len . f) ls
where len (lhs,rhs) = length lhs==n -- the condition that the left subset is of fixed size n
f [] = [([],[])]
f (x:xs) = [ (x:l,r) | (l,r)<-f xs] ++ [ (l,x:r) | (l,r)<-f xs]
Here is a sample of its effect. Evaluating parts 2 "12345" yields:
[ ("12","345")
, ("13","245")
, ("14","235")
, ("15","234")
, ("23","145")
, ("24","135")
, ("25","134")
, ("34","125")
, ("35","124")
, ("45","123")
]
Please notice that my solution enumerates all subsets and then filters out the desired ones. I suppose the subsets function is familiar to you:
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = map (x:) (subsets xs) ++ subsets xs
Personally, I find my solution disappointing. It filters the correct answers from a larger set. My question to the reader is:
Can you come up with a function that is equivalent to parts, but produces the answer directly without this a-posteriory filter?
Inspired by subsets, you might end up with
import Control.Arrow (first, second)
-- first f (x,y) = (f x, y) ; second f (x, y) = (x, f y)
parts n xs = parts' 0 xs where
parts' l (x:xs) | l < n = map (first (x:)) (parts' (l + 1) xs) ++ -- 1a
map (second (x:)) (parts' l xs) -- 1b
parts' l xs | l == n = [([],xs)] -- 2
parts' _ _ = [] -- 3
l contains the length of the first pair so far. As long as the pair isn't yet long enough, we take the first element of the list, and append it to all first elements in our pairs (1a). We're also going to map it onto the second elements (1b). Note that in this case the length of the first pairs didn't increase.
When the first pairs just happen to be long enough (2), we're going to put all other elements into the second half of the pair.
When the requirements for the guards do not hold (list exhausted), we return [] (3). This approach also retains the relative ordering of elements:
> parts 2 "12345"
[
("12","345"),
("13","245"),
("14","235"),
("15","234"),
("23","145"),
("24","135"),
("25","134"),
("34","125"),
("35","124"),
("45","123")
]
This approach will also work on infinite lists:
> map (second (const "...")) $ take 5 $ parts 3 [1..]
[([1,2,3],"..."),([1,2,4],"..."),([1,2,5],"..."),([1,2,6],"..."),([1,2,7],"...")]
(The second elements in the pairs will still be infinite lists)
Ok this is what I came up with:
parts :: Int -> [a] -> [([a],[a])]
parts n list = parts' 0 (length list) [] [] list where
parts' _ _ ls rs [] = [(ls,rs)]
parts' n' l ls rs as#(x:xs) | n' >= n = [(reverse ls, reverse rs ++ as)]
| n' + l <= n = [(reverse ls ++ as, reverse rs)]
| otherwise = parts' (n' + 1) (l - 1) (x : ls) rs xs
++ parts' n' (l - 1) ls (x : rs) xs
If it doesn't matter if the elements of the subsets are in the same order as they were in the original set, then you can remove the four uses of reverse.
Sliding split can be done using zipWith of inits and tails. For each split produce the solution for a smaller sublist, and append the element at the point of split to all such solutions.
parts 0 xs = [([],xs)]
parts n xs = concat $ zipWith f (inits xs) (init $ tails xs) where
f hs (h:ts) = [(h:t', hs++ts') | (t', ts') <- parts (n-1) ts]
-- f hs [] not possible - init $ tails xs does not produce empty lists

Subdividing a list in haskell

How can I group a list into smaller lists of equal length (except last sublist) in haskell?
E.g.
sublist 3 [1,2,3,4,5,6,7,8] -> [[1,2,3],[4,5,6],[7,8]]
sublist 2 [4,1,6,1,7,3,5,3] -> [[4,1],[6,1],[7,3],[5,3]]
Try:
import Data.List.Split
> splitEvery 2 [4,1,6,1,7,3,5,3]
[[4,1],[6,1],[7,3],[5,3]]
If you want to stick to prelude, you can pull this off using splitAt.
splitEvery _ [] = []
splitEvery n list = first : (splitEvery n rest)
where
(first,rest) = splitAt n list
The Data.List.Split module has a chunksOf function for this:
Prelude> import Data.List.Split
Prelude Data.List.Split> chunksOf 3 [1,2,3,4,5,6,7,8,9,10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
Prelude Data.List.Split> chunksOf 3 []
[]
It seemed to be installed by default on my machine, but you might need to get it with cabal.
Another solution that I like is:
splitEvery :: Int -> [a] -> [[a]]
splitEvery n = takeWhile (not.null) . map (take n) . iterate (drop n)
Yet another solution:
split :: Int -> [a] -> [[a]]
split n = unfoldr (\s -> if null s then Nothing else Just $ splitAt n s)
I know this is old, but since this seems to be a post for people who are fairly new to Haskell, I felt like posting my solution too. I tried to solve this problem by using Prelude, only:
sublist :: Int -> [a] -> [[a]]
sublist n ls
| n <= 0 || null ls = []
| otherwise = take n ls:sublist n (drop n ls)
Testing
sublist 3 [1,2,3,4,5,6] -- λ> [[1,2,3], [4,5,6]]
sublist 5 [1,2,3] -- λ> [[1,2,3]]
sublist (-1) [1,2,3] -- λ> []
sublist 20 [] -- λ> []
This list comprehension uses tails. Since the first set starts with one, all subsequent subsets start with an odd number.
ts n ls = [take n l|l<-init$tails ls,odd (head l)]
n is the size-of-sublist, ls is the source list.
The next one will take any list and include unmatched elements. It is set up to do pairs only. It is obvious how to parameterize it to do any chunk size.
np ls = [take 2 (drop a ls)|a<-[0,2..(length ls)-1]]
Just include an n as a parameter and replace the 2's in the formula, one after take and one after 0 in the generator.

creating infinte reverse add then sort

i'm trying to create an infinte reverse add then sort list in haskell
r = map head (iterate rlist [2..])
rlist (x:xs) = [x : xs | x <- xs , x quick $ p+x ]
where p = reverse x
quick [] = []
quick (x:xs) = quick [u |u <- xs, u < x] ++ [x] ++ quick [u | u <- xs , u >= x]
but its not working, any suggestions?
thanks.
I'm not sure how you expect your code to work (perhaps there was a problem when you posted the code). Namely, part of your list comprehension ... x quick $ p + x makes no sense to me - x isn't a function and it isn't a list so reverse x also makes no sense. For that matter you have shadowed x - notice the x in your list comprehension isn't the same as the x in ratslist (x:xs).
A simple solution does exist using read and show to convert the numbers to lists of digits (well, characters, but it works) and back:
import Data.List
myRats = 1 : map ratify myRats
-- Alternatively: myRats = iterate ratify 1
ratify :: Integer -> Integer
ratify n = sortRat (n + rev n)
where
rev = read . reverse . show
sortRat = read . sort . show
And in GHCi:
*Main Data.List> take 10 myRats
[1,2,4,8,16,77,145,668,1345,6677]
I don't quite get your problem, but according to your example, I'd try
rats x = sort (zipWith (+) x (reverse x))
like in rats [1,4,5] which equals [6,6,8].

Resources