list comprehension haskell
paar = [(a,b) | a<-[a | a<-[1..], mod a 3 == 0], b<-[b*b | b<-[1..]]]
a =除数3 b =方
元素必须以公平的顺序构建。
测试&gt; elem(9,9801)必须为True
我的错误
主&GT; elem(9,9801)测试
错误 - 垃圾收集无法回收足够的空间
如何使用Cantor的对角线参数实现这一点?
THX
答案 0 :(得分:7)
不太确定你的目标是什么,但这就是你的代码爆炸的原因。
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 = ...
或者另外找出一些其他搜索策略,而不是通过无限列表直接线性搜索。
答案 1 :(得分:4)
这是同一列表的备用顺序(根据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
通过使用对角线路径迭代所有可能的值,我们保证在有限时间内到达每个有限点(尽管某些点仍然在记忆范围之外)。
正如哈马尔在评论中指出的那样,这还不够,因为它仍然需要
无限量的时间来获得False
答案。
但是,我们对paar的元素有一个顺序,即(3*a,b^2)
来自(3*c,d^2)
之前
a + b < c + d
。因此,要确定给定的对(x,y)
是否在paar
中,我们只需要检查
在(p,q)
时对p/3 + sqrt q <= x/3 + sqrt y
进行配对。
为避免使用Floating
个数字,我们可以使用稍宽松的条件p <= x || q <= y
。
当然p > x && q > y
暗示p/3 + sqrt q > 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