- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
为了解决一些问题,我需要计算如下定义的帕斯卡三角形的变体:
f(1,1) = 1,
f(n,k) = f(n-1,k-1) + f(n-1,k) + 1 for 1 <= k < n,
f(n,0) = 0,
f(n,n) = 2*f(n-1,n-1) + 1.
对于给定的 n,我想高效地获取第 n 行 (f(n,1) .. f(n,n))。一个进一步的限制:如果 f(n,k) >= 2^32,则它应该是 -1。
我的实现:
next :: [Int64] -> [Int64]
next list@(x:_) = x+1 : takeWhile (/= -1) (nextRec list)
nextRec (a:rest@(b:_)) = boundAdd a b : nextRec rest
nextRec [a] = [boundAdd a a]
boundAdd x y
| x < 0 || y < 0 = -1
| x + y + 1 >= limit = -1
| otherwise = (x+y+1)
-- start shoud be [1]
fLine d start = until ((== d) . head) next start
问题:对于非常大的数字,我会出现堆栈溢出。有没有办法强制 haskell 评估整个列表?很明显,每行不能包含超过上限的元素,因为它们最终会变成 -1 并且不会被存储,并且每一行仅取决于前一行。由于惰性评估,只有每行的头部被计算,直到最后一行需要它的第二个元素并且沿途的所有主干都被存储......我在 C++ 中有一个非常有效的实现,但我真的很想知道是否也有办法在 haskell 中完成它。
最佳答案
对我有用:您使用的是什么 Haskell 实现?计算这个三角形的简单程序在 GHC 6.10.4 中对我来说效果很好。我可以很好地打印第 1000 行:
nextRow :: [Integer] -> [Integer]
nextRow row = 0 : [a + b + 1 | (a, b) <- zip row (tail row ++ [last row])]
tri = iterate nextRow [0]
main = putStrLn $ show $ tri !! 1000 -- print 1000th row
我什至可以打印第 100000 行的前 10 个数字而不会溢出堆栈。我不确定你怎么了。全局名称 tri
可能会让整个三角形的结果保持活力,但即便如此,这似乎也相对无害。
如何强制求值顺序:您可以使用 Prelude 函数 seq
(这是一个神奇的函数,不能根据 Haskell 的其他基本功能来实现)。如果你告诉 Haskell 打印 a `seq` b
,它首先计算 a
的 thunk,然后计算并打印 b
。
请注意 seq
很浅:它仅 进行了足够的评估以强制 a
不再是一个 thunk。如果 a
是一个元组类型,结果可能仍然是一个 thunk 元组。如果它是一个列表,结果可能是一个头部和尾部都有 thunk 的 cons 单元格。
对于这样一个简单的问题,您似乎不需要这样做;对于任何合理的实现,几千个 thunk 应该不会太多。但它会像这样:
-- Evaluate a whole list of thunks before calculating `result`.
-- This returns `result`.
seqList :: [b] -> a -> a
seqList lst result = foldr seq result lst
-- Exactly the same as `nextRow`, but compute every element of `row`
-- before calculating any element of the next row.
nextRow' :: [Integer] -> [Integer]
nextRow' row = row `seqList` nextRow row
tri = iterate nextRow' [0]
seqList
中的折叠基本上扩展为 lst!!0 `seq` lst!!1 `seq` lst!!2 `seq` ... `seq` 结果
.
当只打印第 100,000 行的前 10 个元素时,这对我来说要慢得多。我认为这是因为它需要计算 99,999 行完整的三角形。
关于algorithm - haskell 中帕斯卡三角形的变体 - 惰性评估问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2399986/
我有一个大问题,因为这段代码在 Dev-Pascal 中正确编译,但在 Lazarus 中却没有。 for k:=1 to n do begin writeln(a[k
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我有一个与 Pascal 中的 for 循环工作方式相关的问题: Program example; var i:integer; Begin i:=7; for i:=1 to i
PROGRAM RandomNumber; Var rand,count,guess : integer; LABEL correct, loop, wrong, end1; begin {Initi
我是新来的,如果我做错了什么,很抱歉! 我正在 Lazarus 中制作一个简单的 Pascal 程序,编译时出现此错误: HWE(16,18) 错误:“Char”和“Constant String”类
这个问题已经有答案了: What is the implementation of sets used in pascal? (2 个回答) 已关闭 6 年前。 我明天要去参加一个高中编程比赛,他们使
我正在用 pascal 编写一个小程序,但遇到了一个小问题。在其他语言中,有一个名为“split”或“explode”的函数,用于获取由定义的字符分隔的长字符串,并将该长字符串拆分为几个较小的字符串,
我在Pascal中找了很长时间这个算法并没有找到,我只在C++中找到了它,这令人沮丧。然后我决定将 C++ 代码翻译为 Pascal,但是有一些问题我无法解决。出现错误消息“浮点溢出”。我需要帮助才能
例如,如果我有这样的数组,如何获取具有特定索引的数组的长度 TYPE T_PERSON = PACKED RECORD Example : STRING[40]; Example2 : STR
我正在尝试使用 创建 TForm 的子类 针对某些情况的特殊构造函数,以及 将保持与当前代码的兼容性的默认构造函数。 这是我现在的代码: interface TfrmEndoscopistSear
我的插入排序算法出现此错误: insertionsort.lpr(19,17) Error: Incompatible types: got "Boolean" expected "LongInt"
我的任务是在我的屏幕上显示两个图像(两个 TImage),一个是头部,另一个是尾部(硬币),并带有一个 TButton 来随机化它们。 就是当你按下按钮时,两个图像会随机选择正面或反面。 我知道这是一
我正在编写一段代码来读取 CSV 文件并从中解析信息(目前我只有代码的开头部分,它将在文件开头的标题中读取。当我尝试编译这段代码,我在行中收到一个错误,它占用了文件中行的长度。 我收到的错误是:[Er
我正在开发一个 Java 应用程序,它是关于将 Mathcad 工作表转换为 Java 应用程序的。谁能知道/建议如何用 Java 代码编写单位(牛顿、帕斯卡、毫米、千克)? 例子:1? double
我是一名优秀的程序员,十分优秀!