2.B.の問題のできたところまでを書き足したので、メール再送信します。 ---------- 第 7 回 正規表現と Ruby 言語でのプログラミング レポート課題 氏名:高橋岬 学籍番号:c1110973 語学クラス:英語5 コース:環境サイエンスコース 1.A.a.0b11010110 = 0x?? 2進数4桁は最大15を表せ、これは16進数の1桁分と同じである。 なので2進数を下から4つずつになるように区切り、10進数に変換し、それ を並べ16進数として扱う。 1 1 0 1 0 1 1 0 * * * * * * * * 2^3 2^2 2^1 2^0 2^3 2^2 2^1 2^0 0b1101 = 8+4 +1 = 13 0b0110 = 4+2 = 6 13 = d なので答えは 0b11010110 = 0xd6 b.0d1024 = 0x?? 10進数を16進数変換するには、商が0になるまで16で割り、余りを下から 読む。 1024 / 16 = 64 余り 0 64 / 16 = 4 余り 0 4 / 16 = 0 余り 4 よって答えは 0d1024 =0x400 B.自分の名前:Misaki TAKAHASHI この名前に使われている文字をASDIIコード表を参考にして変換する。 M = 0x4d i = 0x69 s = 0x73 a = 0x61 k = 0x6d T = 0x54 A = 0x41 K = 0x4b H = 0x48 S = 0x53 I = 0x49 よって答えは Misaki TAKAHASHI = 0x4d0x690x730x610x6d 0x540x410x4b0x410x480x410x530x480x49 参考文献 基礎プログラミング I 第 5 回 (配列の構造) 「ASCII コード表」 http://roy/~madoka/2012/r1/05/r1_05_01_theme_01_asciicode.html 2.A.使用するデータ 山形市 Yamagata-shi 254487 ナナカマド ベニバナ 寒河江市 Sagae-shi 42085 サクランボ ツツジ 上山市 Kaminoyama-shi 33408 アララギ キク 村山市 Murayama-shi 26413 アカマツ バラ 天童市 Tendo-shi 62138 モミジ ツツジ 東根市 Higashine-shi 46827 ケヤキ サクランボ 尾花沢市 Obanazawa-shi 18536 ケヤキ ツツジ 山辺町 Yamanobe-machi 15095 キャラボク リンドウ 中山町 Nakayama-machi 11894 イチョウ ヒマワリ 河北町 Kahoku-machi 19760 該当なし ベニバナ 西川町 Nishikawa-machi 6107 ブナ ミズバショウ 朝日町 Asahi-machi 7731 ブナ ヒメサユリ 大江町 Oe-machi 9088 スギ アジサイ 大石田町 Oishida-machi 8012 カツラ サクラ 新庄市 Shinjo-shi 38462 モミ アジサイ 金山町 Kaneyama-machi 6259 カネヤマスギ 該当なし 最上町 Mogami-machi 9665 ウメ リンドウ 舟形町 Funagata-machi 6032 エンジュ コブシ 真室川町 Mamurogawa-machi 8983 ウメノキ ウメノハナ 大蔵村 Okura-mura 3707 ブナ リンドウ 鮭川村 Sakegawa-mura 4766 モミジ ミチノクヒメユリ 戸沢村 Tozawa-mura 5170 ヤマノウチスギ ヒメサユリ 米沢市 Yonezawa-shi 89009 コメヅカ アズマシャクナゲ 南陽市 Nannyo-shi 33404 サクラ キク 長井市 Nagai-shi 29297 ツツジ アヤメ 高畠町 Takahata-machi 24805 アカマツ ツツジ 川西町 Kawanishi-machi 17060 マツ ダリヤ 小国町 Oguni-machi 8691 ブナ オオヤマザクラ 白鷹町 Shirataka-machi 15112 エドヒガンザクラ コブシノハナ 飯豊町 Ide-machi 7791 モミジ ユリ 酒田市 Sakata-shi 110253 ケヤキ トビシマカンゾウ 鶴岡市 Tsuruoka-shi 135374 ブナ サクラ 三川町 Mikawa-machi 7740 ケヤキ ナノハナ 庄内町 Shonai-machi 22925 該当なし 該当なし 遊佐町 Yuza-machi 15208 クロマツ チョウカイフスマ 前回作成したこのデータから、市町村名と人口を抜き出して使用する。 作成したプログラム #!/usr/koeki/bin/ruby #codin: euc-jp print("山形県の市町村の人口データを取扱います。\n") # kterm に表 示させる言葉(このプログラムの説明) STDERR.print("検索したいワードを入力して下さい。: ") # 入力させ たい文字への導入 pat = STDIN.gets.chomp # STDIN 照準入力 rep = Regexp.new(pat, true) # 正規表現 # true: # pat を大文字小文字、日本語 euc-jp を探す name = Array.new # どこの市町村か cand = Array.new # 人口何人か i = 0 # しまう変数 open("data_c111097.dat", "r") do |seek| # data_c111097.dat とい うファイルを開き、以後は seek として扱う while data_c111097 = seek.gets # data_c111097.dat からデータ を受けいれる if rep =~ data_c111097 # data_c111097.datから探す if /(\S+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\S+)/ =~ data_c111097 # data_c111097.dat から探したデータを [ ] にしまう name[i] = $1 # [ ] の1番目にある cand[i] = $3.to_i # [ ] の3番目にあり、整数値として扱う i += 1 # 1ずつ増えていく end end end end j = 0 # [ ]内で何個目か(0から数える) total = 0 # 総人口 while j < cand.length # cand[ ]内の総数回目でストップする total += cand[j] # 人口を足していく printf("候補 %d:\t%s %7.0f 人\n", j+1, name[j], cand[j]) # 検 索で引っかかった候補◯/市町村名/人口 j += 1 # 1ずつ増えていく end while true # 計算が終わるまで計算し続ける STDERR.print("操作を選択して下さい。 1.選択 2.平均 3.最大 4.最小: ") # 入力させたい文字への導入 m = gets.to_i # 入力された文字を受け付ける printf(" %d を選択しました。\n", m) # 何を選択したのか表示する if m == 1 # 1(選択)を選んだら STDERR.print("候補から選択して下さい。: ") # さらに表示させ たい候補を入力させる l = gets.to_i # 入力された文字を受け付ける printf("%s は人口 %5.0f 人です。\n", name[l-1], cand[l-1]) # 市町村の人口が何人か(候補は 1,2,3,,, で[ ]は 0,1,2,,, となってい るので l-1 をする。) break # 計算終了 elsif m == 2 # 2(平均)を選んだら printf("平均人口は %5.1f 人です。\n", total.to_f / j) # 表示 された人口の総人口( .to_f は小数値として扱う) ÷ 候補数 break # 計算終了 elsif m == 3 # 3(最大)を選んだら printf("候補の中の最大人口は %d 人です。\n", cand.sort.reverse.shift) # 候補のなかで最大値を表示させる( .sort で小さい順から並べ替え .reverse で並びを逆にし .shift で先 頭を抜き出す) break # 計算終了 elsif m == 4 # 4(最小)を選んだら printf("候補の中の最小人口は %d 人です。\n", cand.sort.shift) # 候補の中で最小値を表示させる( .sort で小さい順から並べ替え .reverse で並びを逆にし .shift で先頭を抜き出す) break # 計算終了 end end 実行したプログラム a.pan{c111097}% ./regexp_c111097.rb 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: 川 候補 1: 西川町 6107 人 候補 2: 真室川町 8983 人 候補 3: 鮭川村 4766 人 候補 4: 川西町 17060 人 候補 5: 三川町 7740 人 操作を選択して下さい。 1.選択 2.平均 3.最大 4.最小: 2 2 を選択しました。 平均人口は 8931.2 人です。 b.pan{c111097}% ./regexp_c111097.rb 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: machi 候補 1: 山辺町 15095 人 候補 2: 中山町 11894 人 候補 3: 河北町 19760 人 候補 4: 西川町 6107 人 候補 5: 朝日町 7731 人 候補 6: 大江町 9088 人 候補 7: 大石田町 8012 人 候補 8: 金山町 6259 人 候補 9: 最上町 9665 人 候補 10: 舟形町 6032 人 候補 11: 真室川町 8983 人 候補 12: 高畠町 24805 人 候補 13: 川西町 17060 人 候補 14: 小国町 8691 人 候補 15: 白鷹町 15112 人 候補 16: 飯豊町 7791 人 候補 17: 三川町 7740 人 候補 18: 庄内町 22925 人 候補 19: 遊佐町 15208 人 操作を選択して下さい。 1.選択 2.平均 3.最大 4.最小: 3 3 を選択しました。 候補の中の最大人口は 24805 人です。 c.pan{c111097}% ./regexp_c111097.rb 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: \s\d\d\d\d\d\d\s 候補 1: 山形市 254487 人 候補 2: 酒田市 110253 人 候補 3: 鶴岡市 135374 人 操作を選択して下さい。 1.選択 2.平均 3.最大 4.最小: 4 4 を選択しました。 候補の中の最小人口は 110253 人です。 d.pan{c111097}% ./regexp_c111097.rb 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: shi\s 候補 1: 山形市 254487 人 候補 2: 寒河江市 42085 人 候補 3: 上山市 33408 人 候補 4: 村山市 26413 人 候補 5: 天童市 62138 人 候補 6: 東根市 46827 人 候補 7: 尾花沢市 18536 人 候補 8: 新庄市 38462 人 候補 9: 米沢市 89009 人 候補 10: 南陽市 33404 人 候補 11: 長井市 29297 人 候補 12: 酒田市 110253 人 候補 13: 鶴岡市 135374 人 操作を選択して下さい。 1.選択 2.平均 3.最大 4.最小: 1 1 を選択しました。 候補から選択して下さい。: 8 新庄市 は人口 38462 人です。 考察 a."川"が名前に入っている市町村が検出された。 ( 6107 + 8983 + 4766 + 17060 + 7740 ) / 5 = 8931.20000000000000000000 検出された市町村の人口を全て足して検出された市町村の数で割ったとこ ろ、起動したプログラムと同じ結果が得られた。 b.ローマ字表記が"machi"となっているところ、つまり"町"が検出された。 検出された町の人口の最大値は高畠町の24805人。 c."\s\d\d\d\d\d\d\s"は \s は空白、 \d は数値よって、10万以上100万未 満の数値を検出する。 検出された市町村の人口の最小値は酒田市の110253人。 d."shi\s"の \s は c. と同様空白を示すので、 shi の後ろに空白が来る" 市"が検出された。 選択された 候補8 の新庄市は人口38462人。 上記の4つの結果より、このプログラムは正常に起動している。 その他 今回実行する際に、ktermで Ruby を開かずに [~] の状態のまま実行すると このようになった。 pan{c111097}% Ruby/regexp_c111097.rb [~] 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: 川 Ruby/regexp_c111097.rb:18:in `initialize': No such file or directory - data_c111097.dat (Errno::ENOENT) from Ruby/regexp_c111097.rb:18:in `open' from Ruby/regexp_c111097.rb:18:in `
' これはこのプログラムが Ruby 内にあり、 プログラムを実行する際に引用 するデータも Ruby 内にあるためだと考えられた。 なので open("data_c111097.dat", "r") do |seek| この引用するデータ名のところを open("Ruby/data_c111097.dat", "r") do |seek| とすると、正しく起動した。 pan{c111097}% Ruby/regexp_c111097.rb [~] 山形県の市町村の人口データを取扱います。 検索したいワードを入力して下さい。: 川 候補 1: 西川町 6107 人 候補 2: 真室川町 8983 人 候補 3: 鮭川村 4766 人 候補 4: 川西町 17060 人 候補 5: 三川町 7740 人 ※以下略 逆に、 Ruby を開いて、引用するデータ名を変えたプログラムを実行すると、 最初失敗したときのようにエラーメッセージが出た。 今後この作業を必要とするかもしれないので、覚えておきたい。 参考プログラム 基礎プログラミング I 第 7 回 「正規表現と Ruby 言語でのプログラミ ング」で作成したプログラム Ruby/regexp_stdin.rb B.作成したデータ 00:30 c 5.3 02:10 b 7.9 03:50 a 6.1 06:30 b 3.9 07:50 a 5.4 08:40 b 4.2 10:10 a 1.4 12:10 b 2.5 13:20 c 4.6 15:40 a 14.3 16:10 b 2.9 18:20 b 8.1 19:30 a 9.0 20:50 c 10.2 22:20 c 0.8 23:40 a 3.7 レポート課題のデータ例を元に情報を付け加えたデータを作成した。 作成したプログラム #!/usr/koeki/bin/ruby #codin: euc-jp print("公益タクシー\n") print("配車したタクシーごとに売上げと走行距離を表示します。\n") # kterm に表示させる言葉(このプログラムの説明) STDERR.print("タイプを入力して下さい。( a, b, c ): " # 入力させ たい文字への導入 pat = STDIN.gets.chomp # STDIN 照準入力 rep = Regexp.new(pat, true) # 正規表現 # true: # pat を大文字小文字、日本語 euc-jp を探す time = Array.new # 何時に配車されたのか type = Array.new # タイプ何か km = Array.new # 何km走ったのか i = 0 # しまう変数 money = 0 # 料金 total = 0 # 総売上げ all = 0 # 総走行距離 open("data_taxi.dat", "r") do |taxi| # data_taxi.dat というファ イルを開き(r)、以後は taxi として扱う while data_taxi = taxi.gets # data_taxi.dat からデータを受けい れる # p data_taxi if rep =~ data_taxi # data_taxi.dat から探す if /(\S+)\s+(\S+)\s+(\d+.\d+)/ =~ data_taxi # data_taxi.dat から探したデータを [ ] にしまう time[i] = $1 # [ ] の1番目にある type[i] = $2 # [ ] の2番目にある km[i] = $3.to_f # [ ] の3番目にあり、小数値として扱う all += km[i] # 走行距離を足していく if type[i] == "a" # タイプ a なら料金計算は以下のように なる money = 70 * km[i] + 650 # 初乗り650円 70円/km elsif type[i] == "b" # タイプ b なら料金計算は以下のよう になる money = 80 * km[i] + 710 # 初乗り710円 80円/km elsif type[i] == "c" # タイプ c なら料金計算は以下のよう になる money = 90 * km[i] + 710 # 初乗り710円 90円/km end i += 1 # 1ずつ増えていく fee = money % 10 # 料金は四捨五入しなければならないので % 10 で計算し、余りを出させる if fee >= 5 # 余りが 5以上 だったら price = money / 10 +1 # / 10 で計算したものに 1 足す elsif fee < 5 # 余りが 5未満 だったら price = money / 10 # / 10 で計算する end total += pricee.to_i * 10 # 四捨五入した料金を10倍にして 足す( .to_i は整数値として扱う) end end end end k = 0 # [ ]内で何個目か(0から数える) printf(" %s の配車時間と走行距離\n", type[k]) # kterm に表示させ る言葉(何を選択したのか) while k < type.length # type[ ]内の総数回目でストップする printf("%s: %s\t %3.1f\n", k+1, time[k], km[k]) # kterm に表 示させる言葉(検索された候補●/配車時間/走行距離) k += 1 # 1ずつ増えていく end while true # 計算が終わるまで計算し続ける print("どの操作を実行しますか?\n") # kterm に表示させる言葉 STDERR.print("1.平均走行距離&売上げ表示 2.レシート発行: ") # 入力させたい文字への導入 m = gets.to_i # 入力された文字を受け付ける if m == 1 # 1(走行距離&売上げ)を選んだら printf(" 平均走行距離:\t%3.1f km\n", all/k) # kterm に表示さ せる言葉(平均走行距離) printf(" 売上げ:\t%d 円\n", total) # kterm に 表示させる言葉(売上げ) break # 計算終了 elsif m == 2 # 2(レシート発行)を選んだら STDERR.print("レシートを発行したい番号を入力して下さい。: ") # 入力させたい文字への導入 l = gets.to_i # 入力された文字を受け付ける if type[i] == "a" # タイプ a なら料金計算は以下のようにな る money = 70 * km[i] + 650 # 初乗り650円 70円/km elsif type[i] == "b" # タイプ b なら料金計算は以下のように なる money = 80 * km[i] + 710 # 初乗り710円 80円/km elsif type[i] == "c" # タイプ c なら料金計算は以下のように なる money = 90 * km[i] + 710 # 初乗り710円 90円/km end i += 1 # 1ずつ増えていく fee = money % 10 # 料金は四捨五入しなければならないので % 10 で計算し、余りを出させる if fee >= 5 # 余りが 5以上 だったら price = money / 10 +1 # / 10 で計算したものに 1 足す elsif fee < 5 # 余りが 5未満 だったら price = money / 10 # / 10 で計算する end open("reciept.txt", "w") do |reciept| # reciept.txt というファ イルに書きこみ(w)、以後は reciept として扱う reciept.print("ご利用ありがとうございます、公益タクシーです。 \n") # reciept.txt に書きこむ言葉 reciept.printf(" 乗車時刻 %s 会計 %d 円\n", time[l-1], price.to_i*10) # reciept.txt に書きこむ言葉(乗車時間/料金( .to_i は整数値として扱う)) reciept.printf(" 取得マイレージ %d マイル\n", price/10) # reciept.txt に書きこむ言葉(取得マイレージ) end printf(" 乗車時刻 %s 会計 %d 円\n", time[l-1],price.to_i*10) # kterm に表示させる言葉(乗車時間/料金( .to_i は整数値として扱う)) printf(" 取得マイレージ %d マイル\n", price/10) # kterm に表示させる言葉(取得マイレージ) break # 計算終了 end end 実行したプログラム a.pan{c111097}% ./open_taxi.rb 公益タクシー 配車したタクシーごとに売上げと走行距離を表示します。 タイプを入力して下さい。( a, b, c ): a a の配車時間と走行距離 1: 03:50 6.1 2: 07:50 5.4 3: 10:10 1.4 4: 15:40 14.3 5: 19:30 9.0 6: 23:40 3.7 どの操作を実行しますか? 1.平均走行距離&売上げ表示 2.レシート発行: 1 平均走行距離: 6.7 km 売上げ: 6700 円 b.pan{c111097}% ./open_taxi.rb 公益タクシー 配車したタクシーごとに売上げと走行距離を表示します。 タイプを入力して下さい。( a, b, c ): b b の配車時間と走行距離 1: 02:10 7.9 2: 06:30 3.9 3: 08:40 4.2 4: 12:10 2.5 5: 16:10 2.9 6: 18:20 8.1 どの操作を実行しますか? 1.平均走行距離&売上げ表示 2.レシート発行: 2 レシートを発行したい番号を入力して下さい。: 4 乗車時刻 16:10 会計 940 円 取得マイレージ 9 マイル c.pan{c111097}% ./open_taxi.rb 公益タクシー 配車したタクシーごとに売上げと走行距離を表示します。 タイプを入力して下さい。( a, b, c ): c c の配車時間と走行距離 1: 00:30 5.3 2: 13:20 4.6 3: 20:50 10.2 4: 22:20 0.8 どの操作を実行しますか? 1.平均走行距離&売上げ表示 2.レシート発行: 2 レシートを発行したい番号を入力して下さい。: 3 乗車時刻 20:50 会計 1630 円 取得マイレージ 16 マイル 考察 a.タイプ a は検出された6つのみであるので、検索は問題ない。 平均走行距離、売上げはそれぞれ 平均走行距離 (6.1+5.4+1.4+14.3+9.0+3.7)/6 6.65000000000000000000 売上げ 6.1*70+650 1077.0 = 1080 5.4*70+650 1028.0 = 1030 1.4*70+650 748.0 = 750 14.3*70+650 1651.0 = 1650 9.0*70+650 1280.0 = 1280 3.7*70+650 909.0 = 910 1080+1030+750+1650+1280+910 6700 となり、起動したプログラムと同じ結果が得られた。 b.タイプ b は検出された6つのみであるので、検索は問題ない。 料金は 2.9*80+710 942.0 となり、 2 が四捨五入されるので 940円 となる。 マイレージは 9マイル である。 また、 reciept.txt に書きこまれた数値は以下のようになった。 ご利用ありがとうございます、公益タクシーです。 乗車時刻 16:10 会計 940 円 取得マイレージ 9 マイル よって、起動したプログラムと同じ結果が得られた。 c.タイプ c は検出された4つのみであるので、検索は問題ない。 料金は 10.2*90+710 1628.0 となり、 8 が四捨五入されるので 1630円 となる。 マイレージは 16マイル である。 また、 reciept.txt に書きこまれた数値は以下のようになった。 ご利用ありがとうございます、公益タクシーです。 乗車時刻 20:50 会計 1630 円 取得マイレージ 16 マイル よって、起動したプログラムと同じ結果が得られた。 上記の4つの結果より、このプログラムは正常に起動している。 参考文献 広瀬雄二, Rubyプログラミング基礎講座, 技術評論社, 2006 p.88 第7講ファイル入出力 7-1ファイルの入出力 ファイルへの書き出し 3.感想 今回の 2.A. の問題はすんなりと作り終えることができた。 以前作った買物するとポイントが貯まるプログラムは切り捨てだったが、 2.B. では、四捨五入させるプログラムだったので、苦戦した。 % で余りを出して、それを5以上か5未満か判断させるというのは、なかなか 良かったと思う。 深夜料金(料金2倍)のプログラムを作ることが出来なかったのは、とても悔し い。 でもそれ以外のところはできたので、良としたい。 ----------------------------- 高橋 岬 東北公益文科大学 2年 c111097@g.koeki-u.ac.jp -----------------------------