ある市販のソフトウェアAとソフトウェアBがある。 このソフトウェアの価格には、購入本数に応じた値引きがあり、 1本あたりの単価が購入本数に応じて決まる。 このため、価格設定によっては「購入本数の多いほうが、購入総額が安くなる」という 逆転現象が起こることがある。 この逆転現象について調査するプログラムを、以下の指示に従って作りなさい。
いくつかの関数を作ることになるが、作りたいプログラムは全体で1つである。 main() 関数の処理内容は、徐々に変化していく。
まず、ソフトウェア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 };
ヒント:numsB[] 配列を先頭要素から順番にアクセスするループは
for (i=0; numsB[i] >= 0; i++) { ... }のように書ける。 参考までに、配列の最後を表す特別な値(-1)の要素は、「番兵」と呼ばれる。
int total_priceB(int n)を作りなさい。
ヒント:total_priceA() で条件分岐をした人は、ここでもう一度考えなおして欲しい。条件分岐をせずにすませた人は、その利点を改めて感じ取って欲しい。
int suggestB(int n)を作りなさい。 簡単のため、1000本よりも多く購入しても、それ以上は単価の値引きが起こらないことを利用してもよい。
ヒント1:関数の動作としては、逆転現象の起こらない場合は、 与えられた n をそのまま返すことになる。
ヒント2:1000という数値に依存しない関数を記述できると、なおよい。-1 という数値は番兵をあらわすので、依存してよい。