ALGOBIT

2010/10/08

ハノイとバベルの塔 第八階 – 端末アニメ in Ruby

Filed under: 離散的な気まぐれ — タグ: , — Kohyama @ 02:53

第五回, 第六回 と同様の構造で書いてみます.

#!/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 で呼び出しているだけであり, クラスに適切なメソッドを定義することで実現されています.

部分文字列を取り出すときに, 配列の添字に負数が利用できるのも良いですね.

第五回, 第六回 で利用した「ランダムアクセスできるスタック」みたいな能力を「配列」が持っていることで記述量はずいぶん減っています.


Yugui
オライリージャパン
発売日:2008-06-26

本書は対象読者の設定が明快です.
既にいくつかのプログラミング言語を実用していて, 他のプログラミング言語と Ruby が違うところだけ知りたい人向けです.
従ってページ数に対して情報量が多く感じました. お買い得.
多くの言語を操る著者さんの, 特定のプログラミング言語に偏った考え方や用語にならないようにという配慮が素敵です.

Copyright © 2010 Yoshinori Kohyama All Rights Reserved.