【问题标题】:elem function of no limit list无限制列表的elem函数
【发布时间】:2011-08-22 15:13:54
【问题描述】:

列表理解haskell

 paar = [(a,b) | a<-[a | a<-[1..], mod a 3 == 0], b<-[b*b | b<-[1..]]]

a = 除数 3 b = 正方形

元素必须按公平顺序构建。

测试 >elem (9, 9801) 必须为真

我的错误

Main> elem (9, 9801) 测试

错误 - 垃圾回收未能回收足够的空间

如何使用康托尔的对角线参数来实现这一点?

谢谢

【问题讨论】:

  • 建议:安装 Haskell 平台,可在此处获得:hackage.haskell.org/platform
  • paar 的含义非常不清楚。你希望这个列表是什么样子的? elem 函数确实适用于无限列表(只要答案是True),但是生成列表的方式会导致问题。

标签: list haskell arguments list-comprehension diagonal


【解决方案1】:

不太确定您的目标是什么,但这就是您的代码崩溃的原因。

Prelude> let paar = [(a,b) | a<-[a | a<-[1..], mod a 3 == 0], b<-[b*b | b<-[1..]]]
Prelude> take 10 paar
[(3,1),(3,4),(3,9),(3,16),(3,25),(3,36),(3,49),(3,64),(3,81),(3,100)]

请注意,您正在生成所有 (3, ?) 对,然后再生成其他任何对。 elem 函数通过从头开始线性搜索此列表来工作。由于(3, ?) 对的数量是无限的,因此您永远无法到达(9, ?) 对。

此外,您的代码可能会在某处保留paar,从而阻止它被垃圾收集。这导致elem (9, 9801) paar 不仅占用了无限的时间,而且占用了无限的空间,从而导致了您所描述的崩溃。

最终,您可能需要采取另一种方法来解决您的问题。例如,像这样:

elemPaar :: (Integer, Integer) -> Bool
elemPaar (a, b) = mod a 3 == 0 && isSquare b
    where isSquare = ...

或者找出一些其他的搜索策略,而不是通过无限列表直接线性搜索。

【讨论】:

    【解决方案2】:

    这是同一列表的另一种排序方式(根据 hammar 的建议):

    -- the integer points along the diagonals of slope -1 on the cartesian plane,
    -- organized by x-intercept
    -- diagonals = [ (0,0), (1,0), (0,1), (2,0), (1,1), (0,2), ...
    diagonals = [ (n-i, i)  | n <- [0..], i <- [0..n] ]
    
    -- the multiples of three paired with the squares
    paar = [ (3*x, y^2) | (x,y) <- diagonals ]
    

    在行动中:

    ghci> take 10 diagonals
    [(0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3)]
    ghci> take 10 paar
    [(0,0),(3,0),(0,1),(6,0),(3,1),(0,4),(9,0),(6,1),(3,4),(0,9)]
    ghci> elem (9, 9801) paar
    True
    

    通过使用对角线路径遍历所有可能的值,我们保证我们在有限的时间内到达每个有限的点(尽管有些点仍然在内存的范围之外)。

    正如 hammar 在他的评论中指出的那样,这还不够,因为它仍然需要 获得False 答案的无限时间。

    但是,我们对 paar 的元素有一个顺序,即 (3*a,b^2)(3*c,d^2) 之前 a + b &lt; c + d。所以要确定给定的对 (x,y) 是否在 paar 中,我们只需要检查 将(p,q)p/3 + sqrt q &lt;= x/3 + sqrt y 配对。

    为避免使用Floating 数字,我们可以使用稍微宽松的条件,即p &lt;= x || q &lt;= y。 当然p &gt; x &amp;&amp; q &gt; y 暗示p/3 + sqrt q &gt; x/3 + sqrt y,所以这仍然会包括任何可能的解决方案,并且保证会终止。

    所以我们可以在里面构建这个检查

    -- check only a finite number of elements so we can get a False result as well
    isElem (p, q) = elem (p,q) $ takeWhile (\(a,b) -> a <= p || b <= q) paar
    

    并使用它:

    ghci> isElem (9,9801)
    True
    ghci> isElem (9,9802)
    False
    ghci> isElem (10,9801)
    False
    

    【讨论】:

    • 不错的解决方案,但这里仍然存在问题。如果您正在搜索列表中不在 中的内容,您将永远继续搜索。您需要elem 的变体,它知道何时可以安全停止。
    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 2022-01-20
    • 2016-11-25
    • 2011-12-12
    • 1970-01-01
    • 2012-02-04
    相关资源
    最近更新 更多