Created
August 15, 2012 14:23
-
-
Save tateisu/3360557 to your computer and use it in GitHub Desktop.
数式を徐々に変化させるプログラム
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!perl | |
use utf8; | |
use warnings; | |
# ノードにランダムアクセスするための配列 | |
my @list = (); | |
# 配列にノードを追加してそのインデクスを返す | |
sub add_node($){ | |
my($node)=@_; | |
push @list,$node; | |
return $#list; | |
} | |
# 配列中のノードを入れ替える | |
sub replace_node($$){ | |
my($idx,$node)=@_; | |
$list[$idx] = $node; | |
} | |
# 葉となるノードを生成する | |
sub gen_leaf{ | |
my $mode = int rand 3; | |
if($mode==0){ | |
return add_node { operate => "idx" }; | |
}elsif($mode==1){ | |
return add_node { operate => "inum", value=>( int rand 10) }; | |
}else{ | |
return add_node { operate => "past", value=>( int rand 3) }; | |
} | |
} | |
# 初期のツリー | |
my $root = gen_leaf(); | |
# 適当に式を変形する | |
for( 1.. 10 ){ | |
# 既存のノードのどれかをランダムに選ぶ | |
my $node_idx = int rand @list; | |
# そのノードを複製する | |
my $node_idx_clone = add_node( $list[ $node_idx] ); | |
# そのノードを置き換える | |
my $mode = int rand 3; | |
if( $mode == 0 ){ | |
# 定数項の付与 | |
$node = { operate =>"add", left=> $node_idx_clone , right =>gen_leaf(), apply=>sub{ my($l,$r)=@_; return $l + $r } }; | |
}elsif($mode==1){ | |
# 乗算 | |
$node = { operate =>"mul_inum", left=> $node_idx_clone , right =>gen_leaf(), apply=>sub{ my($l,$r)=@_; return $l * $r } }; | |
}elsif($mode==2){ | |
# 数値の桁数 | |
$node = { operate =>"length", left=> $node_idx_clone , right =>gen_leaf(), apply=>sub{ my($l,$r)=@_; return length("".$l) * $r } }; | |
} | |
replace_node( $node_idx , $node ); | |
} | |
############################## | |
# 実際に式を評価してみる | |
sub solve_tree{ | |
my($env,$node_idx) = @_; | |
my $node = $list[ $node_idx ]; | |
return $node->{value} if $node->{operate} eq "inum"; | |
return $env->{n} if $node->{operate} eq "idx"; | |
if($node->{operate} eq 'past' ){ | |
my $offset = $node->{value}; | |
my $size = 0+@{ $env->{past}}; | |
return 0 if $offset >=$size; | |
return $env->{past}[ $size - 1 - $offset ]; | |
} | |
return $node->{apply}->( solve_tree($env,$node->{left}) ,solve_tree($env,$node->{right}) ); | |
} | |
my $env = { past=>[] }; | |
for my $idx (1..10){ | |
$env->{n} = $idx; | |
my $v = solve_tree($env,$root); | |
push @{$env->{past}},$v; | |
print $v,","; | |
} | |
print "\n"; | |
__END__ | |
実行例 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment