簡體   English   中英

所有可能的子列表都是成對的

[英]All possible sublists as pairs haskell

有點不確定如何恰當地說這個,所以請耐心等待!

給定一個列表[1,2,3,4]我想要一個列表元組列表,如下所示:[([1],[2,3,4]),([1,2],[3,4] ]),([1,2,3],[4])]。

問題的B部分也是在子列表中獲得所有可能的排序。 所以在第一個元組的情況下,我希望2 3 4按順序243,324,432,423 ......

是的,我喜歡非決定論。

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 ,但我不確定這樣更清楚。

A部分:使用非決定論monad! (列表monad)

第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]]

B部分:使用非確定性monad更多!

splitPairsPerms xs = do (ys, zs) <- splitPairs xs
                        ys' <- permutations ys
                        zs' <- permutations zs
                        return $ (ys', zs')

進一步的想法

列表monad非常適合編寫簡單函數並將它們轉換為非確定性函數。 然而,這種方法並不總是最有效的。 在我的例子中,我使用了length xssplitAt i xs ,它們必須遍歷列表的長度才能執行它們的任務(好吧, splitAt只需要遍歷索引i,這平均是索引i的一半長度。列表,如此相同的數量級)。 如果性能很重要,那么轉換為序列可能是明智之舉。

在第一種情況下,您只需將列表拆分為兩個。 第一個將包含輸入,第二個將最初為空。 然后從第一個元素中取出一個元素,並將其放在第二個元素中,直到第一個元素為空。

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

我最喜歡Dan的答案,因為我認為這是最有啟發性的。 但是,如果你擔心splitPair的效率,那么我認為這個相當直接的定義工作正常:

splitPair :: [a] -> [([a],[a])]
splitPair []       = ([],[]) : []
splitPair a@(x:xs) = ([],a)  : map (\(u,v)->(x:u,v)) (splitPair xs)

此定義與原始問題陳述略有不同,因為它返回第一個或最后一個列表為空的對。 這與大多數列表函數(如tailsinits的定義更為一致:

> 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],[])]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM