2006-11-24 久しぶりに
■[入門記事]第一回演習問題 模範解答 & 変数についてもう少し詳しいこと
前回の演習問題の模範解答を載せておきます。
1. お菓子の名前を入れられる様にしなさい
模範解答
puts "ようこそ!あなたの名前を教えて下さい。"
name = gets.chomp
puts "#{name}さん、ヨロシクお願いします。"
puts "#{name}さんの買ったお菓子は何ですか?"
okasi = gets.chomp
puts "#{okasi}の値段を入れて下さい。"
price = gets.to_i
puts "#{name}さんのお菓子は、#{price * 1.05}円です。"
解説
これは、今までやってきたことをきちんと理解出来ているかの確認です。
5行目でgetsしてユーザから入力をもらい、そこから改行を取り除いた物を変数okasiに代入しています。
2. 税率をユーザから指定できるようにしなさい。
模範解答
puts "ようこそ!あなたの名前を教えて下さい。"
name = gets.chomp
puts "#{name}さん、ヨロシクお願いします。"
puts "#{name}さんの買ったお菓子は何ですか?"
okasi = gets.chomp
puts "#{okasi}の値段を入れて下さい。"
price = gets.to_i
puts "税率は何%ですか?"
tax = gets.to_i
puts "#{name}さんのお菓子は、#{price * (100+tax) / 100}円です。"
解説
これは少し応用です。
先ず14行目でユーザから税率を%で入力してもらい、其れを整数と解釈して変数taxに代入します。
そして15行目では#{}の中で消費税込みの値段を計算し、文字列の中に埋め込み、表示させています。
ところで、このコードはこんな風にも書けます。
puts "ようこそ!あなたの名前を教えて下さい。"
name = gets.chomp
puts "#{name}さん、ヨロシクお願いします。"
puts "#{name}さんの買ったお菓子は何ですか?"
okasi = gets.chomp
puts "#{okasi}の値段を入れて下さい。"
price = gets.to_i
puts "税率は何%ですか?"
tax = gets.to_i
tax = (100+tax) / 100
puts "#{name}さんのお菓子は、#{price * tax}円です。"
なにやら14行目が増えてます。
tax = (100 + tax) / 100
とありますね。
ちょっと待って下さい?両辺にtaxがありますね。こんな風に書いては、
tax = (100 + tax) / 100 tax = (100 + ((100 + tax) / 100)) / 100 tax = (100 + ((100 + ((100 + ((100 + tax) / 100)) / 100)) / 100)) / 100 ...
と言う風になってしまって、上手くいかないのではないでしょうか?
これは尤もな疑問です。確かに数学ではこの様に書いた場合、こうなってしまいます。
しかし、rubyの場合、まずは右辺の値を評価してから左辺の変数に代入します。
この例だと、先ず、右辺の値を計算するときに「これまでのtax」の内容を調べて、結果を出します。次に、その答えをtaxに再び代入しているのです。
この時点で右辺のtaxと左辺のtaxは別物になっている為、今云ったような問題は起こらないのです。。
また、更にtaxの部分はこういうふうに書くことも出来ます。
tax = (100+gets.to_i) / 100
ところで、「あなたの名前」やお菓子の名前を聞くときに「gets.chomp」と言う風にするのは、getsで渡された文字列の後ろに改行が付いているからでした。
しかし、よく見てみると、値段や税率を入れてもらうときは「gets.to_i」だけです。後ろの改行を取り除いていません。何故こっちは取り除かなくて大丈夫なのかというと、to_iは後ろに何か余計な文字が付いていてもきちんと無視してくれるからです。
と、いうことは、消費税入力のところで、「5%」とか「5%だよーん」という入力でも、きちんと5として解釈してくれるのです。便利ですね。
ところで、今までは整数の入力をもらってきましたが、小数でもらいたい場合には、to_iの代わりにto_fを使います。逆に、整数や小数から文字に変換したいときには、to_sを使うことで文字列になってくれます。
これはよく使うので、覚えておくと良いでしょう。
2006-10-11 唐突に入門記事とか書いてみる
■[入門記事]Ruby入門 〜簡単な計算機を作ろう!〜
rubyとは何か
rubyとは、まつもとゆきひろさんが作ったオブジェクト指向プログラミング言語の一種です。
オブジェクト指向、とかまあその辺は後で追々分かってくると思うので、「そう云う物なんだなあ」と思っていて下さい。
何故rubyか
筆者が好きだから(爆
一番初めは
まずはrubyのインストールです。Ruby Programming Languageを参照すると良いでしょう。
インストールが済んだら、さあ、早速プログラムを書いてみましょう!
puts "Hello, world!"
この内容をhello.rbとして好きなところに保存して、実行してみて下さい。
すると、プロンプトに"Hello, world!"と表示されたと思います。そうなればひとまず成功です。
説明すると、「puts 〜」というのは、「〜を出力して改行しなさい!」と言う命令です。一方「"Hello, orld!"」は「Hello, world!」と言う内容の文(文字列)を表しています。
因みに、改行をつけずに表示するには、printを使います。
数字を表示してみる
太郎君は100円のチョコを一つ買おうとしています。しかし、このお店は困ったことに税別表示です(モグリだ!)。一体消費税込みでいくらなんでしょうか?
自分で計算してもいいんですが、面倒なのでパソコンにやらせてしまいましょう。
次のプログラムをtax.rbとして保存して実行してみて下さい。
puts 100*1.05
どうですか?恐らく105.0と表示されたと思います。つまり太郎君は105円払えばいいわけです。めでたしめでたし。
しかし、ただ105と表示するだけでは余りにも不親切です。せめて「105.0円」とか表示してほしいですよね?ですよね?
……よろしい。ではそう表示する様に改良してみましょう。tax.rbを次の様に書き換えて実行して下さい。
puts "太郎君のチョコは#{100*1.05}円です。"
今度は、「太郎君のチョコは105円です」と表示されたと思います。
"と"の間に#{式}と書くと、式を計算した結果を文字列に変換してその場所に埋め込んでくれます。これは便利な機能なので覚えておきましょう。
ユーザからの入力
さて。太郎君はいつも100円のチョコを買うとは限りません。200円のガムかも知れないし、10円のうまい棒20本かも知れません。……それに、買うのは太郎君ではなく花子さんかもしれません。
次のプログラムをtax-ex.rbと言う名前で保存して実行してみて下さい。
puts "ようこそ!あなたの名前を教えて下さい。"
name = gets.chomp
puts "#{name}さん、ヨロシクお願いします。"
puts "値段を入れて下さい。"
price = gets.to_i
puts "#{name}さんのお菓子は、#{price * 1.05}円です。"
ようこそ!あなたの名前を教えて下さい。
と表示されて止まったら、名前を入力します。ここでは、太郎としましょう。
ようこそ!あなたの名前を教えて下さい。 太郎 太郎さん、ヨロシクお願いします。 値段を入れて下さい。
云われたとおりに値段を入れましょう。
ようこそ!あなたの名前を教えて下さい。 konn konnさん、ヨロシクお願いします。 値段を入れて下さい。 200 konnさんのお菓子は、210.0円です。
無事、値段をしることが出来ましたね。
どういう仕組みなんだだよ?
putsの部分はもう、良いですね?
二行目。name = gets.chomp!とあります。
getsは、「ユーザから一行入力をもらえ」と言う意味です。されに、その結果に対してchomp!と言うのを使っています。「chomp」とは「その文字列の最後の改行を取り除け!」という意味です。*1「gets.chomp」なので「ユーザから一行入力をもらってその後ろの改行を取り除いたもの」となります。
そして更に其れを、nameと言う変数に代入しています。変数とは、値を仕舞っておく匣の様なものです。つまり、nameという匣を用意して、その中にユーザからの入力を仕舞っているわけですね。
三行目は、今入力してもらったnameさんに挨拶をしています。
四行目飛ばして五行目。
はい、getsですね。まずユーザから入力をもらいます。「gets.to_i」とあります。to_iは、「整数と解釈して!」と言う意味になります。つまり、ここでは入力された文字を数と解釈して、priceという箱にしまっていると云うことです。
そして最後の行。これはもう、分かりますね?price*1.05で、税込みの値段を出しています。
演習問題
- お菓子の名前を指定できるようにしなさい。
- 税率をユーザから指定できるようにしなさい。
*1:本当は、getsで得られた値のchompメソッドを呼び出していると云うことなのですが、これは追々やっていきます。
2006-06-10 succの従兄弟
■succ又従兄弟多バイト仮対応・破壊的メソッド実装
String#replaceを使って破壊的メソッドを実装。
それから、each_byteからまたすぐにeach_charに戻しまして、かなり暫定的に多バイト対応に。
ただ、jcode.rbとか見てると、多バイト版succ/succ!がかなり複雑に作られているようで、
恐らくこんなシンプルなのじゃダメですね、ハイ。
そら、コード。
require "jcode"
require "enumerator"
class String
def succ2(incr=1)
Enumerable::Enumerator.new(self, :each_char).inject(""){|r, i| i[-1] = (i[-1] + incr).chr; r += i}
end
def succ2! *arg
replace succ2(*arg)
end
end
考えていること
- i[-1] = (i[-1] + incr).chr; r += i を一文に。
- というか多バイト対応をもっときちんと。
- 楽にする方法無いかな〜っと。
■succ又従兄弟続報
どうやら、each_charの代わりにeach_byteを使えば良い模様。
そうすっとjcode.rb要らなくなるのね。ただ、多バイト対応にするにはまたeach_charに戻す必要があるけどね。
コード。
require "enumerator"
class String
def succ2(incr=1)
Enumerable::Enumerator.new(self, :each_byte).inject(""){|r, i| r += (i + incr).chr}
end
end
■succの又従兄弟
String#succの従兄弟のようなメソッドを作ってみました。
文字列に含まれる全ての文字を、指定された数だけズラします。
require "jcode"
require "enumerator"
class String
def succ2(incr=1)
Enumerable::Enumerator.new(self, :each_char).inject(""){|r, i| r += (i[0] + incr).chr}
end
end
requireするのとかを除いて本質だけ見てみると、何とワンライナー!一行野郎!すごいなあ。
実行結果
"abcdefg".succ2 #=> "bcdefgh" "abcdefg".succ2(2) #=> "cdefghi" "R is for Ruby".succ2(3) #=> "U#lv#iru#Uxe|" "R is for Ruby".succ2(0) #=> "R is for Ruby" "abcdefg".succ2(-1) #=> "`abcdef"
工夫したところ
- Enumerable::Enumerator を使った
- 意外と使える!
- each_charも使った
思ったこと
String#each_char は、jcode.rbじゃなくて標準で入れて欲しい!
更に思ったこと
いっそString#eachと置き換えで!
今後やりたいこと
- 名前をもうちょいマシに
- 破壊的メソッドも作りたい
- 多バイト文字対応
初学者ですが演習問題解いてみました。
一見していただけると嬉しいです。
是非解答を見てみたいのですが、どちらにあるのでしょうか?