5
5

More than 5 years have passed since last update.

Perl5,Perl6でマイナンバーのチェックデジットを計算する

Last updated at Posted at 2015-10-30

あわせて読みたい

言語 リンク
Ruby マイナンバーのチェックデジットを計算する
C++ C++でマイナンバーのチェックデジットを計算する
Python Python マイナンバー検証用モジュールを公開
PHP マイナンバーのチェックデジットを計算する PHP版
C# C#でマイナンバーのチェックデジットを計算する
SQL マイナンバーのチェックデジットを計算する(SQLで)
PowerShell WindowsPowerShell & C#マイナンバーのチェックデジットを計算する
JavaScript, Groovy JavaScriptとGroovyでマイナンバーのチェックデジットを計算する
Haskell Haskellでマイナンバーのチェックデジットを計算する
Haskell マイナンバー数字列の確認
Java マイナンバーのチェックデジットを計算する(Java編)
C, Go, Bash, Excel etc... マイナンバーのチェックデジットの検算をざっくり1割くらい高速化する(計ってないので知らんけど)
Go マイナンバーのチェックデジットをGoで計算する
Swift マイナンバーのチェックデジットをSwiftで計算する
Vim script Vim からマイナンバーを検証出来るプラグイン書いた。
Gauche Scheme(Gauche)でマイナンバーのチェックデジットを計算する
OCaml OCaml でマイナンバーのチェックデジットを計算する
Rust My Number validator for Rust

説明

流行に乗ってマイナンバーのチェックデジットを計算してみます。
Ruby 版を真似て書いています。

Perl5

mynumber_validate.pl
#!/usr/bin env perl

use v5.18;
use List::Util 'sum';
use feature qw(say switch);
no warnings 'experimental';

&main;exit;

sub main{
  say validate_my_number('123456789010'); #=> false
  say validate_my_number('123456789011'); #=> false
  say validate_my_number('123456789012'); #=> false
  say validate_my_number('123456789013'); #=> false
  say validate_my_number('123456789014'); #=> false
  say validate_my_number('123456789015'); #=> false
  say validate_my_number('123456789016'); #=> false
  say validate_my_number('123456789017'); #=> false
  say validate_my_number('123456789018'); #=> true
  say validate_my_number('123456789019'); #=> false
  say validate_my_number('023456789013'); #=> true (先頭が0の場合)
}

sub validate_my_number{
  # 整数列化
  my @digits = split'', $_[0];

  # 12桁しか認めない
  return 'false' unless @digits == 12;

  # チェックデジットを分離します
  my $check_digit = pop @digits;

  # P(n) 定義
  my $P = sub {
      my @digits = @_;
      return sub {
        my $n = $_[0];
        return $digits[ -$n ];
      };
  }->(@digits);

  # Q(n) 定義
  my $Q = sub {
        my $n = $_[0];
        return ($n<= 6) ? $n+1 : $n-5;
  };

  # 数列の和を11で割った余りを計算します
  my $remainder = ( sum map{ $P->($_) * $Q->($_) } 1..11 ) % 11;

  given( $remainder ){
    when ([0,1]){
      return $check_digit == 0 ? 'true' : 'false';
    }
    default{
      return $check_digit == 11 - $remainder ? 'true' : 'false';
    }
  }
}

Perl6

perl6_mynumber_validate.pl
use v6;

sub MAIN (){
  say validate_my_number('123456789010'); #=> false
  say validate_my_number('123456789011'); #=> false
  say validate_my_number('123456789012'); #=> false
  say validate_my_number('123456789013'); #=> false
  say validate_my_number('123456789014'); #=> false
  say validate_my_number('123456789015'); #=> false
  say validate_my_number('123456789016'); #=> false
  say validate_my_number('123456789017'); #=> false
  say validate_my_number('123456789018'); #=> true
  say validate_my_number('123456789019'); #=> false
  say validate_my_number('023456789013'); #=> true (先頭が0の場合)
}

sub validate_my_number( Str $mynumber ){
  # 整数列化
  my @digits = $mynumber.comb;

  # 12桁しか認めない
  return False unless @digits.elems == 12;

  # チェックデジットを分離します
  my $check_digit = @digits.pop;

  # P(n) 定義
  my $P = sub ( @digits ) {
      return sub ( Int $n ) {
        return @digits[ *-$n ];
      };
  }.(@digits);

  # Q(n) 定義
  my $Q = sub ( Int $n ) {
    return ($n <= 6) ?? $n + 1 !! $n - 5;
  };

  # 数列の和を11で割った余りを計算します
  my $remainder = ( [+] (1..11).map:{ $P.(+$_) * $Q.(+$_) } ) % 11;

  given $remainder {
    when 0|1 {
      return $check_digit == 0;
    }
    default {
      return $check_digit == (11 - $remainder);
    }
  }
}

おわりです。

参考や注釈

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5