今回は汎用性を考えて解いたもの……と言いたかったが、すでに順列生成の関
数が TSperl に流れているので、あまり独自性がなくなってしまった。まあ、せっ
かく作ったので出します(^^;。dune さんのと同じように実行でき、同じ結果が
戻ります。
--------^ ticket4.pl ( date:02-05-13 time:08:00 ) ----------< cut here
#! env perl
### 初期化
my $num = "8 4 2 1";
my $op = "+ - * /";
my $target = 10;
my $opn = $num =~ s/\s+/ /g;
my @num = mkary("", $num);
my @op = mkary2("", $op, $opn);
### 数値と演算子を組み合わせる、実際の処理部分
for (my $i = 0; $i < @num; $i++) {
for (my $j = 0; $j < @op; $j++) {
my $exp = $num[$i];
$exp =~ s/ /substr($op[$j], $_, 1)/e foreach (0 ... ($opn - 1));
printf("$exp=%d\n", eval($exp)) if (eval($exp) == $target);
}
}
### $post の要素から作られる全順列を、配列の形で返す
### "1 2 4 8", "1 4 2 8", ...
sub mkary {
my ($pre, $post, @ary) = @_;
return (@ary, $pre) if ($post =~ /^\s*$/);
foreach (split(/\s+/, $post)) {
my $post1 = $post;
$post1 =~ s/$_\s*//;
@ary = mkary(($pre eq "")? $_: "$pre $_", $post1, @ary);
}
return @ary;
}
### $str から n 個、重複を許して取り出し、並べたものを配列の形で返す
### "+++", "++-", ...
sub mkary2 {
my ($exp, $str, $n, @ary) = @_;
return (@ary, $exp) if ($n == 0);
@ary = mkary2(($exp eq "")? $_: "$exp$_", $str, $n - 1, @ary) foreach (split(/\s+/, $str));
return @ary;
}
--------$ ticket4.pl ( lines:39 ) --------------------------< cut here
myary2 は上で使うのに一番手軽なように、空白をつめたものを返してますが、
この辺は空白入れるのも、文字列の配列で返すのをやめて配列の配列にするのも
少し手を入れれば可能ですから、まあ汎用的と言えるかと思います。
--
本田博通(閑舎)
Hiromichi Honda <raku@...>