ひらがな対応のシーザー暗号の Perl スクリプト

シーザー暗号をかける Perl スクリプトをついカッとなって作ってしまいました。できたと思ってスレを見たら、すでに解かれてしまっていたりw

標準入力にいれれば、標準出力から答えが出てきます。シーザー暗号は、ずらす値を正負逆にするだけで、同じプログラムで暗号化と復号ができてお手軽ですね。

#!/usr/bin/perl

use strict;
use encoding 'shift_jis'; # ソースコードも入出力も Shift_JIS

# シーザー暗号で使用するシンボル一覧
# 各行で最初と最後がループする
my @symbols = (
    "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん",
    "がぎぐげござじずぜぞだぢづでどばびぶべぼ",
    "ぱぴぷぺぽ",
    "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン",
    "ガギグゲゴザジズゼゾダヂヅデドバビブベボ",
    "パピプペポ",
    "abcdefghijklmnopqrstuvwxyz"
);

# シーザー暗号のずらす量
my $offset = -3;

my @symbolmaps;

foreach my $list (@symbols) {
    my @idx2sym = unpack "U*", $list;
    my %sym2idx = map { $idx2sym[$_] => $_ } (0 .. $#idx2sym);
    push @symbolmaps, [\@idx2sym, \%sym2idx];
}

while (my $str = <>) {
    chomp $str;
    my @str = unpack "U*", $str;
    foreach my $c (@str) {
        my $val = $c;
        foreach my $m (@symbolmaps) {
            my ($idx2sym, $sym2idx) = @$m;
            if (exists $sym2idx->{$c}) {
                my $newidx = ($sym2idx->{$c} + $offset) % ($#$idx2sym + 1);
                $val = $idx2sym->[$newidx];
                last;
            }
        }
        print pack("U", $val);
    }
    print "\n";
}