列表理解不会在 Haskell 中给出正确的结果

Posted

技术标签:

【中文标题】列表理解不会在 Haskell 中给出正确的结果【英文标题】:List comprehension won't give correct result in Haskell 【发布时间】:2009-11-29 16:10:18 【问题描述】:

我正在做project euler question 136,并想出了以下内容来测试给出的示例:

module Main where
import Data.List

unsum x y z n = (y > 0) && (z > 0) && (((x*x)  - (y*y)- (z*z)) == n) && ((x - y) == (y - z))
answer = snub $ takeWhile (<100) [n|x<-[1..],d<-[1..x`div`2],n<-[x..100],y<-[x-d],z<-[y-d], unsum x y z n ]
    where 
      snub [] = []
      snub (x:xs) | elem x xs = snub (filter (/=x) xs)
                  | otherwise = x : snub xs

snub 将从列表中删除所有重复的数字。

该示例应该为 n 提供 25 个解决方案,其中 x^2 - y^2 - z^2 == n 并且所有数字都是正数(或者我从问题中收集到)并且是算术级数,例如 x-y == y-z。但是当我使用代码时,会返回n 的 11 个解决方案列表。

我在列表理解方面做错了什么,我错过了哪些优化?

【问题讨论】:

我自己创建了nub,因此它会返回一个删除了两个重复项的列表,因为问题需要n 的唯一解决方案 这样就可以在此处解释您的评论***.com/questions/1801459/… :) 【参考方案1】:

第 1 点

我尝试了这个问题,发现这是我想出的ns的序列

[4,3,16,12,7,20,11,48,28,19,80,44,23,52,112,31,68,76,1156,43,176,559...

这可能意味着您的takeWhile (&lt;100) 是用于确定何时停止的错误过滤功能。在相关说明中,我尝试运行此:

answer = snub $ filter (<=100) $ takeWhile (<200) [...listcomprehension...]

但我放弃了,因为它花了太长时间。这让我想到了第 2 点。


第 2 点

在优化方面,看看你的列表理解在原始输出方面产生了什么。

Main> take 30 [(x,y,z,n) | x<-[1..], d<-[1..x`div`2], n<-[x..100], y<-[x-d], z<-[y-d]]
[(2,1,0,2),(2,1,0,3),(2,1,0,4),(2,1,0,5),(2,1,0,6),(2,1,0,7),(2,1,0,8),(2,1,0,9),
(2,1,0,10),(2,1,0,11),(2,1,0,12),(2,1,0,13),(2,1,0,14),(2,1,0,15),(2,1,0,16),(2,1,0,17),
(2,1,0,18),(2,1,0,19),(2,1,0,20),(2,1,0,21),(2,1,0,22),(2,1,0,23),(2,1,0,24),(2,1,0,25),
(2,1,0,26),(2,1,0,27),(2,1,0,28),(2,1,0,29),(2,1,0,30),(2,1,0,31)]

这意味着在 x y z 和 n 的每个组合上都会调用 unsum,这有点多余,因为我们知道 2^2 - 1^2 - 0^2 = 3

n 的计算从列表理解(由于上述原因很慢)移动到一个函数并且仅列表理解有效的(x,y,z) 组合,这也更简单且更少冗余。

ns = map nsum [(x, x-d, x-d-d) | x <- [1..], d <- [1..x`div`2]]
nsum (x,y,z) = x^2 - y^2 - z^2

然后可以从这个无限列表中计算答案,但要小心使用 takewhile。

【讨论】:

感谢您的帮助,我明白为什么takeWhile 不正确了,因为在n 超过100 后n 的解决方案跳回到0 以下。 好的,尝试后:answer = length $ snub $ filter (&gt; 0) $ map nsum [(x, x-d, x-d-d) | x &lt;- [3..5000], d &lt;- [1..xdiv2]] 它完全吸光了我所有的内存。我认为我还没有弄清楚一些关键的优化,其中x,y,z 三元组可能是独特解决方案的候选者(可能涉及素数)

以上是关于列表理解不会在 Haskell 中给出正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

Haskell如何知道`xs`是函数定义中的列表?

Haskell 中的非确定性是啥?

Haskell 分析

在 Haskell 中整理列表理解

[Haskell电影搜索

用 90 行 Haskell 代码实现 2048 游戏