2

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)

Community
  • 1
  • 1

2 Answers2

5

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]]
Asocia
  • 5,935
  • 2
  • 21
  • 46
גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
1

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]]
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Yes, it definitely helps to achieve this task, however I am learning and would like to know how I can modify the existing code to produce the same result. Using an already defined function is quite easy, but won't help me understand the problem more deeply. Anyway, thanks! – Vladyslav Babych Jan 31 '16 at 20:48
  • 3
    `replicateM` produces all possible variations, not permutations. – Alexey Shmalko Jan 31 '16 at 22:38
  • 1
    @AlexeyShmalko Terminology aside, doesn't it fit the requirements described in the OP? – Mark Seemann Feb 01 '16 at 06:11
  • 1
    It doesn't. It generates different answer. – Alexey Shmalko Feb 01 '16 at 11:22
  • 1
    ReplicateM n produces a "cartesian product" X^n where X is a certain set. It's true that it's not permutation. But the OP is not really clear about that in his question. The output [1,2,3], [9,8,7], [0,6,8] can hardly be considered as a permutation. – Zacharie 007 Feb 02 '16 at 12:44