我必须编写一个函数,它返回所有对(x,y)的列表,其中x, y∈N,和:
我的尝试:
listPairs :: [(Int, Int)]
listPairs = [(a*b, y) | y <- [0..], a <- [0..], b <- [0..],
(a*b) > 5, (a*b) < 500, (y*y) < 1001,
mod y (a*b) == 0]
但它没有返回任何东西,而且计算机在它上面工作很多。
但是,如果我为a
,b
和y
e选择较小的范围。 G。 [0..400]
,它需要一分钟,但它会返回正确的结果。
那我怎么能解决性能问题呢?
答案 0 :(得分:1)
因此,无限列表上的嵌套列表推导当然不会终止。
幸运的是,你的名单不是无限的。有一个限制。如果x = a*b < 500
,则我们知道它必须是a < 500
和b < 500
。此外,c = y*y < 1001
只是y < 32
。所以,
listPairs :: [(Int, Int)]
listPairs =
[(x, c*c) | c <- [1..31], a <- [1..499], -- a*b < 500 ==> b<500/a ,
b <- [a..min 499 (div 500 a)], -- a*b==b*a ==> b >= a
let x = a*b, x > 5,
-- (a*b) < 500, (c*c) < 1001, -- no need to test this
rem (c*c) x == 0]
mod 0 n == 0
平凡地持有,所以我在这里从“自然数”中排除0。
此处仍有一些重复项,即使我们已将b
值限制为b >= a
中的x=a*b
,因为x
可以有多个表示形式(例如{ {1}})。
您可以使用1*6 == 2*3
删除它们。