教えてください初心者です

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
nakama123

教えてください初心者です

#1

投稿記事 by nakama123 » 11年前

下記のコードを書いてみました
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
/*int no[10] = {0,1,2,3,4,5,6,7,8,9};*/


int k;
int no[10];
int x;
int y;
int temp;
int sum;
int j;
int even_a;
int even_b;
int even_c;
int even_d;
int under_a;
int under_b;
int under_c;
int under_d;
int under_e;

for (k = 0; k < 10; k++)
no[k] = k;

while(1)
{
srand(time(NULL));
for (k = 0; k < 100; k++)
{
x = rand() % 10;
y = rand() % 10;

temp = no[x];
no[x] = no[y];
no[y] = temp;
}

for (j = 0; j < 4; j++)
{
sum += no[j];
if((no[j])==2)
++even_a;
if((no[j])==4)
++even_b;
if((no[j])==6)
++even_c;
if((no[j])==8)
++even_d;
if((no[j])==0)
++under_a;
if((no[j])==1)
++under_b;
if((no[j])==2)
++under_c;
if((no[j])==3)
++under_d;
if((no[j])==4)
++under_e;
}
if(((15<=sum) && (sum <= 24)) && ((even_a+even_b+even_c+even_d)==1 || (even_a+even_b+even_c+even_d)==2) && ((under_a+under_b+under_c+under_d+under_e)== 2 || (under_a+under_b+under_c+under_d+under_e)== 3))
{
printf("%d\t", no[j] );
printf("\n");
break;
}
}
return 0;
}
0~9までの数値を抜出して(合計範囲が15~24)(偶数が1個もしくは2個)(小数値0~4が2個もしくは3個含まれること)この条件に当てはまる組み合わせを見つけると
printf文で出力してループを出る.....はずなんですが、動いてくれません。
どこをどう書き直せばいいのか分かりませんどなたかご指南ください。宜しくお願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 教えてください初心者です

#2

投稿記事 by みけCAT » 11年前

とりあえず、コードを提示するときはBBcodeを有効にした状態でcodeタグで囲み、
かつ適切なインデントをしていただけると、見やすくて助かります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 教えてください初心者です

#3

投稿記事 by みけCAT » 11年前

sum、even_a~even_d、under_a~under_eが全て初期化されていないようですね。

コード:

