ページ 11

スケーリング

Posted: 2009年11月29日(日) 17:09
by 愛川
11個の非負の整数を入力として受け付ける。
これは,0点から10点までの人数だと考える。
このデータを利用して,*を使用したヒストグラムを出力したい。
人数が大きい場合には,*が画面を折り返してしまい,見にくくなってしまう。
そこで,次のようにスケーリング(縮小)を行いたい。
 *の数の最大を40 としたい。
 全データの最大値が,*の数を40個として表すことにする。
 例えば,最大値が80 だとして,それを40個とすることは50%に縮小することになる。
他のデータも同じように縮小する。
人数が20の場合は,*が10個になる。
また人数が25 の場合は,その半分が12.5なるが,小数点以下を四捨五入して*を13個とする。
 なお最大値が40以下の場合は,拡大も縮小も行わない。

出力形式は,最初の2桁が点数,一つ空白,続いて8桁が人数,一つ空白,*を0から40個となる。

下のようなプログラムは書けたのですが、スケーリングのやり方が分かりません。
よかったら教えていただけないでしょうか。

#include<stdio.h>
int main(void){
int i, j, data[11];
for(i = 0; i <= 10; i++){
scanf("%d", &data);
}
for(j = 0; j <= 10; j++){
printf("%2d %8d ", j, data[j]);
for(i = 0; i < data[j]; i++){
printf("*");
}
printf("\n");
}
return(0);
}

Re:スケーリング

Posted: 2009年11月29日(日) 17:28
by non
まず、環境を書いてください。
それに、添付するプログラムは、規約を読んで<pre>タグを使ってください。

さて、上のプログラムに、最大値を求めるプログラムを
追加してみてください。

Re:スケーリング

Posted: 2009年11月29日(日) 17:44
by 愛川
申し訳ありません。
OSはWindows、コンパイラはVisual C++です。
#include<stdio.h>
int main(void){
	int i, j, data[11];
	for(i = 0; i <= 10; i++){
		scanf("%d", &data);
	}
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		for(i = 0; i < data[j]; i++){
			printf("*");
		}
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年11月29日(日) 20:38
by 愛川
最大値を求めるプログラムを追加しました。
ここからがどうしていいか全く分かりません。
よろしくお願いします。
#include<stdio.h>
int main(void){
	int i, j, data[11], max = 0;
	for(i = 0; i <= 10; i++){
		scanf("%d", &data);
		if(data > 0){
			max =data;
		}
	}
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		for(i = 0; i < data[j]; i++){
			printf("*");
		}
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年11月29日(日) 21:17
by ドラ
>最大値を求めるプログラムを追加しました。
本当に最大値が取得できているか確認しましたか?


>ここからがどうしていいか全く分かりません。
無事に最大値maxが算出できたなら、何個'*'を出力すればいいか計算するだけでしょう。
max <= 40 の場合は、data[j]個。
max > 40 の場合は基本的に40の(data[j]/max)倍の個数の'*'を表示すればいいですね。
ただし、小数点以下四捨五入の指示がありますので求めた個数に0.5を加算してから
小数点以下を切り捨てると良いでしょう。

Re:スケーリング

Posted: 2009年11月29日(日) 21:18
by non
最大値が求まっていません。
このままでは、最後に入力したデータがmaxになります。

Re:スケーリング

Posted: 2009年11月29日(日) 22:55
by 愛川
すみません、間違えていました。
最大値の部分は直せましたが、そのあとがうまくいきません。
#include<stdio.h>
int main(void){
	int i, j, data[11], max = 0;
	double a;
	for(i = 0; i <= 10; i++){
		scanf("%d", &data);
		if(data > max){
			max =data;
		}
	}
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		if(max <= 40){
			for(i = 0; i < data[j]; i++){
				printf("*");
			}
		}
		else{
			a = 40 / max + 0.5;
			for(i = 0; i < a * data[j]; i++){
				printf("*");
			}
		}
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年11月29日(日) 23:56
by 星映
>a = 40 / max + 0.5;
maxが80のとき以下のようになってしまいます。
a = 40 / 80 + 0.5;
a = 0.5 + 0.5;
a = 1;
あとfor文内のa * date[j]の部分はループの内一回だけ 「a」*「maxの入った配列」 になりますので、
i < a * max
i < 1 * 80
i < 80
です。つまり、「maxの入った配列」のときは「*」が80個並びます。

今回間違っている部分は四捨五入する場所です。四捨五入するのは「*」の表示個数です。
頑張ってみてください。

Re:スケーリング

Posted: 2009年11月30日(月) 00:36
by 愛川
以下のようになったのですが…
出力が若干うまくいきません。
#include<stdio.h>
int main(void){
	int i, j, data[11], max = 0;
	double a;
	for(i = 0; i <= 10; i++){
		scanf("%d", &data);
		if(data > max){
			max =data;
		}
	}
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		if(max <= 40){
			for(i = 0; i < data[j]; i++){
				printf("*");
			}
		}
		else{
			a = 40 * data[j] / max;
			for(i = 0; i < a + 0.5; i++){
				printf("*");
			}
		}
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年11月30日(月) 02:26
by 星映
>以下のようになったのですが… 
>出力が若干うまくいきません。 
>a = 40 * data[j] / max;
>for(i = 0; a + 0.5; i++){
>	printf("*");
>}
おそらくscanfで0を入力すると0が入った配列は1になるでしょう。
なぜならi < a + 0.5が原因です。
scanfで0ならaは必然的に0になります。
i < 0 + 0.5 → i < 0.5になります。
i = 0のときは → 0 < 0.5(結果はTRUE)
そのため最低一回は 「*」を表示します。

自分なりに作ってみました。あと肝心の式の部分は(double)(~) int(a)などと書いていますが、
便利なので使わせて頂いてます。もし分からなければ質問していただいて結構ですよ。
#define OK1~OK3の部分や#ifndef,#ifdef,#endifは無駄なおまけです。

#include<stdio.h>

//#define OK1
//#define OK2
//#define OK3

int main(void)
{
	int i, j, data[11], max = 0;
	double a;
	for(i = 0; i <= 10; i++)
	{
		#ifdef OK1
		scanf("%d", &data);	
		#endif
		
		#ifdef OK2
		data = i * i;      	
		#endif
		
		#ifdef OK3
		data = i * 100;    	
		#endif
		
		#ifndef OK1
		#ifndef OK2
		#ifndef OK3
		printf("#defineのOK1かOK2かOK3のコメントをはずしてください\n");
		printf("コメントをはずした後コンパイルしてください。\n");
		return(0);
		//コメントははずすだけで結構です。
		#endif
		#endif
		#endif
		
		if(data > max)
		{
			max = data;
		}
	}
	printf("max %d\n",max);
	for(j = 0; j <= 10; j++)
	{
		printf("%2d %8d ", j, data[j]);
		if(max <= 40)
		{
			for(i = 0; i < data[j]; i++)
			{
				printf("*");
			}
		}
		else
		{       
			if( 40 > (a = (double)(data[j]) / (double(max) / 40) ) )
			{
				a += 0.5;	
			}
			for(i = 0; i < int(a); i++)
			{
				printf("*");
			}
		}
		printf(" %d ", i );
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年11月30日(月) 09:04
by non
極力、本人のプログラムを活かすなら
for(i = 0; i <(int)( a + 0.5 ); i++){

Re:スケーリング

Posted: 2009年11月30日(月) 23:59
by 愛川
皆様、ありがとうございます。
以下のようなプログラムで合っているかと思うのですが…
無駄な処理など入っていますでしょうか?
#include<stdio.h>
int main(void){
	int i, j, data[11], max;
	double a;
	scanf("%d", &data[0]);
	max = data[0];
	for(i = 1; i <= 10; i++){
		scanf("%d", &data);
		if(data > max){
			max = data;
		}
	}
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		if(max <= 40){
			for(i = 0; i < data[j]; i++){
				printf("*");
			}
		}
		else{
			a = (int)(max / 40 + 0.5);
			for(i = 0; i < (int)(data[j] / a + 0.5); i++){
				printf("*");
			}
		}	
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年12月01日(火) 00:52
by 星映
回答します。(前回は無駄な回答ごめんなさい)
>scanf("%d", &data[0]);
>max = data[0];
>for(i = 1; i <= 10; i++){
>	scanf("%d", &data);
>	if(data > max){
>		max = data;
>	}
>}
scanf("%d, &data[0]);
max = data[0];
を分けている意図が分かりません。ここは消してfor文のiの開始を0にするべきです。

>a = (int)(max / 40 + 0.5);
aにスケーリングの比率を代入する際、int型でキャストしている部分が謎です。それと比率には四捨五入は必要ないです。(「*」の表示個数をint型でキャストしているのは問題ないですが。)

以上です。頑張ってください。

Re:スケーリング

Posted: 2009年12月01日(火) 08:43
by non
>scanf("%d, &data[0]);
>max = data[0];
>を分けている意図が分かりません。ここは消してfor文のiの開始を0にするべきです。

これは、maxに初期値を入れるためですね。今回は、点数入力に範囲があるので(0から10点)
max=0に初期化すればi=0からでOKです。

Re:スケーリング

Posted: 2009年12月01日(火) 08:56
by non
>点数入力に範囲があるので(0から10点)
上限はなかったですね。

無駄というほどではありませんが、このような解答もあるという例で
#include<stdio.h>
int main(void){
	int i, j, data[11], max=0;
	double a;
	for(i = 0; i <= 10; i++){
		scanf("%d", &data);
		if(data > max){
			max = data;
		}
	}
	a=(max>40)? max/40.0:1.0;
	for(j = 0; j <= 10; j++){
		printf("%2d %8d ", j, data[j]);
		for(i = 0; i < (int)(data[j] / a + 0.5); i++){
			printf("*");
		}
		printf("\n");
	}
	return(0);
}

Re:スケーリング

Posted: 2009年12月02日(水) 00:55
by 愛川
回答してくださった皆様、ありがとうございます。
ようやく自分でも納得いくプログラムができました。
またなにかありましたらよろしくお願いいたします。