当你有你的数字作为字符串(或者如果你有你的数字作为整数,就#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
这只是简单的解决方案,不值得解释,除非有人要求