while(1)
{
の直後で、全て0で初期化しましょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 14年前

Re: 教えてください初心者です

#4

投稿記事 by box » 11年前

本題とは関係ないかもしれませんが
nakama123 さんが書きました:

コード:

	while(1)
	{
	srand(time(NULL));
乱数を毎回初期化する必要が本当にあるかどうか、やや疑問に思います。
乱数を発生させる前に「1回だけ」初期化すればいいのではないでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 教えてください初心者です

#5

投稿記事 by みけCAT » 11年前

そもそも、even_a~even_d、under_a~under_eを分ける必要はなく、
それぞれevenとunderにまとめて加算すればいいのではないでしょうか?
このあと拡張する予定があるのでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
asd
記事: 319
登録日時: 14年前

Re: 教えてください初心者です

#6

投稿記事 by asd » 11年前

すでに指摘されている通り、インデントをしっかりしてうっかりミスをなくすようにしましょう。
そのうえでまずプログラムのロジックをきちんと説明してみましょう。
また「動いてくれない」ではなく、配列がどのような場合に、どんな結果を期待したのに、実際はどうなるのかをきちんと説明しましょう。
(あなたの考える動くと回答者側が考える動くが違っているといけません)

軽く見たところ以下の問題があります。
1.抜き出す数値が配列先頭から3個まで限定
1.抜き出す数値が配列先頭から4個まで限定 (2014/07/21 20:55asd追記 指摘を受け修正しました)
 →場合によっては数値が抜き出しきれない可能性あり
  例)仮に配列が9,8,7,6,5,4,3,2,1,0の順だと小数値が2個または3個含まれないです
2.条件に当てはまらない場合、何も出力されない
 →抜き出しに失敗してもいい場合には考えなくていいです

抜き出す数値の個数が決まっていないのであれば、条件に当てはまるまで抜き出す(その際、条件が未達になってしまう数値はスルーする)必要があると思います。
守るべき条件は提示されている以下の3つです。

i.合計範囲が15~24
ii.偶数が1個もしくは2個 → 0以外の偶数を抜き出した場合、0を抜き出すためにはほかの偶数は抜き出せない
iii.小数値0~4が2個もしくは3個含まれること → 最悪でも0と1の2つを抜き出す必要があるため、小数値が1個も抜き出せていない場合は上限値は23(0と1の両方を抜き出す必要あり)、0以外の小数値が抜き出せている場合は上限値は24とする必要あり

すべてを満たすように考えると結構大変かもしれません。
iは現在書かれているように抜き出した数値の合計を保持すれば判定はできますが、
抜き出す数値を確認する際にiiとiiiが達成可能かを判定しなくてはなりません。
(抜き出しに失敗してもいいのであれば判定は不要ですが、それが今回のうまく動かない事象なのでは?)

配列の先頭から順番に数値を抜き出すとして、より条件が悪い場合を考えるとよいかと思います。
たとえば>9,7,8,6,5,4,3,2,1,0 や 0,1,2,3,4,5,6,7,8,9

先頭から順番に数値を抜き出してよいか判定しながら抜き出しましょう。
1個目:9 合計:0  偶数の個数:0 小数値の個数:0 →取得しても合計は上限を超えない。また最悪でも0,1を取得すれば偶数の個数と小数値の個数は条件を満たせる
2個目:7 合計:9(9)  偶数の個数:0 小数値の個数:0 →取得しても合計は上限を超えない。また最悪でも0,1を取得すれば偶数の個数と小数値の個数は条件を満たせる
3個目:8 合計:16(9,7) 偶数の個数:0 小数値の個数:0 →取得してしまうと合計が上限の24になり0以外に数値を取得できない。しかも0を取得しても小数値の個数2個か3個を満たせないので取ってはいけない
4個目:6 合計:16 偶数の個数:0 小数値の個数:0 →取得しても合計は上限を超えない。また最悪でも0を取得すれば偶数の個数と小数値の個数は条件を満たせる
5個目:5 合計:22(9,7,6) 偶数の個数:1(6) 小数値の個数:0 →取得してしまうと合計が上限を超えるので取得できない。
6個目:4 合計:22 偶数の個数:1(6) 小数値の個数:0 →取得してしまうと合計が上限を超えるので取得できない。
7個目:3 合計:22 偶数の個数:1(6) 小数値の個数:0 →取得してしまうと合計が上限を超えるので取得できない。
8個目:2 合計:22 偶数の個数:1(6) 小数値の個数:0 →取得してしまうと合計が上限の24になり、0以外は取得できない。偶数の個数は条件を満たしている。取得した場合の小数値の個数は1個、0がまだ取得されていないので取得してもよい
9個目:1 合計:24(9,7,6,2) 偶数の個数:1(6) 小数値の個数:1(2) →取得してしまうと合計が上限の24になるので取得できない。
10個目:0 合計:24(9,7,6,2) 偶数の個数:1(6) 小数値の個数:1(2) →取得できる
条件を満たしたので数値を出力し終了
合計:24(9,7,6,2,0) 偶数の個数:2(6,0) 小数値の個数:2(2,0)

こんな感じで数値を抜き出す時にほかの合計以外にほかの条件が実現可能かを判別する必要があります。
(実行時に必ず条件を満たさなくてもいい場合には合計上限のチェックだけ行えばOKです。
その場合抜き出し失敗となり何も出力されないことがあります)

そんなわけで実行時に必ず条件を満たすように数字を抜き出す場合結構大変だと思います。
数値の抜き出しかたの変更と、条件判定の付与が必要と思います。
あと、現在は複数の変数を用意して偶数フラグ、小数値フラグとしていますが、
個数を記憶する変数を1つずつ用意して、抜き出したときに+1したほうがよいのではと思います。
最後に編集したユーザー asd on 2014年7月21日(月) 20:55 [ 編集 1 回目 ]
Advanced Supporting Developer
無理やりこじつけ(ぉ

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 教えてください初心者です

#7

投稿記事 by みけCAT » 11年前

asd さんが書きました:軽く見たところ以下の問題があります。
1.抜き出す数値が配列先頭から3個まで限定
 →場合によっては数値が抜き出しきれない可能性あり
  例)仮に配列が9,8,7,6,5,4,3,2,1,0の順だと小数値が2個または3個含まれないです
・抜き出す数値は配列先頭から4個までではないですか?
・抜き出しきれない可能性については、配列のシャッフルを行っているので、乱数の性能がある程度良いと仮定すれば大丈夫ではないですか?
シャッフルしても条件に合わない可能性があるということですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
asd
記事: 319
登録日時: 14年前

Re: 教えてください初心者です

#8

投稿記事 by asd » 11年前

みけCAT さんが書きました:
asd さんが書きました:軽く見たところ以下の問題があります。
1.抜き出す数値が配列先頭から3個まで限定
 →場合によっては数値が抜き出しきれない可能性あり
  例)仮に配列が9,8,7,6,5,4,3,2,1,0の順だと小数値が2個または3個含まれないです
