#!/usr/bin/ruby def move(src, tmp, dst, n) if (n == 0) return end move(src, dst, tmp, n - 1) dst.push(src.pop()) printAStep() move(tmp, src, dst, n - 1) end def printAStep() sleep($w/1000.0) print "\x1b[2J\x1b[2;1H" $N.times do |i| $pegs.each do |peg| if (peg.length < $N - i) print " " + $ws + "|" + $ws + " " else l = peg[$N - i - 1] print " " + $ws[l..-1] + $bar[0..(l - 1)] + "|" + $bar[0..(l - 1)] + $ws[l..-1] + " " end end print "\n" end print $grnd + "\n" end $N = (0 < ARGV.length) ? ARGV[0].to_i : 3 $w = (1 < ARGV.length) ? ARGV[1].to_i : 500 $pegs = [[],[],[]] $N.downto(1) do |i| $pegs[0].push(i) end $ws = " "*$N $bar = "-"*$N $grnd = "="*(6*$N + 9) printAStep() move($pegs[0], $pegs[1], $pegs[2], $N)
$N.times do |i| ... end のループに, 数値もオブジェクトであることや, ブロック(無名関数)を受け取る既定義メソッドなどに言語の特色が出ています.
手続き中で任意個の '-' からなる文字列を生成してもさほど遅くはならないと思うのですが, 言語毎の特色を見るために「$N個の '-' からなる文字列を作っておいて, 部分文字列を使う」ように書いています.
n個の '-' からなる文字列を "-"*n と書けるのは
* という演算子の機能を規定する言語の組み込み機能ではありません.
* も単なるメソッドであり, "-"*n の実態は "-".*(n) すなわち, 文字列 "-" のインスタンスメソッド * を引数 n で呼び出しているだけであり, クラスに適切なメソッドを定義することで実現されています.
部分文字列を取り出すときに, 配列の添字に負数が利用できるのも良いですね.
第五回, 第六回 で利用した「ランダムアクセスできるスタック」みたいな能力を「配列」が持っていることで記述量はずいぶん減っています.
本書は対象読者の設定が明快です.
既にいくつかのプログラミング言語を実用していて, 他のプログラミング言語と Ruby が違うところだけ知りたい人向けです.
従ってページ数に対して情報量が多く感じました. お買い得.
多くの言語を操る著者さんの, 特定のプログラミング言語に偏った考え方や用語にならないようにという配慮が素敵です.
既にいくつかのプログラミング言語を実用していて, 他のプログラミング言語と Ruby が違うところだけ知りたい人向けです.
従ってページ数に対して情報量が多く感じました. お買い得.
多くの言語を操る著者さんの, 特定のプログラミング言語に偏った考え方や用語にならないようにという配慮が素敵です.