Hello
I need to check that the NHS numbers in my database are valid. I’m
storing them as ten-digit strings: the first nine are the identifier and
the tenth is a check digit.
There are four steps to calculating the check digit (from
UK Government Web Archive):
-
multiply each of the first nine digits by a weighting factor (10 for
the first digit, 9 for the second… 2 for the ninth)
-
sum the results of these multiplications
-
divide the total by 11 and establish the remainder
-
subtract the remainder from 11 to give the check digit.
If the result of step 4 is 11 a check digit of 0 is used; if the result
is 10 then the number is invalid.
I’m struggling to implement this into my model. I imagine that the first
thing is to convert the string to an array:
nhs_no = “1234567890”
nhs_no.split(“”).map{ |v| v.to_i } # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
Then I get a bit stuck (i.e. before step 1!): I want to transform the
first nine digits of the array so that the new value of the kth element
is v*(10-k).
I hope this makes some sense, and I’d really appreciate any help.
Thanks.
On Apr 18, 2007, at 1:15 PM, Tim C. wrote:
tech_nn_check_digit.pdf):
9, 0]
Then I get a bit stuck (i.e. before step 1!): I want to transform the
first nine digits of the array so that the new value of the kth
element
is v*(10-k).
You probably want the Enumerable#each_with_index method, eg.
new_array = []
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].each_with_index do |value, index|
new_array.push(value * (10 - index))
end
James.
–
James S.
Play: http://james.anthropiccollective.org
Work: http://jystewart.net/process/
James S. wrote:
You probably want the Enumerable#each_with_index method, eg.
new_array = []
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].each_with_index do |value, index|
new_array.push(value * (10 - index))
end
Thank you James! In case anyone’s interested here’s a function which
returns the check digit for a given NHS number string:
def check_digit(nhs_number)
# must be ten digits long
unless nhs_number.length == 10
check_digit = nil
else
new_array = []
nhs_number.split("").map{ |v| v.to_i }.each_with_index do |value,
index|
new_array.push(value * (10 - index)) if index < 9
end
check_digit = 11-new_array.sum.remainder(11)
# recode check digit of 11 to 0 and ‘disallow’ 10
case check_digit
when 11 then check_digit = 0
when 10 then check_digit = nil
end
# disallow NHS numbers like “1111111111”, “2222222222” etc.
check_digit = nil if check_digit.to_s*10 == nhs_number
end
check_digit
end
I’m sure that I could make this more elegant somehow, especially if
there were a ‘map_with_index’ function…