第7回 正規表現とRuby言語でのプログラミング レポート課題 氏名:佐藤智久 学籍番号:C1110803 語学クラス:英語2 コース:地域共創コース ※前に1度送りましたが、一部修正しましたので再送信します。 1.筆記問題 A. a.0bから0xへの変換なので、2進数から16進数への変換を行う。 2進数 11010110を16進数に変換する場合、まず右端から4桁ずつ区切ってい く。これは16進数を表示する際にエラーを発生させないようにするためだ。 そうすると、 1101 0110 の2つに分けられる。 次にこれらを2進数の考え方で計算していく。 1101は、 1*2**3 =8 1*2**2 =4 0*2**1 =0 1*2**0 =1 なので、 8 + 4 + 0 + 1 = 13 0110は、 0*2**3 =0 1*2**2 =4 1*2**1 =2 0*2**0 =0 0 + 4 + 2 + 0 = 6 あとはこれらをつなげて読んだ値が16進数となる。 ちなみに「13」は16進数表示では d である。 よって答えは 0xd6 である。 b.0dから0xへの変換なので10進数から16進数への変換である。 最初に 1024 を 16 で割る。 1024 / 16 = 64 64 / 16 = 4 そして2進数と同じように割った余りを逆から読んだ値が16進数に変換した 値となっている。 1024 % 16 = 0 64 % 16 = 0 これに余った4を加えた結果、 答えは 0x400 となる。 B.自分の名前のアルファベットを16進法表示で表す場合、ASCIIコード表を参考 にするとよい。 まず私の名前をアルファベットに直すと、 Sato Tomohisa となる。 これをASCIIコードに当てはめて考えていくと、 S → 0x53 a → 0x61 t → 0x74 o → 0x6f T → 0x54 o → 0x6f m → 0x6d o → 0x6f h → 0x68 i → 0x69 s → 0x73 a → 0x61 となる。 よって、私の名前のアルファベットを16進法表示で表すと、 Sato Tomohisa → 0x53 0x61 0x74 0x6f 0x54 0x6f 0x6d 0x6f 0x68 0x69 0x73 0x61 である。 参考文献 第5回 「ASCIIコード表」 : http://roy/~madoka/2012/r1/05/r1_05_01_theme_01_asciicode.html 2.プログラム問題 A.前回使用したデータファイル「data_c111080.dat」を読み込み、選手を検索 するプログラム「data_c111080.rb」を作成した。 ちなみに、こちらはまだ幾つか未完成の部分があるが、経過報告ということ で記載させていただく。 作成したプログラムは以下の通りである。 #!/usr/koeki/bin/ruby #coding: euc-jp s = Array.new #選手名簿の各種配列の新規作成 w = Array.new #以下も同様である n = Array.new a = Array.new y = Array.new STDERR.print("選手を検索:") #どのような選手を探すか検索 pat = STDIN.gets.chomp #正規表現を使用し、標準出力 req = Regexp.new(pat,true) で表示する i=0 open("data_c111080.dat" , "r") do |cmd| #data_c111080.datを読み込み while data = cmd.gets #data変数に格納 if req =~ data #dataとreqが似ている場合 if /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)/ =~ data #dataが左辺の場合 s[i] = $1 #対応する部分を配列に格納していく w[i] = $2 #以下も同様である n[i] = $3 a[i] = $4 y[i] = $5.to_i #この部分は整数型で格納する printf("番号%d: %s選手\n",i+1 ,$3) #候補に上がった選手を表示 i += 1 end end end end #ループの終了 STDERR.print("どの選手を探していますか?\n番号を入力して下さい→") j = gets.to_i #候補の中から選手を選択 printf("%s選手を選択しました。\n\n",n[j-1]) printf("%s選手は%sの%s代表で、%d年のオリンピックに出場しました\n", n[j-1] ,s[j-1] ,w[j-1] ,y[j-1]) #選択した選手の一覧を表示 実行結果 pan{c111080}% ./data_c111080.rb [~/Ruby] 選手を検索:1992 番号1: 吉田秀彦選手 番号2: 古賀稔彦選手 どの選手を探していますか? 番号を入力して下さい→2 古賀稔彦選手を選択しました。 古賀稔彦選手は男子の71kg代表で、1992年のオリンピックに出場しました B.今回はレポート課題のページのデータ例を使用させていただいた。ファイル 名は「taxi.dat」。 また、今回作成したプログラム「open_taxi.rb」は以下のような内容となっ た。 #!/usr/koeki/bin/ruby #coding:euc-jp typea = 0 #各種変数の初期設定 typeb = 0 #typea~c: 各タクシーの総売上を代入するための変数 typec = 0 avekma = 0 #avekma~c: 各タクシーの平均走行距離を代入するための変数 avekmb = 0 avekmc = 0 a = 0 #a~c: 各タクシーに何回乗車したかチェックするための変数 b = 0 c = 0 #←ここまで time = Array.new #配列の初期設定 taxi = Array.new km = Array.new hour = Array.new #←ここまで i=0 open("taxi.dat" , "r") do |cmd| #taxi.datファイルを読み込み、 while type = cmd.gets #ループ処理を実行 if /(\S+)\s+(\S+)\s+(\d+.\d+)/ =~ type #指定条件に一致した場合 time[i] = $1 #配列にデータファイルの文字列を格納 taxi[i] = $2 #上と同様 km[i] = $3.to_f #ここには実数型の値を格納する i += 1 end end end #ループ処理の終了 j=0 while j < taxi.length #jがtaxiの格納数より大きくなったら処理を終了 if taxi[j] == "a" #aが入力された場合、以下の処理を行う typea += km[j] * 70 #距離に応じた値段を計算 typea += 650 #それに加え乗車した回数ごとに料金を足していく avekma =avekma.to_f + km[j].to_f #aの合計走行距離を求める a += 1 elsif taxi[j] == "b" #bが入力された場合 typeb += km[j] * 80 typeb += 710 avekmb = avekmb.to_f + km[j].to_f b += 1 elsif taxi[j] == "c" #cが入力された場合 typec += km[j] * 90 typec += 710 avekmc =avekmc.to_f + km[j].to_f c += 1 end j += 1 end #ループ処理の終了 avekma = avekma/a #合計走行距離からaの平均走行距離を求める avekmb = avekmb/b #bの計算 avekmc = avekmc/c #cの計算 printf("本日の小型タクシーの総売上は%d円です。\n" ,typea) #売り上げを表示 printf("小型の平均走行距離は%5.2f[km]でした。\n\n",avekma) #平均を表示 printf("本日の中型タクシーの総売上は%d円です。\n" ,typeb) #\n\nは1行あけて printf("中型の平均走行距離は%5.2f[km]でした。\n\n",avekmb) #見やすくするため printf("本日の大型タクシーの総売上は%d円です。\n" ,typec) printf("大型の平均走行距離は%5.2f[km]でした。\n\n",avekmc) STDERR.print("小型:a 中型:b 大型: c\n") STDERR.print("乗車したタクシーを教えて下さい→") #どのタクシーに乗ったか car=gets.chomp #確認 STDERR.print("乗車した時間を教えて下さい→") #いつ乗ったのかを確認 hour = gets.chomp k = 0 while k < time.length if time[k] == hour #入力した時間とデータが一致した場合 long = km[k] #longにその時間の走行距離を代入する break #その場合は処理を終了する else #違う場合は k += 1 #ループして条件に合うものを探す end end #ループの終了 cat = (long+0.5).to_i #走行距離を四捨五入する if car == "a" #aの場合 p money = 650 + cat * 70 #金額の計算(確認のため p をつけている) elsif car == "b" p money = 710 + cat * 80 #bの場合 elsif car == "c" p money = 710 + cat * 90 #cの場合 end mileage = money/100 #マイレージの計算 open("reciept.txt" , "w") do |send| #reciept.txtに書きこむ send.printf("+-------------------+\n") #書きこむ内容 send.printf("出発時刻:%s\n金額:%s円\n" ,hour ,money) send.printf("取得マイレージ:%dマイル",mileage) send.printf("\n公益タクシー\n") send.printf("+-------------------+\n",) #←ここまで end print("発券終了\n") #標準出力で発券の終了を確認 実行結果 pan{c111080}% ./open_taxi.rb [~/Ruby] 本日の小型タクシーの総売上は3308円です。 小型の平均走行距離は 6.47[km]でした。 本日の中型タクシーの総売上は1852円です。 中型の平均走行距離は 2.70[km]でした。 本日の大型タクシーの総売上は1124円です。 大型の平均走行距離は 4.60[km]でした。 小型:a 中型:b 大型: c 乗車したタクシーを教えて下さい→a 乗車した時間を教えて下さい→10:10 720 発券終了 pan{c111080}% cat reciept.txt [~/Ruby] +-------------------+ 出発時刻:10:10 金額:720円 取得マイレージ:7 公益タクシー +-------------------+ 今回追加したオプション a , b , c , d 考察 まずは上記の実行結果の計算が正しいかの確認をする。 確認にはktermでbc -l を実行する。 aの総売り上げは、 ・お客を3回乗車させた ・それぞれ1.4 , 3.7 , 14.3km走った ・運賃は1kmごとに70円増えていく このことから、 1.4*70 98.0 3.7*70 259.0 14.3*70 1001.0 650*3 1950 1950+98+259+1001 3308 となり、総売り上げは3308円となる。 bとcも同様に計算し、 bの場合 2.5*80 200.0 2.9*80 232.0 710*2 1420 200+232+1420 1852 よって1852円。 cの場合 4.6*90 414.0 710*1 710 414+710 1124 となり、1124円。 以上のことから総売り上げの計算が正しいことが分かる。 次に平均走行距離の計算だが、 この場合は 走行した距離/走行した回数を計算すれば良いのではないかと考えた。 そうして、 aの場合は 1.4+3.7+14.3 19.4 19.4/3 6.46666666666666666666 よって平均は6.466.... プログラム上は小数点第2位までで四捨五入させているので、6.47kmになる。 bでは 2.5+2.9 5.4 5.4/2 2.70000000000000000000 同じように小数点第2位までで四捨五入し2.70km cの場合も 4.6/1 4.60000000000000000000 同様に四捨五入し4.60kmとなる。 このことから、平均走行距離も正しく計算されていることが確認できた。 次に、レシートに表示させる金額の確認をする。 今回はオプションのcも適用させているので四捨五入を行った結果が表示される。 その結果、 小型タクシーがお客を10:10に乗車させた際に走行した距離は1.4kmなので、 pan{c111080}% bc -l [~/Ruby] 1.4+0.5 1.9 650+1*70 720 quit 他の場合でも検証する。 小型:a 中型:b 大型: c 乗車したタクシーを教えて下さい→b 乗車した時間を教えて下さい→12:10 950 発券終了 上記のような条件でレシートを発券した場合は ・走行距離は2.5km ・初乗り料金は710円 ・1kmごとに80円ずつ増えていく よって pan{c111080}% bc -l [~/Ruby] 2.5+0.5 3.0 710+3*80 950 レシートに印刷されたのも pan{c111080}% cat reciept.txt [~/Ruby] +-------------------+ 出発時刻:12:10 金額:950円 取得マイレージ:9マイル 公益タクシー +-------------------+ このことから走行距離と金額の計算が正しいことが分かった。 参考文献 第7回 レポート課題 : http://roy/~madoka/2012/r1/07/rpt/rpt.html 第7回 「走行距離を求めるには」 : http://roy/~madoka/2012/r1/07/r1_07_15_theme_12_distance.html 第7回 「券売機の仕組み」 : http://roy/~madoka/2012/r1/07/r1_07_14_theme_11_vendingmachine.html 第7回 「自動印刷を行うには」 : http://roy/~madoka/2012/r1/07/r1_07_16_theme_13_filewrite.html 第7回 プログラム作成のコツ : http://roy/~madoka/2012/rpt/rpt_proc.html C.感想 今回のレポート課題はとにかく時間が無かったが、ひとまず作成することが出来 たので良かった。しかし、A問題と、B問題のeが解けなかったのは悔やまれる。 A問題は a , c が出来るようにはなっているはずだが、bを実行しようとしても 反応しなかったのが疑問に残った。おそらくプログラムに足りない部分があるか、 検索の正規表現に問題があるのだろう。これは後々調べてみようと思う。 B問題のeは深夜料金という設定だが、プログラム上、時間の部分を文字列として 読み込んでしまったために上手く実行することが出来無かったのではないかと思 われる。 これには前回の課題に対しての先生からの一言を応用すれば実行できる かと思うが、作成することは出来なかった。 くやしいので時間があれば追加してみようと思う。 また、今回一番頑張ったこととしてB問題のレシートの出力関連が挙げられる。 レシートの出力自体はそれほどまで難しいものではなかったが、そこまでの金額 の計算と走行距離の求め方などが思うようにいかなかった。 最終的にはA問題を解くはずだった時間を割いてまで解くことになってしまった が、今回の経験から次回以降似たような問題があればすぐに取り掛かることが出 来ると思う。 D.共同学習者名 渡辺十夢 及川慎司 小野貴己 稲村洋樹 齋藤允貴 伊藤貴章