Ruby Pascal';带记忆的s三角发生器
作为一个Ruby学习实验,我正在尝试记忆我的Pascal三角形生成器的实现。我有以下工作代码:Ruby Pascal';带记忆的s三角发生器,ruby,closures,memoization,Ruby,Closures,Memoization,作为一个Ruby学习实验,我正在尝试记忆我的Pascal三角形生成器的实现。我有以下工作代码: module PascalMemo @cache = {} def PascalMemo::get(r,c) if @cache[[r,c]].nil? then if c == 0 || c == r then @cache[[r,c]] = 1 else @cache[[r,c]] = PascalMemo::get(r
module PascalMemo
@cache = {}
def PascalMemo::get(r,c)
if @cache[[r,c]].nil? then
if c == 0 || c == r then
@cache[[r,c]] = 1
else
@cache[[r,c]] = PascalMemo::get(r - 1, c) + PascalMemo::get(r - 1, c - 1)
end
end
@cache[[r,c]]
end
end
def pascal_memo (r,c)
PascalMemo::get(r,c)
end
这能更简洁吗?具体地说,我可以创建一个全局作用域函数和一个局部闭包吗
这能更简洁吗
这似乎很清楚,IMO,module
ing通常是一种良好的本能
我能用一个局部闭包创建一个全局作用域函数吗
另一个选项是递归的lambda
:
memo = {}
pascal_memo = lambda do |r, c|
if memo[[r,c]].nil?
if c == 0 || c == r
memo[[r,c]] = 1
else
memo[[r,c]] = pascal_memo[r - 1, c] + pascal_memo[r - 1, c - 1]
end
end
memo[[r,c]]
end
pascal_memo[10, 2]
# => 45
请注意,上述构造确实实现了记忆化,它不仅仅是一个简单的递归方法。我找到了一种方法来实现我想要的稍微更令人满意,因为它生成的是一个函数而不是lambda:
class << self
cache = {}
define_method :pascal_memo do |r,c|
cache[[r,c]] or
(if c == 0 or c == r then cache[[r,c]] = 1 else nil end) or
cache[[r,c]] = pascal_memo(r-1,c) + pascal_memo(r-1,c-1)
end
end
类如果我可以问的话,@cache
实例变量属于哪个对象?@BorisStitnicky:很好,这是一个复制粘贴延迟。根本不需要实例变量这很有用,因为我不知道如何创建递归lambda。然而,我接受了另一个答案,因为它没有将缓存留在全局范围内。我从中学到了很多。我不想留下pascal\u memo
工厂函数,但我能够通过将工厂函数本身设置为lambda,并将p
分配给内联调用它的结果来实现这一点。(r,c)
语法糖对我来说也是新的。最后,函数本身在如何构建缓存方面很聪明——尽管在这方面它牺牲了相当多的可读性:(我很高兴它有帮助。至于缓存构建,我只是尝试提出一个替代方案。请注意,缓存本身是在存储在lambda绑定中的局部变量中构建的,而不是在main中。
class << self
cache = {}
define_method :pascal_memo do |r,c|
cache[[r,c]] or
(if c == 0 or c == r then cache[[r,c]] = 1 else nil end) or
cache[[r,c]] = pascal_memo(r-1,c) + pascal_memo(r-1,c-1)
end
end