Math Battle [ 0140: 連想配列を使いました ]

[ 0140: 連想配列を使いました ]


[ 西尾三奈さんの補足 ]

0137 で多絵さんが作ってくださった Perl スクリプトを改良しました。

if / elsif / else のネスティングが煩雑ですので、
各頂点から可能な移動ベクトルは連想配列の中に組み込みました。

改良版には if は全く含まれていません。ソースコードは以下のとおりです。

#!/usr/local/bin/perl

$N = 1000;
$f = 100/$N;
$sum = 0;
%sums = (0, 0, 0, 0);
($x1, $y1, $z1) = (0, 0, 1);
($x2, $y2, $z2) = (1, 1, 1);
%vectors = (
 "0,0,0", [[1,0,0],[0,1,0],[0,0,1]],
 "0,0,1", [[1,0,0],[0,1,0],[0,0,-1]],
 "0,1,0", [[1,0,0],[0,-1,0],[0,0,1]],
 "0,1,1", [[1,0,0],[0,-1,0],[0,0,-1]],
 "1,0,0", [[-1,0,0],[0,1,0],[0,0,1]],
 "1,0,1", [[-1,0,0],[0,1,0],[0,0,-1]],
 "1,1,0", [[-1,0,0],[0,-1,0],[0,0,1]],
 "1,1,1", [[-1,0,0],[0,-1,0],[0,0,-1]]);

MAIN: {
 my $d;
  for ($i=0; $i<$N; $i++) {
   $d = abs($x1-$x2)+abs($y1-$y2)+abs($z1-$z2);
   $sums[$d]++;
   $sum += sqrt(($x1-$x2)**2 + ($y1-$y2)**2 + ($z1-$z2)**2);
   ($x1,$y1,$z1) = &get_next($x1,$y1,$z1);
   ($x2,$y2,$z2) = &get_next($x2,$y2,$z2);
  }
  printf("Average distance: %.2f\n", $sum/$N);
  printf("(0: %.0f%) (1: %.0f%) (sqrt(2): %.0f%) (sqrt(3): %.0f%)\n",
   $sums[0]*$f, $sums[1]*$f, $sums[2]*$f, $sums[3]*$f);
}
sub get_next() {
 my ($x,$y,$z) = @_;
 my ($dx,$dy,$dz);
 my $index = int(rand(3));
 my $key;

 $key = sprintf("%d,%d,%d", $x, $y, $z);
 $x += $vectors{$key}->[0][$index];
 $y += $vectors{$key}->[1][$index];
 $z += $vectors{$key}->[2][$index];

 return($x,$y,$z);
}

実行結果は:

Average distance: 1.06
(0: 25%) (1: 0%) (sqrt(2): 75%) (sqrt(3): 0%)


[ 浅見多絵さんのコメント ]

わー、三奈ちゃん。ありがとう。こんなにスッキリ短く書けるなんて。
移動ベクトルは連想配列に入れたほうが見てわかりやすいし、
ミスするおそれがないですね。勉強になりました。

それから $index = int(rand(3)); としたところ。
こういう部分で if / elsif / else の場合分けをする必要はないですね。


[ 大宙乗児君のコメント ]

三奈さんのソースコードは美しいですね。正憲君も感心しています。

機会があったら、 Math Battle チームでプログラムのソースコードを書く勉強会をやりませんか?
プログラムの構造やらスコープから始まって、わかりやすい変数名のつけかた、
デバッグのやりかた、などなど。
Perl 以外におすすめのプログラム言語があれば教えてください。
よろしくお願いいたします。


[ 湯会老人のコメント ]

そういうことであれば、定期的に勉強会をやりましょう。
月 1 回のペースぐらいで集まって。
都合で出席できないメンバーは Skype で参加してください。

第一回は 4 月 28 日 (日) とします。
それまでに、
各自わからないことや他のメンバーに質問したいことをまとめておいてください。
Math Battle は知恵を共有するグループです。

[ 0141: 次の記事 ]

[ 0140: 連想配列を使いました ]

[ 0139: 積み重ねた半円の面積 ]

[ 0138: 0137 の補足 ]

[ 0137: 0133 ふたたび ]

[ 0136: 出題と回答の振り返り ]

[ 0135: 3乗根の和 ]

[ 0134: 難問ふたたび ]

[ 0133: 立方体頂点上の2匹の平均距離 ]

[ 0132: 直角三角形の辺上の正三角形 ]

[ 0131: 円の中の2個の正三角形 ]

[ 0130: 2個の同心円と接線 ]

[ 0129: 長方形の中の2個の半円 ]

[ 0128: 半円の中の円 ]

[ 0127: 三角形の中の辺x ]

[ 0126: xy2次方程式の整数解 ]

[ 0125: 湯会老人の近況報告 ]

[ 0124: 真実の愛は無限にある? ]

[ 0123: AIで素敵な曲を作るのは可能? ]

[ 0122: 雪が降りはじめたのはいつ? ]

[ 0121: ドラゴン曲線の描画例 ]

[ 0120: 前の記事 ]

[ トップページへ ]