Haskell:最多n个非相同整数的所有非相同无序列表的列表

时间:2017-07-31 14:54:43

标签: list haskell

我正在尝试将一组单词划分为相同长度的单词的等价类,其中给定的字符,例如' e',特别是位置。

(我正在尝试实施此处指定的邪恶刽子手游戏:http://nifty.stanford.edu/2011/schwarz-evil-hangman/。)

例如,给定'""感觉"和"剥离"会在同一个等级的班级,但是" bed"并且"吃"不会是。不包含给定字符的单词构成了自己的等价类。

对于指定这种等价类的每个条件,我将计算满足它的字库中的字数。 (然后选择最大尺寸的等价类)

起初,我考虑使用列表推导,但我不确定如何向GHC指定我想要的内容。

例如,能够执行以下操作会很好:

[[x1...xn] | x1,..,xn <- [1..10], xn> x(n-1) > ... > x1]

xns形成按索引排序的有序数据类型。 n是任意参数。

因此,我希望收到有关如何通过列表推导或其他方式获得创建条件所需列表的建议。

编辑:

要提供其他详细信息,请参阅以下代码片段:

let countList = [(countSatisfy ((char, letterPositionList):listConditions) wordset , (char, letterPositionList) ) | letterPositionList <- foldl (++) [] (map (increasingSequences 0 (wl-1)) [1..(wl-1)] )  ]
let countAndSelectedList = getMaxCount countList

使用以下功能(感谢Daniel增加序列表功能):

countSatisfy :: [(Char, [Int])] -> [[Char]] -> Int
countSatisfy listConditions wordset =
    foldl (+) 0 $ map (boolToBin . (foldl (&&) True)) (map (mapf (map checkCondTrue listConditions)) wordset)

getMaxCount :: [(Int, (Char, [Int]))] -> (Int, (Char, [Int]))
getMaxCount ((x1, y1):(x2, y2):xs)
    |x1 > x2 = getMaxCount ((x1, y1):xs)
    |otherwise = getMaxCount ((x2, y2):xs)
getMaxCount ((x, y):[]) = (x, y)
getMaxCount [] = error "No conditions satisfied"

mapf :: [(a -> b)] -> a -> [b]
mapf (f:fs) x = f x : mapf fs x
mapf [] _ = []

checkCondTrue :: (Char, [Int]) -> [Char] -> Bool
checkCondTrue (letterChar, letterPositionList) word = 
    (foldl (&&) True $ map (letterChar ==) (map (word !!) letterPositionList)) && (not (letterChar `elem` (removeItemsInPositionList (quicksort letterPositionList) word) ) )

increasingSequences :: Int -> Int -> Int -> [[Int]]
increasingSequences min max 0 = [[]]
increasingSequences min max count | max-min+1 < count = []
increasingSequences min max count = do
    h <- [min .. max]
    t <- increasingSequences (h+1) max (count-1)
return (h:t)

正如所预料的那样,这种方法确实会受到性能的影响。我没有预料到多次出现单个字母导致的组合爆炸。代码也很糟糕,因为这是我在Haskell中的第一个程序。

1 个答案:

答案 0 :(得分:1)

您可以这样做:

increasingSequences :: Int -> Int -> Int -> [[Int]]
increasingSequences min max 0 = [[]]
increasingSequences min max count | max-min+1 < count = []
increasingSequences min max count = do
    h <- [min .. max]
    t <- increasingSequences (h+1) max (count-1)
    return (h:t)

在ghci:

> increasingSequences 1 5 3
[[1,2,3],[1,2,4],[1,2,5],[1,3,4],[1,3,5],[1,4,5],[2,3,4],[2,3,5],[2,4,5],[3,4,5]]

或者像这样,如果你只是打算用它来索引另一个列表:

import Data.List

subsequencesOfLength n xs = go n xs where
    go 0 _ = [[]]
    go n xs = do
        h:rest <- tails xs
        t <- go (n-1) rest
        return (h:t)

在ghci:

> subsequencesOfLength 3 "abcde"
["abc","abd","abe","acd","ace","ade","bcd","bce","bde","cde"]

但我不清楚这些中的任何一个是否有用。在我看来,你更愿意直接从字符串和字母计算等价类的定义特征,例如。

type Class = [Bool]

classCharacteristic :: Char -> String -> Class
classCharacteristic c s = map (c==) s

然后生成所有等价类很容易:

import qualified Data.Map as M

classes :: Char -> [String] -> [[String]]
classes c ss = id
    . M.elems
    . M.fromListWith (++)
    $ [(classCharacteristic c s, [s]) | s <- ss]

在ghci:

> classes 'e' ["echo", "heal", "best", "lazy"]
[["lazy"],["best","heal"],["echo"]]

(如果我自己写这篇文章,我甚至可能会避免定义Class和内联classCharacteristic - 将它们分开只是为了教学法。)