底辺 b, 高さ h の三角形を考える。ただし b, h ともに整数で、10≦b≦20, 10≦h≦20 の範囲をとるものとする。この中で、面積が 70 以上 97 以下になるものの数を数えたい。次の指示に従って、プログラムを完成させなさい。
今、手元に次の硬貨がある。
10円 2枚 50円 5枚 100円 1枚 500円 2枚
ヒント1:硬貨の枚数から合計金額を求める手続きを、関数に独立させてみよ。
ヒント2:最小値を求める手順を復習せよ。「暫定の最小値を更新する」手順である。
提出するのは 2. のプログラムだけでよい。
ある市販のソフトウェアAとソフトウェアBがある。 このソフトウェアの価格には、購入本数に応じた値引きがあり、 1本あたりの単価が購入本数に応じて決まる。 このため、価格設定によっては「購入本数の多いほうが、購入総額が安くなる」という 逆転現象が起こることがある。 この逆転現象について調査するプログラムを、以下の指示に従って作りなさい。
まず、ソフトウェアAについて考える。 単価は以下のようになっている。
本数 | 単価 |
---|---|
~4本 | 5000円 |
5~9本 | 4500円 |
10本~ | 3500円 |
int priceA(int n)を作りなさい。
ヒント:条件分岐に無駄がないように注意せよ。
int total_priceA(int n)を作りなさい。n は 0 以上であることを前提としてよい。
ヒント:この関数に条件分岐が必要か、よく検討せよ。
ヒント:購入本数が減るように逆順のループを回すことに注意せよ。 総額の最小値は、ほとんどの場合に更新される。
ヒント:総額の最小値を更新しなかった場合に限って表示すればよい。
次に、ソフトウェアBについて考える。 単価は以下のようになっている。
本数 | 単価 |
---|---|
~4本 | 5000円 |
5~9本 | 4800円 |
10~14本 | 4600円 |
15~19本 | 4500円 |
20~49本 | 4300円 |
50~79本 | 4100円 |
80~99本 | 3600円 |
100~999本 | 3500円 |
1000本~ | 3300円 |
このように価格表が大きく複雑であるので、 価格の改定があった場合にプログラムの修正作業が楽になるように工夫したい。 つまり、ソフトウェアAの場合とは違う構造のプログラムを作りたい。
int priceB(int n)を作りなさい。ただし、プログラム(関数)の中に価格を直接書き込むのではなく、 配列に価格を書き並べるようにしなさい。 例えば、次のような2つの配列を大域変数(グローバル変数)に宣言するとよい。 (これ以外の配列の使い方をしてもよい。)
int pricesB[] = { 5000, 4800, 4600, 4500, 4300, 4100, 3600, 3500, 3300 }; int numsB[] = { 5, 10, 15, 20, 50, 80, 100, 1000, -1 /* 番兵 */ };
ヒント1:numsB[] 配列を先頭要素から順番にアクセスするループは
for (i=0; numsB[i]>=0; i++) { ... }のように書ける。 参考までに、配列の最後を表す特別な値(-1)の要素は、「番兵」と呼ばれる。
ヒント2:配列には複数の要素が含まれることから、配列をあらわす変数名に、英単語の複数形を用いる習慣がある。 またこの例では、関数名と区別する目印の役目も果たしている。
int total_priceB(int n)を作りなさい。main() で関数の値を表示して、動作を確かめなさい。
ヒント:total_priceA() で条件分岐をした人は、ここでもう一度考えなおして欲しい。条件分岐をせずにすませた人は、その利点を改めて感じ取って欲しい。
int suggestB(int n)を作りなさい。 さらに main() で関数の値を表示して、動作を確かめなさい。
ヒント1:関数の動作としては、逆転現象の起こらない場合は、 与えられた n をそのまま返すことになる。
ヒント2:簡単のため、1000本よりも多く購入しても、それ以上は単価の値引きが起こらないことを利用してもよい。
ヒント3:関数を1000という数値に依存しないで記述できると、なおよい。ちなみに、-1 という数値は番兵をあらわすので、依存してよい。
ソフトウェアAとBの処理を共通化したい。値段表をあらわす配列を引数として受け取る関数
int price(int n, int prices[], int nums[]) int total_price(int n, int prices[], int nums[]) int suggest(int n, int prices[], int nums[])
を作り、2種類の配列を切り替えることで、これまでに作った関数 priceA(), total_priceA(), priceB(), total_priceB(), suggestB() と同じ動作をさせなさい。 ソフトウェアAとBそれぞれに配列を準備して、 main() 関数から作成した関数に引数として与えて呼び出して、動作を確かめなさい。
ヒント:1000のような数値には依存してはいけない。
逆転現象の起こる本数は、9本と8本。
ソフトウェアBで逆転の起こる本数は(マウスで選択すると見える)→ n=999〜943, 99〜98, 79〜71, 49〜48 ←