・抜き出す数値は配列先頭から4個までではないですか?
ご指摘ありがとうございます。確かに0~3の4個までですね。
みけCAT さんが書きました:・抜き出しきれない可能性については、配列のシャッフルを行っているので、乱数の性能がある程度良いと仮定すれば大丈夫ではないですか?
シャッフルしても条件に合わない可能性があるということですね。
ご推察の通りです。
文中にも例示してある通り、小数値(0~4)や偶数が後半に固まった場合などには先頭から4個まででは条件を満たすことができません。
なので実行時に必ず条件に一致した結果を出すためには抜き出し条件の厳密化が必要になります。
失敗してもOKな場合にはそこまでの条件判定は不要です。

難易度的にはまず数値合計が範囲内に収まるように抜き出してから、ステップアップとしてそのほかの条件も加味するように
進めたほうがいいかもですね。
(初心者を名乗られているのでいきなり全部の条件を満たすのは難しいと思っています)
Advanced Supporting Developer
無理やりこじつけ(ぉ

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 教えてください初心者です

#9

投稿記事 by みけCAT » 11年前

asd さんが書きました:文中にも例示してある通り、小数値(0~4)や偶数が後半に固まった場合などには先頭から4個まででは条件を満たすことができません。
なので実行時に必ず条件に一致した結果を出すためには抜き出し条件の厳密化が必要になります。
失敗してもOKな場合にはそこまでの条件判定は不要です。
これについてですが、
nakama123 さんが書きました:0~9までの数値を抜出して(合計範囲が15~24)(偶数が1個もしくは2個)(小数値0~4が2個もしくは3個含まれること)この条件に当てはまる組み合わせを見つけると
printf文で出力してループを出る.....はずなんですが、動いてくれません。
と書いてあるので、条件に一致しない数値の組が抜き出されても、
(最悪無限ループになるだけで)プログラムとしては仕様の範囲内だと認識しました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
asd
記事: 319
登録日時: 14年前

Re: 教えてください初心者です

#10

投稿記事 by asd » 11年前

みけCAT さんが書きました:
nakama123 さんが書きました:0~9までの数値を抜出して(合計範囲が15~24)(偶数が1個もしくは2個)(小数値0~4が2個もしくは3個含まれること)この条件に当てはまる組み合わせを見つけると
printf文で出力してループを出る.....はずなんですが、動いてくれません。
と書いてあるので、条件に一致しない数値の組が抜き出されても、
(最悪無限ループになるだけで)プログラムとしては仕様の範囲内だと認識しました。
もちろんその考えを否定するつもりはありません(文面通りに受け取れば見つかった時だけ出力と読めますし)
回答中にも記載しましたが、
asd さんが書きました: (抜き出しに失敗してもいいのであれば判定は不要ですが、それが今回のうまく動かない事象なのでは?)
私は質問者さんの「うまく動かない」が「条件を満たす数値を出力してくれない」と読み取り、実行すれば必ず結果を導出してくれると
考えていると思ったので、上記のような回答にした次第です。
実際がどっちなのかは質問者さんの補足待ちです。
Advanced Supporting Developer
無理やりこじつけ(ぉ

閉鎖

“C言語何でも質問掲示板” へ戻る