Perlサンプル28 正規表現で遊ぶ
投稿:2020-11-27
こちらのツイートを拝見しました。 正規表現にhがあるのでperlは入ってないんだ。
古今東西のプログラミング言語の名前からbi-gram(N-gramの2文字版)の出現頻度を集計します。 ターゲットの名前が2文字で特定できれば良い訳です。 なので、ターゲットもbi-gramを調べて最も少ない頻度のbi-gramを使い正規表現を生成して絞り込む作戦です。 連続する2文字の文字クラスが2文字(なんだそりゃ?)でマッチさせ、ターゲットと異なる順に並べればバレないはず(取らぬ狸の皮算用)。
#!/usr/bin/env perl
use v5.26;
use utf8;
use warnings;
use strict;
use Encode::Locale;
use feature "say";
use open IO => ":utf8";
binmode STDOUT, ":encoding(console_out)";
binmode STDERR, ":encoding(console_out)";
$| = 1;
# ウィキのプログラミング言語から
my @program = qw|
FORTRAN COBOL LISP ALGOL PL/I BASIC
BCPL Simula Forth Pascal B
C Prolog Smalltalk ML awk
SQL Ada C++ Objective-C PostScript
Eiffel Perl Mathematica Python Tcl
Haskell Ruby Lua Delphi Java
JavaScript Erlang C# Scala F#
D Go Rust Dart Kotlin
Julia Swift Hack
|;
say "プログラミング言語:@program";
# 連続する2文字の頻度集計
my %bi_gram;
for (@program) {
$bi_gram{$_}++ for gen_bi_gram($_);
}
my $histogram;
$histogram .= "$_($bi_gram{$_}) " for sort {$bi_gram{$a} <=> $bi_gram{$b} or $a cmp $b} keys %bi_gram;
say "bi-gram:$histogram";
# ターゲットのプログラミング言語
use constant TARGET => "Python";
say "ターゲット:" . TARGET;
my @target_bi_gram = sort {$bi_gram{$a} <=> $bi_gram{$b}} gen_bi_gram(TARGET);
say "ターゲットのbi-gram:@target_bi_gram";
# 最小頻度の2文字を採用
my $target_bi_gram = $target_bi_gram[0];
# ターゲットの文字順の場合はひっくり返してバレないようにします(笑)
$target_bi_gram = reverse $target_bi_gram if TARGET =~ /$target_bi_gram/;
# 正規表現を生成
my $regex = qr/[$target_bi_gram]{2}/i;
say "正規表現:$regex";
say "分かりやすい版:/[$target_bi_gram]{2}/i";
# チェック
my @match = grep {/$regex/} @program;
say "マッチ:@match";
# 連続する2文字を生成
sub gen_bi_gram {
my ($str) = @_;
my %bi_gram;
my $before;
for (split //, lc $str) {
$bi_gram{$before lt $_ ? "$before$_" : "$_$before"} = 1 if defined $before;
$before = $_;
}
return sort keys %bi_gram;
}
プログラミング言語:FORTRAN COBOL LISP ALGOL PL/I BASIC BCPL Simula Forth Pascal B C Prolog Smalltalk ML awk SQL Ada C++ Objective-C PostScript Eiffel Perl Mathematica Python Tcl Haskell Ruby Lua Delphi Java JavaScript Erlang C# Scala F# D Go Rust Dart Kotlin Julia Swift Hack bi-gram:#c(1) #f(1) ++(1) +c(1) -c(1) -e(1) /i(1) /l(1) ab(1) ai(1) ap(1) au(1) aw(1) bc(1) bj(1) bu(1) by(1) ce(1) ck(1) cl(1) co(1) cp(1) de(1) ef(1) eh(1) ei(1) ej(1) ek(1) em(1) ep(1) ev(1) ff(1) ft(1) gl(1) gn(1) hi(1) ho(1) hp(1) im(1) in(1) iv(1) iw(1) ju(1) kl(1) ko(1) ks(1) kw(1) lm(1) lq(1) ms(1) mu(1) no(1) op(1) os(1) ot(1) pr(1) ps(1) py(1) qs(1) su(1) sw(1) ty(1) ad(2) ah(2) aj(2) am(2) an(2) ar(2) at(2) av(2) bo(2) ci(2) cr(2) ct(2) er(2) fi(2) fo(2) ip(2) ir(2) it(2) ll(2) lr(2) lt(2) pt(2) ru(2) st(2) el(3) go(3) ht(3) il(3) is(3) lo(3) lp(3) lu(3) or(3) rt(3) ac(4) as(4) cs(4) al(6) ターゲット:Python ターゲットのbi-gram:ho no py ty ht 正規表現:(?^ui:[oh]{2}) 分かりやすい版:/[oh]{2}/i マッチ:Python