Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何改进Haskell组合算法?_Haskell_Ghc - Fatal编程技术网

如何改进Haskell组合算法?

如何改进Haskell组合算法?,haskell,ghc,Haskell,Ghc,如何改进以下问题的解决方案?它能在时间和空间上更有效吗?有空间泄漏吗 问题: 给定一份输入的宇航员列表,生成一份成对的宇航员列表,这样成对的宇航员就不会有来自同一国家的两名宇航员。假设输入有一个带有唯一标识符的宇航员列表 data Astronaut = Astronaut { identifier :: Int, country :: String } deriving (Eq) astronautPairs :: [Astronaut] -> [(Astronaut, Astrona

如何改进以下问题的解决方案?它能在时间和空间上更有效吗?有空间泄漏吗

问题: 给定一份输入的
宇航员列表
,生成一份成对的
宇航员列表
,这样成对的宇航员就不会有来自同一国家的两名
宇航员。假设输入有一个带有唯一标识符的宇航员列表

data Astronaut = Astronaut { identifier :: Int, country :: String } deriving (Eq)

astronautPairs :: [Astronaut] -> [(Astronaut, Astronaut)]
astronautPairs xs = foldl accumulatePairs [] [(a, b) | a <- xs, b <- xs, country a /= country b]
    where
        accumulatePairs pairs pair = if hasPair pair pairs then pairs else pair:pairs
        hasPair pair@(a,b) ((c,d):xs) = a == d && b == c || hasPair pair xs
        hasPair _ [] = False
数据宇航员=宇航员{identifier::Int,country::String}派生(Eq)
宇航员对::[宇航员]->[(宇航员,宇航员)]

让我们从实现细节后退一步,思考一下您试图实现的目标:

制作一份成对的
宇航员
s的列表,这样成对的宇航员就不会有来自同一国家的两名
宇航员
s

你似乎可以假设每个宇航员在名单中只出现一次

解决这个问题的一个有效方法是从按国家划分列表开始。一个自然的方法是构建一个包含每个国家所有宇航员列表的
HashMap字符串[Int]

import qualified Data.HashMap.Strict as HMS
import Data.HashMap.Strict (HashMap)

divideAstronauts :: [Astronaut] -> HashMap String [Int]
divideAstronauts = foldl' go mempty where
  go hm (Astronaut ident cntry) = HMS.insertWith (++) cntry [ident] hm
现在,您可以将程序的其余部分分为两个步骤:

  • 选择所有国家/地区对
  • 对于每一对国家,选择每一对来自其中一个国家的宇航员

  • 与其消除翻转对,为什么不首先避免生成它们。是我们生成了它们,是吗

    import Data.List (tails)
    
    astronautPairs :: [Astronaut] -> [(Astronaut, Astronaut)]
    astronautPairs xs = [ (y,z) | (y:ys) <- tails xs, z <- .... , country y /= country .... ]
    
    导入数据列表(尾部)
    宇航员对::[宇航员]->[(宇航员,宇航员)]
    
    你认为它应该占用多少空间?一旦你决定了,只需在一个大的输入上运行你的代码,看看你的内存使用情况是否匹配(这里可以使用
    -stderr
    运行时选项)。然后告诉我们它是否有空间泄漏。您可能喜欢中的
    pairs
    函数。是否同时生成
    (a,b)
    (b,a)
    ,或者你打算代表两人团队吗?是的,我觉得这很正确。这个团队的空间复杂度是多少?当然,时间是二次的。空间将取决于最终列表的长度。没有什么可以阻止编译器生成除O(n)外还可以在O(1)空间中工作的代码必须完全存在于内存中的输入列表的大小——也就是说,这不是一个在线算法,即使在访问最后一个元素时,GC也无法回收列表的头元素。