ルモーリン

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