当您将数字作为字符串时(或者如果您将数字作为整数,只需 #to_s 并获取字符串),然后您可以简单地从那里提取数字:
number_string[idx].to_i
或者如果你使用 Ruby 1.8
number_string[idx..idx].to_i
#to_i是把它转成整数,这样你就可以把它加给别人了。然后继续执行提供的步骤来计算您的数字。
实现它所需要做的就是将指令中提供的位置正确映射到数字字符串表示中的idx 索引位置。只需在纸上计算 head 或在 Ruby 中使用负 idx(从字符串末尾开始计算)。
编辑:
解决方案可能是这样的:
bar_code_data = "961102098765431234567C"
digits_with_position = bar_code_data.reverse[1..14].split(//).map(&:to_i).zip(2..1/0.0)
如下:
-
reverse - 反向字符串,所以现在我们可以从左到右计数而不是反向
-
[1..14] - 选择我们感兴趣的字符子串(Ruby 从 0 开始计数)
-
split(//) - 将一个字符串拆分为长度为 1 个字符的子字符串,换句话说 - 单独的数字
-
map(&:to_i) - 对数组的每个元素调用 #to_i,换句话说,转换为整数
-
zip(2..1/0.0) - 为每个元素添加从 2 到 Infinity 的位置
现在我们应该有这样的东西:
[[7, 2],
[6, 3],
[5, 4],
[4, 5],
[3, 6],
[2, 7],
[1, 8],
[3, 9],
[4, 10],
[5, 11],
[6, 12],
[7, 13],
[8, 14],
[9, 15]]
sum = digits_with_position.map{|i| i[0] * (i[1].even? ? 3 : 1)}.reduce(+:)
我们在算法上做了一些小改动,你应该不难理解:
代替:
sum = (in[2] + in[4] + in[6] + ...)*3 + (in[3] + in[5] + in[7] + ...)
我们做了:
sum = in[2]*3 + in[3]*1 + in[4]*3 + in[5]*1 + in[6]*3 + in[7]*1 + ...
这是相同的结果,但操作顺序有所不同。
还有:
-
map {|i| ... } - 映射列表的每个值,在我们的例子中 i 是元组,一对 [digit,pos]
-
i[1].even? - 检查位置是否偶数
-
i[1].even? ? 3 : 1 - 偶数位置使用 3,相反(奇数)位置仅使用 1
-
reduce(:+) - 使用 + 操作将结果数组减少为单个值(添加所有结果)
现在有趣的部分:-)
check_code = 10 - (sum % 10)
-
sum % 10 - 和值的模块 10,返回除以 10 的提醒,在我们的例子中是最后一位
-
10 - (sum % 10) - 补到最接近的不小于 10 的倍数
描述有误,因为如果你的结果是130,那么10的下一个更大的倍数是140,差是10,这不是数字的正确结果(应该是0)。
其他更快的解决方案是这样的(展开所有循环,只需对所有内容进行硬编码):
d = "961102098765431234567C".split(//) # avoid having to use [-2..-2] in Ruby 1.8
sum_even = d[-2].to_i + d[-4].to_i + d[-6].to_i + d[-8].to_i + d[-10].to_i + d[-12].to_i + d[-14].to_i
sum_odd = d[-3].to_i + d[-5].to_i + d[-7].to_i + d[-9].to_i + d[-11].to_i + d[-13].to_i + d[-15].to_i
sum = sum_even * 3 + sum_odd
check_code = 10 - sum % 10
这只是简单的解决方案,不值得解释,除非有人要求