我不知道Ruby,但我试图理解这个代码是否存在Euler#17问题。我理解这个问题,并且我理解代码的前几行。而且,我搜索了puts
和injects
等个别方法。我不明白代码在|sum,n|
之后尝试做什么。
有人可以将其转换为某种伪代码吗?
这是the code:
digit = [ 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 8, 7, 9, 8, 8 ]
decade = [4, 3, 6, 6, 5, 5, 5, 7, 6, 6]
puts (1..1000).inject(0) { |sum, n|
sum, n = sum + 11, n % 1000 if n > 999
sum, n = sum + digit[n / 100] + (n % 100 > 0 ? 10 : 7), n % 100 if n > 99
sum, n = sum + decade[n / 10], n % 10 if n > 19
sum += digit[n] if n > 0
sum
}
答案 0 :(得分:3)
首先,请注意该程序中存在错误:digit[15]
应为7,而不是8。
我不确定将它转换为伪代码会使它更清晰,但这是一行一行的解释:
sum, n = sum + 11, n % 1000 if n > 999
如果n
至少为1000,请将单词one thousand
的非空格字符数添加到正在运行的总数sum
中,然后将余下的n
替换为余下的n
n
除以1000.例如,如果1538
为n % 1000
,则538
为sum, n = sum + digit[n / 100] + (n % 100 > 0 ? 10 : 7), n % 100 if n > 99
,从而删除第一个数字。
n
如果hundred
至少为100,请添加第一个数字的名称长度加上7(单词n
的长度)。如果and
不是100的倍数,您还需要添加单词n
,总共10个字符。然后像以前一样删除sum, n = sum + decade[n / 10], n % 10 if n > 19
的第一个数字。
twenty
现在添加表达第一个数字所需的字符数(thirty
表示2,n
表示3,等等...),前提是该数字至少为2.“青少年”在最后一行单独处理。最后,将sum += digit[n] if n > 0
替换为最后一位数字。
n
此时,digit
是单个数字或“青少年”,其名称中的字符数都预先计算在a, b = 3, 5
数组中,因此我们添加该值,我们'完了。
这里使用了一些可能模糊的语法功能:
多项作业
在ruby中,您可以编写类似
的语句puts "hi" if n > 0
同时为多个变量赋值。在这种情况下没有真正的理由这样做,除了使代码更短(虽然可读性更低)。
后缀条件
其主体只有1个表达式的条件可以用 postfix 形式写入。例如:
if n > 0
puts "hi"
end
完全等同于:
n > 0 ? n : 1
同样,这仅用于缩短代码。
三元运营商
编写条件表达式的另一种方法:
if n > 0
n
else
1
end
转换为
digit = [ 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 ]
decade = [4, 3, 6, 6, 5, 5, 5, 7, 6, 6]
puts (1..1000).inject(0) { |sum, n|
if n > 999
sum += 11
n = n % 1000
end
if n > 99
sum += digit[n / 100] + 7
if n % 100 > 0
sum += 3
end
n = n % 100
end
if n > 19
sum += decade[n / 10]
n = n % 10
end
if n > 0
sum += digit[n]
end
sum
}
通过“desugaring”上面解释的所有特殊语法(并将错误修复为15),程序变为:
{{1}}
答案 1 :(得分:0)
我假设您已熟悉模数操作数(n % 100
)和三元运算符(condition ? result_if_true : result_if_false
)
这里只有两个新概念:
所以,代码
sum += digit[n] if n > 0
相当于
if n > 0
sum += digit[n]
end
代码
sum, n = sum + decade[n / 10], n % 10 if n > 19
相当于
if n > 19
sum = sum + decade[n / 10]
n = n % 10
end
现在代码应该是显而易见的。