マイナンバーのチェックデジットの検算をざっくり1割くらい高速化する(計ってないので知らんけど)

# まずは計算方法をじっと考える
<a href="http://qiita.com/qube81/items/fa6ef94d3c8615b0ce64">承前</a>。

まず、検査用数字(チェックデジット)の算出方法をじっと眺めます。プログラマ目線で眺めていると、要するに次のような手順で計算すればよい、ということがわかります。

1. $P, Q$ を次のようにおく。$P$は、マイナンバーのうちチェックデジットを除く11桁の番号を要素として含むリストとし、$P$の要素$P_{0}$は11桁の番号のうち1桁目の数値を表すこととする。$Q$の各要素$Q_n$は$n \bmod 6 + 2$として求める。ただし$n$は$0 \le n \le 10$とする。
    * $P = (P_{10}, P_{9}, P_{8}, ..., P_{0})$
    * $Q = (Q_{10}, Q_{9}, Q_{8}, ..., Q_{0}) = (6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2)$
2. $r = (11 - \sum_{n=1}^{11} P_n \cdot Q_n \bmod 11) \bmod 10$ を求め、$r$を検査用数字として出力する。

ここまでわかれば、あとはどの言語でどう書くにしても簡単です。条件分岐なども登場しないため、たぶん実行速度も速くなっているでしょう。
では、さっそく書いてみましょう。

# Ruby
```ruby:verify_my_number.rb
def verify_my_number(my_number)
  remain, given_check_digit = my_number.divmod(10)
  check_digit = 0

  11.times do |i|
    remain, p_i = remain.divmod(10)
    check_digit += p_i * (i % 6 + 2)
  end

  (11 - check_digit % 11) % 10 == given_check_digit
end
```

# Perl
```pl:verify_my_number.pl
sub verify_my_number {
    my ($my_number) = @_;
    my $given_check_digit = $my_number % 10;
    my $check_digit = 0;

    for (my $i = 0; $i < 11; $i++) {
        $my_number /= 10;
        $check_digit += ($my_number % 10) * ($i % 6 + 2);
    }

    return (11 - $check_digit % 11) % 10 == $given_check_digit;
}
```

Rubyの場合とそれほど差が無くて面白くないので、一応、別の書き方も試してみます。
書いていて少し楽しい、というだけで、速度の面での優位性はないと思いますが。

```pl:verify_my_number2.pl
sub verify_my_number {
    my ($my_number) = @_;
    my $check_digit = 0;

    map {
        $check_digit += $my_number / (10 ** ($_ + 1)) % 10 * ($_ % 6 + 2);
    } (0 .. 10);

    return (11 - $check_digit % 11) % 10 == $my_number % 10;
}
```
# C
```c:verify_my_number.c
int
verify_my_number(long long int my_number)
{
        int check_digit = 0;
        int given_check_digit = my_number % 10;

        for (int i = 0; i < 11; i++) {
                my_number /= 10;
                check_digit += (my_number % 10) * (i % 6 + 2);
        }

        return (11 - check_digit % 11) % 10 == given_check_digit;
}
```

# Go
```verify_my_number.go
func verify_my_number(my_number int) bool {
    check_digit := 0
    given_check_digit := my_number % 10

    for i := 0; i < 11; i++ {
        my_number /= 10
        check_digit += (my_number % 10) * (i % 6 + 2)
    }

    return (11 - check_digit % 11) % 10 == given_check_digit
}
```

# bash
```verify_my_number.sh
function verify_my_number {
    n=`printf %012d $1`
    given_check_digit=$(($1 % 10))
    check_digit=`echo -n $n|grep -o .|paste -d\* - <(echo -n '654327654320'|grep -o .)|paste -d+ - - - - - - - - - - - -|sed -e 's/^/echo $(((11-(/' -e 's/$/)%11)%10))/'|sh`
    [ $check_digit -eq $given_check_digit ] && echo 'OK' || echo 'NG'
}
```

# Excel
チェックデジットの算出だけなら次のように書けます。
```
=MOD(
  11 - MOD(
  (MOD(QUOTIENT($A1, 10000000000), 10) * 6 +
   MOD(QUOTIENT($A1, 1000000000), 10) * 5 +
   MOD(QUOTIENT($A1, 100000000), 10) * 4 +
   MOD(QUOTIENT($A1, 10000000), 10) * 3 +
   MOD(QUOTIENT($A1, 1000000), 10) * 2 +
   MOD(QUOTIENT($A1, 100000), 10) * 7 +
   MOD(QUOTIENT($A1, 10000), 10) * 6 +
   MOD(QUOTIENT($A1, 1000), 10) * 5 +
   MOD(QUOTIENT($A1, 100), 10) * 4 +
   MOD(QUOTIENT($A1, 10), 10) * 3 +
   MOD($A1, 10) * 2),
  11),
10)
```

# Python
Pythonよくわからないけど、多分こんな感じ?
それほど速くはないと思います。

```verify_my_number.py
def verify_check_digit(my_number):
    product = sum([
                    (my_number / (10 ** (i + 1)) % 10) * (i % 6 + 2)
                    for i in range(0, 11)
                 ])
    return (11 - product % 11) % 10 == my_number % 10
```