Если у вас есть ваш номер в виде строки (или если у вас есть цифра в виде целого числа, просто наберите #to_s
и получите строку), а затем вы можете просто извлечь цифры из него с помощью:
number_string[idx].to_i
или если вы используете Ruby 1.8
number_string[idx..idx].to_i
#to_i
- преобразовать его в целое, чтобы вы могли добавить его к другим. Затем просто выполните шаги для расчета вашего числа.
Все, что вам нужно сделать для его реализации, это правильно отобразить позиции, указанные в инструкции, на idx
индексную позицию в вашем строковом представлении числа. Просто сделайте это на бумаге с подсчетом в голове или используйте отрицательный idx (отсчитывается от конца строки) в Ruby.
EDIT
Решение может быть примерно таким:
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 до бесконечности, для каждого элемента
Теперь у нас должно быть что-то вроде этого:
[[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[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
Это просто мёртвое простое решение, объяснять не стоит, если только кто-то не попросит об этом