不确定如何正确地说出来,所以请耐心等待!
给定一个列表[1,2,3,4]我想要一个列表元组列表,如下所示:[([1],[2,3,4]),([1,2],[ 3,4]),([1,2,3],[4])。
问题的B部分也是在子列表中获得所有可能的排序。所以在第一个元组的情况下,我希望2 3 4按顺序243,324,432,423 ......
是的,我喜欢非决定论。
答案 0 :(得分:4)
import Data.List (inits, tails, permutations)
import Control.Arrow (first, second)
parta :: [a] -> [([a], [a])]
parta [] = []
parta xs = init . tail $ zip (inits xs) (tails xs)
对于b部分,我不确定您是想要[([1],[2,3,4]), ([1],[3,4,2]), ...]
还是[([1],[[2,3,4],[3,4,2],...]), ...]
。如果是后者,那么
partb :: [a] -> [([a], [[a]])]
partb = map (second permutations) . parta
编辑:哦,但你想要前者。在那种情况下
partb :: [a] -> [([a], [a])]
partb = map (uncurry zip . first repeat . second permutations) . parta
最终编辑:由于我已经使用了Control.Arrow中的一些函数,我会注意到 zip (inits xs) (tails xs)
也可以写成(inits &&& tails) xs
,但我不是确定它更清楚。
答案 1 :(得分:3)
第1步:找到一个合适的方法,将列表拆分为两个列表的元组。
Hoogling [a] -> ([a], [a])
我们找到splitAt :: Int -> [a] -> ([a],[a])
import Data.List (splitAt, permutations) -- we'll need to permute for part B
第2步:将其写入一个索引。
splitPair xs = splitAt 1 xs
第3步:让许多索引无法确定地工作。
splitPairs xs = do index <- [1..length xs-1]
return $ splitAt index xs
了解单选功能可以轻松转换为非确定性选择功能吗? (这与列表理解一样容易编写:)
splitPairs' xs = [splitAt i xs | i <- [1..length xs-1]]
splitPairsPerms xs = do (ys, zs) <- splitPairs xs
ys' <- permutations ys
zs' <- permutations zs
return $ (ys', zs')
list monad非常适合编写简单函数并将它们转换为非确定性函数。然而,这种方法并不总是最有效的。在我的示例中,我使用了length xs
和splitAt i xs
之类的操作,它们必须遍历列表的长度才能执行任务(好吧,splitAt
只需要遍历索引i,它平均是列表长度的一半,所以数量级相同)。如果性能很重要,那么转换为序列可能是明智的。
答案 2 :(得分:2)
在第一种情况下,您只需将列表拆分为两个。第一个将包含输入,第二个将最初为空。比从第一个元素中取一个元素,然后将它放在第二个元素中,直到第一个元素为空。
magic x = magic' x []
where
magic' [] y = [[[], y]]
magic' (x:xs) y = [[reverse y, (x:xs)]] ++ magic' xs (x:y)
下一个问题:它只是元素的简单排列。
perm x = perm' x [] []
where
perm' [] [] prefix = [prefix]
perm' [] rest prefix = []
perm' (x:xs) rest prefix =
perm' (xs++rest) [] (x:prefix) ++
perm' xs (x:rest) prefix
答案 3 :(得分:1)
我最喜欢丹的答案,因为我认为这是最有启发性的。但是,如果您担心splitPair
的效率,那么我认为这个相当直接的定义可以正常工作:
splitPair :: [a] -> [([a],[a])]
splitPair [] = ([],[]) : []
splitPair a@(x:xs) = ([],a) : map (\(u,v)->(x:u,v)) (splitPair xs)
这个定义与原始问题陈述有所不同,它返回第一个或最后一个列表为空的对。这与大多数列表函数的定义更为一致,例如tails
或inits
:
> splitPair [1,2,3,4]
[([],[1,2,3,4]),([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4]),([1,2,3,4],[])]