【发布时间】:2018-06-07 13:59:32
【问题描述】:
所以我试图在 Haskell 中生成出租车号码列表。出租车号码是可以用两种不同方式写成两个不同立方体的总和的数字 - 最小的是
1729 = 1^3 + 12^3 = 9^3 + 10^3.
现在,我只想生成“组成”出租车号码的四个数字,例如(1,12,9,10),并被告知使用列表理解(我不太熟悉)。此函数将生成最大数最多为 n 的所有 4 元组:
taxi n = [(a,b,c,d) | a <- [1..n], b <- [1..n], c <- [1..n], d <- [1..n], a^3 + b^3 == c^3 + d^3, a < b, a < c, c < d]
但是,由于以下几个原因,它很麻烦:
- a、b、c、d 的域都是相同的,但我不知道如何简化此代码,所以
[1..n]只写一次。 - 我想要一个无限列表,没有上限,所以我可以让程序尽可能长时间地运行,并在我喜欢的时候终止它。显然,如果我只设置
a <- [1..]等,那么程序将永远不会评估任何内容。 - 程序非常慢:仅
taxi 50需要 19 秒。
任何速度优化也很好,但如果不是我使用的幼稚方法就足够了。
【问题讨论】:
-
谁让你使用列表理解的?您如何对此进行基准测试?请说
ghc -O2 -fforce-recomp -fllvm。搜索应该按什么顺序?深度优先?如果a是从一个无限列表中抽取的,为什么什么都不会被评估? -
使用列表理解是问题的要求。我不知道您的“ghc ...”代码是什么意思;我在 Haskell 中使用了命令
:set +s,但速度不是我主要关心的问题。任何合理的顺序对我都有好处 - 问题是我不知道如何让 Haskell 以特定顺序进行评估,尽管我可以构造一个双射 ℕ^4 -> ℕ 循环遍历整数。我知道无限列表是必要的;我的意思是用a <- [1..]替换a <- [1..n]而不做进一步更改将导致程序永远不会输出任何东西。 -
仅供参考
:set +s不是在“Haskell”中完成的,而是在名为 GHCi 的 GHC 解释器中完成的。除了这个解释器之外,还有一个名为 ghc 的编译器,它可以生成运行得更快的机器代码。列表推导的使用将您锁定在对第一个列表的值进行广度优先探索的过程中,在考虑第一个列表的下一个值之前,先考虑后面列出的变量的所有可能值。使用诸如[ (a,b,c) | a <- [1..3], b <- [1,2], c <- [1,2] ]之类的语句可以轻松且具有教育意义。 -
不应该是b
-
@Soldalma 一点也不。考虑 (1,12,9,10)。不等式条件只是为了避免获得该元组的其他 23 个排列,例如(9,10,1,12) 或 (12,1,9,10)。在每一对中,我们希望数字较小的在前,在这些对中,我们希望数字最小的在前(当然,这只是一种可能的解决方案)。
标签: haskell list-comprehension infinite