rubyチュートリアルを試してみる その3
id:Kiske:20070705:1183627478の続きです。7〜8章です。
プログラミング入門 - Rubyを使って -, by Chris Pine, 日本語ver. by S. Nishiyama
配列とイテレータ
配列と配列に関するメソッドの話です。ここはPHPとそんなに変わらない気がする。
練習問題
- では、この章の最初で述べたプログラムを書いてみましょう。
ヒント: 配列を順番に並び替える(ソートする)には素敵なメソッド sortがあります。 これを使いましょう。(訳注:配列 ary の最後に要素 elem を追加するには、ary << elem と記述します。)最初で述べられてるプログラムは下記です。
好きな数だけ単語の入力をしてもらい(1行に1単語、最後はEnterだけの空行)、 アルファベット順に並べ変えて出力するようなプログラムを書いてみましょう
str = gets.chomp array = [] while str != "" array << str str = gets.chomp end puts 'ソート結果' puts array.sort
- 上のプログラムをsortメソッドなしで 書けますか。プログラミングの大部分は、問題解決にあります。これはいい練習になります。
str = gets.chomp array = [] while str != "" array << str str = gets.chomp end i = 0 while i < array.length j = i + 1 while j < array.length if( array[i].to_s > array[j].to_s) tmp = array[i] array[i] = array[j] array[j] = tmp end j += 1 end i += 1 end puts 'ソート結果' puts array
とりあえず単純なソートで実装してみました。ruby自体はどんな実装なんだろ。やっぱクイックソートなのかな
- 以前、メソッドの章で書いた目次を表示するプログラムを修正してみましょう。
その際、プログラムの最初で目次の情報(つまり、章の名前やページ番号など)をすべてひとつの配列にしまいます。
その後、その配列から情報を取り出して美しくフォーマットされた目次を出力します。
lineWidth = 40 mokuji = [] title = '目次' mokuji.push title mokuji.push '1章: 数'.ljust(lineWidth) + 'p. 1'.ljust(lineWidth) mokuji.push '2章: 文字'.ljust(lineWidth) + 'p. 72'.ljust(lineWidth) mokuji.push '3章: 変数'.ljust(lineWidth) + 'p. 118'.ljust(lineWidth) puts mokuji
メソッドの作り方
自作メソッドの作り方について解説されてます。PHPでいうfunctionです。
Rubyだとdef〜endで定義されます。
練習問題
・上のenglishNumberを拡張してみましょう。最初にthousand(千の桁)を導入してください。
上のプログラムでは 'ten hundred'となっているところを'one thousand'を返すように、あるいは、'one hundred hundred'の代わりに'ten thousand'を返すようにします。
def englishNumber number if number < 0 return '負でない数を入力してください.' end if number == 0 return 'zero' end numString = '' onesPlace = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] tensPlace = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'] teenagers = ['eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'] left = number ### 1000の位 write = left / 1000 left = left - write * 1000 if write > 0 thousands = englishNumber write numString = numString + thousands + ' thousand' if left > 0 numString = numString + ' ' end end write = left/100 left = left - write*100 if write > 0 hundreds = englishNumber write numString = numString + hundreds + ' hundred' if left > 0 numString = numString + ' ' end end write = left/10 left = left - write*10 if write > 0 if ((write == 1) and (left > 0)) numString = numString + teenagers[left-1] left = 0 else numString = numString + tensPlace[write-1] end if left > 0 numString = numString + '-' end end write = left left = 0 if write > 0 numString = numString + onesPlace[write-1] end numString end
- englishNumberにさらに改良を加えましょう。 milion(百万)を加えます。
その結果、'one thousand thousand'の代わりに 'one million'が得られるようにします。
その後、billion(十億)とかtrillion(兆)とかを追加していってみましょう。どこまでいけるでしょうか?
def englishNumber number if number < 0 return '負でない数を入力してください.' end if number == 0 return 'zero' end numString = '' onesPlace = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] tensPlace = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'] teenagers = ['eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'] left = number digit_name = [' milion', ' thousand', ' hundred'] digit_number = [1000000, 1000, 100] pointer = 0 while pointer < digit_name.length write = left / digit_number[pointer] left = left - write * digit_number[pointer] if write > 0 milion = englishNumber write numString = numString + milion + digit_name[pointer] if left > 0 numString = numString + ' ' end end pointer += 1 end # 10の位 write = left / 10 left = left - write * 10 if write > 0 if( (write == 1) and (left > 0)) numString = numString + teenagers[left-1] left = 0 else numString = numString + tensPlace[write-1] end if left > 0 numString = numString + '-' end end # 1の位 write = left left = 0 if write > 0 numString = numString + onesPlace[write-1] end numString end
100万、10億も1000と同じように追記できるので配列表記にして処理をひとまとめにしてみました。
- weddingNumberはどうでしょう? このプログラムはenglishNumber とほとんど同じように動作しますが、"and" という接続詞をやたらめったら挿入します。
たとえば 'nineteen hundred and seventy and two' という具合に、結婚式の招待状のような感じで。
もう少し例を挙げたいと思いましたが、私自身詳しくありません。結婚のコーディネータに訊いてみるのも良いでしょう。
weddingNumberって何でしょう・・・?わからないので飛ばしました
- "99本のビールが壁に..." englishNumberと以前作ったプログラムを使って、今度は正しい方法でこの歌の詩を出力させなさい。
その後は、9999から初めてコンピュータをこらしめましょう。 (ただ、あまり大きな数字を使うと、コンピュータといえども全部出力するのにかなりの時間を必要とします。
10万本のボトルには、かなりの時間がかかります。もし、100万本のボトルなどとするとあなた自身がひどい目に会いますよ。)
def singasong number while number > 0 num = englishNumber(number) puts num + ' Bottles of beer on the wall' puts num + ' Bottles of beer' puts 'Take one down and pass it around' number -= 1 puts englishNumber(number) + ' Bottles of beer on the wall' end end
上で作ったenglishNumberを中で使ってますので動かすときはenglishNumberの定義も必要です。