第5回 何度も呼び出そう レポート課題 氏名 : 余語結佳 学籍番号 : c1101974 語学クラス : 英語2 コース : 地域共創コース ---------------------------------------------------------------------- 1. 筆記問題 ---------------------------------------------------------------------- **************************** A ***************************** 名前 ASCIIコード 変換 (16進数) (10進数) ---------------------------- Y 0x 59 89 O 0x 4f 79 G 0x 47 71 O 0x 4f 79 Y 0x 59 89 U 0x 55 85 K 0x 4b 75 A 0x 41 65 これを使う。 ●16進数の足算 手順 1 : 16進数を1桁ずつに区切って、それぞれを2進数に直す。 Y 0x 59 → 5 = 0101 → 9 = 1001 = 0b 0101 1001 O 0x 4f → 4 = 0100 → f = 1111 = 0b 0100 1111 G 0x 47 → 4 = 0100 → 7 = 0111 = 0b 0100 0111 O 0x 4f → 4 = 0100 → f = 1111 = 0b 0100 1111 Y 0x 59 → 5 = 0101 → 9 = 1001 = 0b 0101 1001 U 0x 55 → 5 = 0101 → 5 = 0101 = 0b 0101 0101 K 0x 4b → 4 = 0100 → b = 1011 = 0b 0100 1011 A 0x 41 → 4 = 0100 → 1 = 0001 = 0b 0100 0001 Y + O = 0101 1001 + 0100 1111 ------------- 1010 1000 G + O = 0100 0111 + 0100 1111 ------------- 1001 0110 Y + U = 0101 1001 + 0101 0101 ------------- 1010 1110 K + A = 0100 1011 + 0100 0001 ------------- 1000 1100 ( Y + O ) + ( G + O ) = 1010 1000 + 1001 0110 ------------- 1 0011 1110 ( Y + U ) + ( K + A ) = 1010 1110 + 1000 1100 ------------- 1 0011 1010 ( Y + O + G + O ) + ( Y + U + K + A ) = 1 0011 1110 + 1 0011 1010 --------------- 10 0111 1000 それぞれを16進数に変換すると 0010 → 2 0111 → 7 1000 → 8 なので、変換結果は 0x278 ●10進数の足算 10進数はいつもわたしたち人間が日常的に使用している数字なのでそのまま足し 算をして良い 89 + 79 + 71 + 79 + 89 + 85 + 75 + 65 = 0x632 これを16進数に直すと 16) 632 8 ------ 16) 39 7 ------ 16) 2 2 ------ 0 下から読んでいくと 0x 0278 で、 0は消すので16進数に変換した答えは 0x 278 である。 16進数を足し算した数と10進数を足した数は 0x278 で等しいので、一致するこ とが確認できた。 ***************************** B **************************** 設定 本屋さんのアルバイトで何度も繰り返す作業をプログラム風に書き出しました。 文庫本を売るときと、文具を売るときの作業を書いています。 def book (bunko,cover,band) bunko をお客様から預かる cover を出す service = book に covert をつける service = seivice に band をかける end def bungu (pen,eraser,hukuro) pen をお客様から預かる eraser を追加で預かる hikiwatasi = pen と eraser をレジに通す hikiwatasi = hikiwatasi を袋にいれる end book(2冊,2枚,1本) # 文庫本を売るので呼び出す bungu(3本,2個,1袋) # 文具を売るので呼び出す print"お買い上げありがとうございました!!\n" ---------------------------------------------------------------------- 2.プログラム問題 ---------------------------------------------------------------------- ********************************************************************** 作成したプログラム : A の def_combination.rb ****************************** 考えた設定 **************************** 袋の中に何個かボールがあって、その中からいくつかボールをとったときの組み 合わせが何通りあるかを計算する設定でプログラムを組みました。 *************************** 作成したプログラム *********************** #!/usr/koeki/bin/ruby # 階乗(順列)のためのメソッド def factorial(ball) # ballには指定された数がはいる if ball <= 1 # もしballが 1 以下の時 1 # 1 を返す else # それ以外の時 ball * factorial(ball-1) # くわしい説明は一番下で↓ end # if-end end # def-end # 組み合わせ計算のためのメソッド def kumiawase(inball,out) # inball = hukuro,out = outball factorial(inball) / (factorial(out) * factorial(inball - out)) # 組合せの公式 nCr = n!/r!(n-r)!の公式に当てはめている。 # factorialメソッドは階乗のためのメソッドなので、階乗(順列)が必要なこのdef kumiawase の中でも呼び出している end # def-end print"袋の中にはいっているボールを?個取り出した時の組み合わせは何通りあるか計算します。\n" print"袋の中にあるボールは何個ですか?\n" hukuro = gets.to_i # 袋の中のボールの数代入 #printf("袋の中の順列 %d \n",factorial(hukuro)) # 順列の値が正しいか確認。確認のため最終的には消している。 print"ボールは何個取り出しますか?\n" outball = gets.to_i # 取り出すボールの数代入 #printf("ボールの順列 %d \n",factorial(outball)) # 順列の値が正しいか確認。確認のため最終的には消している。 # 袋の中にあるボールが、組み合わせの nCr の n にあたる # 何個取り出すか、というのが組み合わせの nCr の r にあたる # 変数を当てはめると、hukuro C outball ということ。 printf("組み合わせは %d 通りあります。\n",kumiawase(hukuro,outball)) # kumiawase(hukuro,outball)でkumiawaseメソッドを呼んでいる # ball * factorial(ball-1)の説明 (仮に5が代入されたとして考える) # factorial(5)が呼び出される # ball * factorial(ball-1)のballに5が代入される # factorial(5-1) = factorial(4)だからfactorial(4)が呼ばれる # factorial(4-1) = factorial(3)だからfactorial(3)が呼ばれる # factorial(3-1) = factorial(2)だからfactorial(2)が呼ばれる # factorial(2-1) = factorial(1)だからfactorial(1)が呼ばれる #A. factorial(1) = 1 は if ball <= 1 に当てはまるので1が返される # これで factorial(1) = 1 が定義付けられた。 # 代入された値は5なので、1から順に5までを計算する。 # B #factorial(2) = 2 * factorial(2-1) # ↓ # factorial(1) #factorial(1) = 1と Aで定義付けられたので引算結果のfactorial(1)には1が入る # 2 * 1 = 2 なので factorial(2) = 2 が定義付けられた。 # C #factorial(3) = 3 * factorial(3-1) # ↓ # factorial(2) #factorial(2) = 2と Bで定義付けられたので引算結果のfactorial(2)には2が入る # 3 * 2 = 6 なので factorial(3) = 6 が定義付けられた。 # D #factorial(4) = 4 * factorial(4-1) # ↓ # factorial(3) #factorial(3) = 6と Cで定義付けられたので引算結果のfactorial(3)には6が入る # 4 * 6 = 24 なので factorial(4) = 24 が定義付けられた。 # E #factorial(5) = 5 * factorial(5-1) # ↓ # factorial(4) #factorial(4) = 24と Dで定義付けられたので引算結果のfactorial(4)には24が入る # 5 * 24 = 120 なので factorial(5) = 120 が定義付けられた。 #結果、このプログラムでは袋の中のボール数を5つとした場合、袋の中の順列は120通りになっている。 #(ちなみに順列を出力していた文は上ではコメント扱いになっている) *********************** 元にしたプログラム ************************* 元にしたプログラムは def_factorial.rb です。 主に一つ目のdef factrial を考える際に参考にしました。 変数の名前を それぞれ変えています。 ******************************* 実行結果 ***************************** ●袋の中のボールは5個、取り出すボールは3個の時 pan{c110197}% ./def_combination.rb [~/Ruby] 袋の中にはいっているボールを?個取り出した時の組み合わせは何通りあるか計算します。 袋の中にあるボールは何個ですか? 5 ボールは何個取り出しますか? 3 組み合わせは 10 通りあります。 ●確認 公式に当てはめて計算すると以下のようになる。 5 * 4 * 3 * 2 * 1 5 C 3 = ---------------------- 3 * 2 * 1 * ( 5 - 3 )! pan{c110197}% bc -l [~/Ruby] 5 * 4 * 3 * 2 * 1 120 3 * 2 * 1 6 5-3 2 2*1 2 120 = ---------------- 6 * ( 2 * 1 ) 120 120 = --------- = ------ = 10 10通り 6 * 2 12 以上から正しいと言える。 ●袋の中のボールは10個、取り出すボールは5個の時 pan{c110197}% ./def_combination.rb [~/Ruby] 袋の中にはいっているボールを?個取り出した時の組み合わせは何通りあるか計算します。 袋の中にあるボールは何個ですか? 10 ボールは何個取り出しますか? 5 組み合わせは 252 通りあります。 ●確認 公式に当てはめて計算すると以下のようになる。 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 10 C 5 = ----------------------------------------- 5 * 4 * 3 * 2 * 1 * ( 10 - 5 )! pan{c110197}% bc -l [~/Ruby] 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 3628800 5 * 4 * 3 * 2 * 1 120 10 - 5 5 pan{c110197}% bc -l [~/Ruby] 3628800/14400 252.00000000000000000000 3628800 = ---------------------------- 120 * ( 5 * 4 * 3 * 2 * 1 ) 3628800 3628800 = ----------- = --------- = 252 252通り 120 * 120 14400 以上から正しいと言える。 ******************************** 考察 ******************************** ●組み合わせと順列 順番が違っていても、内容が同じなら別物ではないものを言います。 ちなみに、内容が同じでも順番が違えば別物になるのは「順列」です。 組み合わせの前に順列について説明します。 ◯順列 順列とは、上で書いたように順番が違えば内容が同じでも違うものになるものを 言います。 (例) Aさん、Bさん、Cさんがいて、3人はキャンプをしていて、ご飯を作ります。 1番目の役割は作るものを決める係です。 2番目の役割はたき火をする係です。 3番目の役割は材料を好きな形に切る係です。 Aさんが1番目になったらAさんはカレーを作るつもりです。 Bさんが1番目になったらBさんはサンドウィッチを作るつもりです。 Cさんが1番目になったらCさんはラーメンを作るつもりです。 Aさんが3番目になったらAさんは材料を星の形に切ります。 Bさんが3番目になったらBさんは材料を適当な形に切ります。 Cさんが3番目になったらCさんは材料を正方形に切ります。 そうなると、 1番 2番 3番 ---------------------------- A B C →できるものはカレーで材料は正方形 ---------------------------- B C A →できるものはサンドウィッチで材料は星型 ---------------------------- C A B →できるものはラーメンで材料は適当な形 ・ ・ ・ のように、内容は同じでも違うものだということがわかります。 これが、順列ということです。 順列の例はここまでにして、具体的な計算方法は以下のようになります。 全体が n個 ある 中から r個だけとった場合の値 nPr (例) 4個から3個撮った場合 4 P 3 = 4 * 3 * 2 答え.24通り のようになります。 ◯組み合わせ 順列のキャンプの例では、内容が同じでも順番が違えば違うものになると言うも のになりました。 組み合わせはそれとは違って、順番が違っていても内容が同じであれば別物には ならないというものです。 (例) Aさん、Bさん、Cさんたちのクラスでは先生が3人グループを作れと言ったので、 Aさん、Bさん、Cさんはいつものようにこの3人でグループを作りました。 その場合、一番最初にAさんが「グループ組もう」と言っても、Bさんが言っても、 Cさんが言ってもこの3人の組み合わせは違うものにはなりません。 これが組み合わせの考え方になります。 組み合わせの例はここまでにして、具体的な計算方法は以下のようになります。 組み合わせの計算方法では先程考えた順列も使います。 n! nCr = -------------- r!(n-r)! この公式で計算できます。 プログラムの中でも実際この公式を使って計算しています。 ●プログラムを作る中で、最初は n! nCr = -------------- r!(n-r)! の公式ではなく nPr nCr = -------- r! の公式を使っていて、2つ目のdefでもう一度 n * factorial (n-1)をして繰り返 しをして、nPrの計算(n (n-1)(n-2)…2,1)を実行して、繰り返しの回数(が代入 されている変数)と取り出すボールの数が一致したらbreakをするようにしようと 思ったのですが、factrialはプログラムの説明の中にもあるように、下から計算 をしていくのでそれは実現不可能なことがわかったので今の公式を使った形にしました。 ********************************************************************** 作成したプログラム : B の two_methods.rb ****************************** 考えた設定 **************************** クイズの配点プログラムを作成しました。 問題は全部で20問あります。 1問目から10問目までが問1になり、配点は各5点。 11問目から20問目までが問2になり、配点は各5点ですが5問以上正解するとボー ナス得点として5点プラスされるという設定になっています。 *********************** 作成したプログラムと説明 ********************* #!/usr/koeki/bin/ruby def toi1 (seikai1) # seikai1 = kazu1(問1の正解数を代入) seikai1 * 5 # 配点は各5点なので、正解数(seikai1)*5点をしている end # def toi1-end def toi2 (seikai2) # seikai2 = kazu2(問2の正解数を代入) if seikai2 >= 5 # 「もし正解数(左辺)が5つ(右辺)以上の場合」 tokuten = seikai2 * 5 # 配点は各5点なので、正解数(seikai2)*5点をしている tokuten + 5 # 正解数が5つ以上なのでボーナス得点として+5点している else # それ以外の場合(正解数が4点以下の場合) seikai2 * 5 # 配点は各5点なので、正解数(seikai2)*5点をしている # このif文では4点以下なので、ボーナス得点計算は不要 end # if-end end # def toi2-end print"このプログラムはクイズの配点プログラムです。\n" print"[問1] 1問目から10問目 まで。\n" print"[問2] 11問目から20問目 まで。\n" print" ※問2に関しては、5問以上正解でボーナス得点として+5点。\n\n" print" [問1] の正解数はいくつでしたか?(配点:各5点)\n" kazu1 = gets.to_i # [問1]の正解数を kazu1 に代入。 # 文字列では何問正解かわからないのでto_iで整数に変換 printf("[問1]の得点 \t %d 点\n",toi1(kazu1)) # toi1(kazu1)で def toi1 を呼び出す print" \n[問2] の正解数はいくつでしたか?(配点:各5点)\n" print" ※5問以上正解で+5点\n" kazu2 = gets.to_i # [問2]の正解数を kazu1 に代入。 # 文字列では何問正解かわからないのでto_iで整数に変換 printf("[問2]の得点 \t %d 点\n\n\n",toi2(kazu2)) # toi2(kazu2)で def toi2 を呼び出す printf("よって、このテストの合計点数は %d 点でした。\n",toi1(kazu1)+toi2(kazu2)) # toi1(kazu1) と toi2(kazu2)を呼び出して加算。 # 計算結果 = 合計点数になる。そしてその答えを出力。 *********************** 参考にしたプログラム ************************* def_metabolic.rbを参考にしました。 参考にしただけなので変更点はありません。 ******************************* 実行結果 ***************************** ★問2でボーナス得点がない場合(4問以下正解) pan{c110197}% ./two_methods.rb [~/Ruby] このプログラムはクイズの配点プログラムです。 [問1] 1問目から10問目 まで。 [問2] 11問目から20問目 まで。 ※問2に関しては、5問以上正解でボーナス得点として+5点。 [問1] の正解数はいくつでしたか?(配点:各5点) 10 [問1]の得点 50 点 [問2] の正解数はいくつでしたか?(配点:各5点) ※5問以上正解で+5点 4 [問2]の得点 20 点 よって、このテストの合計点数は 70 点でした。 ★考察(確認) [問1] 5点 * 10問正解 pan{c110197}% bc -l [~/Ruby] 5*10 50 プログラムの結果も「50点」なので正しい。 [問2] 5点 * 4問正解 なのでボーナス得点の+5点はないはずである。 pan{c110197}% bc -l [~/Ruby] 5*4 20 プログラムの結果も「20点」なので正しい。 問1と問2を足すと pan{c110197}% bc -l [~/Ruby] 50+20 70 で、プログラムの結果と同じなのでこのプログラムは成功している。 ★★問2でボーナス得点がある場合(5問以上正解) pan{c110197}% ./two_methods.rb [~/Ruby] このプログラムはクイズの配点プログラムです。 [問1] 1問目から10問目 まで。 [問2] 11問目から20問目 まで。 ※問2に関しては、5問以上正解でボーナス得点として+5点。 [問1] の正解数はいくつでしたか?(配点:各5点) 10 [問1]の得点 50 点 [問2] の正解数はいくつでしたか?(配点:各5点) ※5問以上正解で+5点 5 [問2]の得点 30 点 よって、このテストの合計点数は 80 点でした。 ★考察(確認) [問1] 5点 * 10問正解 pan{c110197}% bc -l [~/Ruby] 5*10 50 プログラムの結果も「50点」なので正しい。 [問2] 5点 * 5問正解 なのでボーナス得点の+5点がある。 pan{c110197}% bc -l [~/Ruby] 5*5 25 25+5 30 プログラムの結果も「30点」なので正しい。 問1と問2を足すと pan{c110197}% bc -l [~/Ruby] 50+30 80 quit で、プログラムの結果と同じなのでこのプログラムは成功している。 ******************************** 考察 ******************************** ●defのメソッドを toi-1 という名前にしていたのですが、そうするとエラー メッセージが出力されました。ということから、メソッドの名前にはハイフンな どの記号は使えないのだと学びました。 ●defのメソッドの中で printf("[問1]の得点 \t %d 点\n",def内で設定した変数) のように、def toi1 と def toi2 の結果をそれぞれの def の中でprintを使っ て出力させていたのですが、そうするとdefの外で最終的に足し算をする printf("\n\nよって、このテストの合計点数は %d 点でした。 \n",toi1(kazu1)+toi2(kazu2)) の箇所でエラーが発生することに気が付きました。 なので、defの中ではprint文は使わず計算結果のみを呼び出せるようにして、 defの外で自由自在に結果をあつかえるようにしました。 ●最初は、問2のボーナス得点を問2のクイズを5問以上正解したら1問につき5点 ずつ配点という設定にしていたのですが、それではあまりにも不公平なのと現実 味がないプログラムになってしまったので、全体に+5点をすることにしました。 改善した後でも「もらってくる値によって計算を変化させる」という課題に沿っ ているのでこの結果に仕上げました。 ●実行結果の確認 見やすくするため実行結果のそれぞれの下で考察を行なっているので、具体的な 確認は実行結果の項目を参照。 defの計算結果の値が違うところが正しく実行されているか考察した結果、思っ た通り実行されているのでこのプログラムは正しく動いていると言える。 ---------------------------------------------------------------------- 3. 感想 ---------------------------------------------------------------------- ●機械的な操作を繰り返すもの 機械で言えばレジの計算機能や、電卓、などがあり、 おもちゃで言えば、スイッチをいれるとたいこを叩くおもちゃがあり、 人間で言えば毎週時間割どおりに行動する学生も機械的だと言えると思います。 ●感想 プログラムの問題で、Aに行き詰まってしまい軽い気持ちでBを作成してみたら思っ ていたよりも簡単にプログラムを組むことができて達成感を感じました。 Aのプログラムは難しく、組合せの公式を学習し直すところから始めました。 組合せと順列はITパスポート試験の学習で最近復習したばかりだったのですが、 今回プログラム内で使用しているタイプの公式は今までしたことがなかったので 理解に少し時間を使ってしまいました。 また、 m * factorial(m-1) の文は複雑でとても理解するまで時間を使いましたが、理解すると繰り返しのよ うな機能になっていて、whileやfor文を使ってないのに、おもしろい仕組みだと 思いました。 ---------------------------------------------------------------------- 4.参考文献 ---------------------------------------------------------------------- 組合せの考え方と公式 http://www.ne.jp/asahi/license/ikawa17/info_2/kougi/kougi106.html タイトル不明 組合せの復習に使用 http://www.kwansei.ac.jp/hs/z90010/sugaku1/sugaku1.htm 基礎プログラミング II 第 5 回 「何度も呼び出そう」 西村まどか http://roy/~madoka/2011/r2/05/ 基礎プログラムII 第8回 神田直弥 http://roy/~naoya/rubyII/8.html 自分のプログラミングメモ 協力してくれた先輩 : 小林勝範 ---------------------------------------------------------------------- 5. 添付 ----------------------------------------------------------------------