\begin{align*}
d &= 11 - \Biggl( \sum^{11}{n=1} P_n \times Q_n \Biggr) \bmod 11 \
& \text{ただし,$\Biggl( \sum^{11}{n=1} P_n \times Q_n \Biggr) \bmod 11 \leq 1$の場合は$d=0$} \
P_n &= \text{ 個人番号を構成する検査用数字以外の十一桁の番号の最下位の桁を1桁目としたときの$n$桁目の数字} \
Q_n &=
\begin{cases}
n + 1 && \text{if
from: 総務省令第八十五号 行政手続における特定の個人を識別するための番号の利用等に関する法律
class MynumberValidator
def validate(num)
d = num.to_s.chars.reverse.map(&:to_i)
return false if d.size != 12
cd = d.shift
sum = 0
1.upto(11) do |i|
sum += d[i-1] * (i <= 6 ? i + 1 : i - 5)
end
sum %= 11
cd == (sum <= 1 ? 0 : 11 - sum)
end
end
require 'test/unit'
extend Test::Unit::Assertions
validator = MynumberValidator.new
assert_equal validator.validate(12345678901), false
assert_equal validator.validate(123456789012), false
assert_equal validator.validate(123456789018), true
assert_equal validator.validate(123456789001), false
assert_equal validator.validate(123456789000), true
assert_equal validator.validate("123456789012"), false
assert_equal validator.validate("023456789013"), true
class MynumberValidator
def validate(num)
d = num.to_s.chars.map(&:to_i)
return false if d.size != 12
cd = d.pop
sum = d.reverse.map.with_index(1) { |n, i| n * (i <= 6 ? i+1 : i-5) }.inject(0, :+) % 11
cd == (sum <= 1 ? 0 : 11 - sum)
end
end
require 'test/unit'
extend Test::Unit::Assertions
validator = MynumberValidator.new
assert_equal validator.validate(12345678901), false
assert_equal validator.validate(123456789012), false
assert_equal validator.validate(123456789018), true
assert_equal validator.validate(123456789001), false
assert_equal validator.validate(123456789000), true
assert_equal validator.validate("123456789012"), false
assert_equal validator.validate("023456789013"), true
class MyNumberValidator
MYNUMBER_LENGTH = 12
def validate(num)
@my_number = num.to_s.chars.map(&:to_i)
validate_length && validate_check_digit
end
private
def digits
@my_number[0..-2].reverse
end
def check_digit
@my_number[-1]
end
def validate_length
digits.size != MYNUMBER_LENGTH
end
def validate_check_digit
q_n = [*(2..7), *(2..6)]
sum = digits.zip(q_n).inject(0) { |sum, (p, q)| sum + p * q } % 11
check_digit == (sum <= 1 ? 0 : 11 - sum)
end
end
require 'test/unit'
extend Test::Unit::Assertions
validator = MyNumberValidator.new
assert_equal validator.validate(12345678901), false
assert_equal validator.validate(123456789012), false
assert_equal validator.validate(123456789018), true
assert_equal validator.validate(123456789001), false
assert_equal validator.validate(123456789000), true
assert_equal validator.validate("123456789012"), false
assert_equal validator.validate("023456789013"), true
<main>:1: warning: already initialized constant MyNumberValidator::MYNUMBER_LENGTH
<main>:1: warning: previous definition of MYNUMBER_LENGTH was here
class MynumberValidator
def validate(num)
d=num.to_s.chars.map(&:to_i)
d.size==12&&d.pop==(11-d.reverse.zip((2..7).cycle).inject(0){|s,(n,m)|s+n*m}%11).tap{|cd| break 0 if cd>9}
end
end
require 'test/unit'
extend Test::Unit::Assertions
validator = MynumberValidator.new
assert_equal validator.validate(12345678901), false
assert_equal validator.validate(123456789012), false
assert_equal validator.validate(123456789018), true
assert_equal validator.validate(123456789001), false
assert_equal validator.validate(123456789000), true
assert_equal validator.validate("123456789012"), false
assert_equal validator.validate("023456789013"), true
\begin{align*}
Q_n &=
\begin{cases}
n + 1 && \text{if
実際に計算してみる
(1..11).each do |i|
puts "Q_#{"%02d" % i} = #{i <= 6 ? i + 1 : i - 5}"
end
Q_01 = 2
Q_02 = 3
Q_03 = 4
Q_04 = 5
Q_05 = 6
Q_06 = 7
Q_07 = 2
Q_08 = 3
Q_09 = 4
Q_10 = 5
Q_11 = 6
1..11
2, 3, 4, 5, 6, 7, 2, 3, ...
というように循環した配列になる!
循環リスト的なのを作ってくれる
[0, 1, 2].cycle(3) { |i| puts i }
# (0..2).cycle(3, &method(:puts))
0
1
2
0
1
2
0
1
2
配列をいい感じに合成してくれる
p [:a, :b, :c].zip([0,1,2])
p [:a, :b, :c, :d].zip([0,1,2])
# p %i(a b c d).zip(0..2)
[[:a, 0], [:b, 1], [:c, 2]]
[[:a, 0], [:b, 1], [:c, 2], [:d, nil]]
[[:a, 0], [:b, 1], [:c, 2], [:d, nil]]
RSpec.describe MynumberValidator do
let(:validator) { MynumberValidator.new }
RSpec.describe '#validate_mynumber' do
subject { validator.validate(num) }
context 'pass the number that has invalid length ' do
let(:num) { 12345678901 }
it { is_expected.to be false }
end
context 'pass the invalid number' do
let(:num) { 123456789012 }
it { is_expected.to be false }
end
context 'pass the valid number' do
let(:num) { 123456789018 }
it { is_expected.to be true }
end
context 'pass the invalid number that calculated digit is bigger' do
let(:num) { 123456789001 }
it { is_expected.to be false }
end
context 'pass the valid number that calculated digit is bigger' do
let(:num) { 123456789000 }
it { is_expected.to be true }
end
context 'pass the invalid number as string' do
let(:num) { '123456789012' }
it { is_expected.to be false }
end
context 'pass the valid number starts with 0' do
let(:num) { '023456789013' }
it { is_expected.to be true }
end
end
end