Performance 合格Haskell列表理解的有效替代方案

Performance 合格Haskell列表理解的有效替代方案,performance,haskell,list-comprehension,Performance,Haskell,List Comprehension,作为Haskell中合格列表理解的一个示例,本教程提供了一个列表理解示例,该示例提出了一种寻找具有给定周长p的直角三角形的通用方法,表示为元组: λ> let rightTriangles p = [ (a,b,c) | c <- [1..(quot p 2)], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a + b + c == p] λ>让右三角形p=[(a,b,c)| c这些注释很好地说明,您真正需要的是一个更好的算

作为Haskell中合格列表理解的一个示例,本教程提供了一个列表理解示例,该示例提出了一种寻找具有给定周长
p
的直角三角形的通用方法,表示为元组:

λ> let rightTriangles p = [ (a,b,c) | c <- [1..(quot p 2)], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a + b + c == p] 

λ>让右三角形p=[(a,b,c)| c这些注释很好地说明,您真正需要的是一个更好的算法

但是,让我们尝试一些不同的方法,看看我们可以对当前代码进行哪些优化:

let rightTrianglesCubic p = [ (a,b,c) | c <- [1..quot p 2], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a + b + c == p]
这种方法有一个小问题:

λ rightTrianglesCubic 120
[(30,40,50),(24,45,51),(20,48,52)]
λ rightTrianglesQuadraticA 120
[(40,30,50),(30,40,50),(45,24,51),(24,45,51),(48,20,52),(20,48,52),(0,60,60)]

我们得到了一些额外的结果!这是因为我们忽略了
a的隐式条件。我认为一般的想法是使用不同的算法,即不是蛮力。这不是列表理解的错,因为它太慢,这是嵌套for循环的蛮力算法的一个经典示例。该算法的复杂性s在
O(n^3)附近的某个地方
,随着
n
变大,复杂度不是很高。对,这是一个算法/数学问题,而不是哈斯克尔/性能问题。你对解决这个特定的问题有多感兴趣,找到具有规定周长的直角三角形?有效的方法是使用毕达哥拉斯三元组的参数化,从事实开始ring
p
…@ReidBarton:是的,很好的观点,部分回答了这个问题:约束不适用于域规范。例如,
(a,b,c)
的所有值都是c谢谢。这正是我想要的:我想坚持列表理解,但不想成为O(n³)。我还想确认我想知道的是:
|
之后的约束没有以任何方式“解决”(正如您在上面“手动”所做的那样)。
λ rightTrianglesCubic 120
[(30,40,50),(24,45,51),(20,48,52)]
λ rightTrianglesQuadraticA 120
[(40,30,50),(30,40,50),(45,24,51),(24,45,51),(48,20,52),(20,48,52),(0,60,60)]
let rightTrianglesQuadraticB p = [ (a,b,c) | c <- [1..quot p 2], b <- [1..c], let a = p - b - c, a^2 + b^2 == c^2, 1 <= a, a <= b]
λ rightTrianglesQuadraticB 120
[(30,40,50),(24,45,51),(20,48,52)]
let rightTrianglesQuadraticC p = [ (a,b,c) | c <- [1..quot p 2], b <- [max 1 (div (p - c + 1) 2) .. min c (p - c - 1) ], let a = p - b - c, a^2 + b^2 == c^2]
let rightTrianglesQuadraticD p = [ (a,b,c) | c <- [1 + quot p 3..quot p 2], b <- [max 1 (div (p - c + 1) 2) .. min c (p - c - 1) ], let a = p - b - c, a^2 + b^2 == c^2]