コードの間違いを指摘して下さい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
mkt
記事: 9
登録日時: 11年前

コードの間違いを指摘して下さい

#1

投稿記事 by mkt » 11年前

AOJの問題 http://judge.u-aizu.ac.jp/onlinejudge/d ... d=ITP1_7_B に関してなのですが、下記のコードで

Sample Input
5 9

を試したところ

Sample Input
2

となるはずが

自分の環境では
0

となってしまいました。

コードのどこが間違っているかを教えて下さい。よろしくお願いします。

コード:

#include <stdio.h>
    
int main(void)
{
    int n,x,no[100],i,j,k,count=0;
    while (1) {
        scanf("%d %d",&n,&x);
        if (n==0&&x==0) {
            break;
        } else {
            for (i=0;i<n;i++) {
                no[i]=i+1;
            }
            for (i=0;i<n;i++) {
                for (j=0;j<n;j++) {
                    for (k=0;k<n;k++) {
                        if (no[i]==no[j]||no[i]==no[k]||no[j]==no[k]) {
                        	break;
                        } else if (no[i]+no[j]+no[k]==x) {
                            count++;
                        } 
                    }
                }
            }
                              
        }
    printf("%d",count/6);
    }
    return 0;    
}

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

Re: コードの間違いを指摘して下さい

#2

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

18行目のbreakが蛇足だと思います。
27行目で改行していないのも問題です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: コードの間違いを指摘して下さい

#3

投稿記事 by box » 11年前

そもそもno[]という配列を使う必要があるのでしょうか。
最後に6で割っているのはなぜでしょうか。

if文の条件を見直せばうまくいくような気がします。ついでにfor文も。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

much

Re: コードの間違いを指摘して下さい

#4

投稿記事 by much » 11年前

◆不適切な点

・breakの位置

→例えばi=2 j=1 k=1 となったとき no[j]||no[k]は成り立ちますのでbreakが実行されて
 i=2 j=2 k=1 となってしまう
 実はこのことによって順番による重複分が消えているので
 countはそのまま答えの2になっている
 そして(int)2/(int)6 で0と出てきます

・1ループしたあとはcountを初期化しましょう

→実行するたびにどんどん増えていますよ

◆悪くはないが改善すべき点

・printfの最後の改行

→省略

・no[]の必要性がない

→no[a]は(a+1)などで表現できる もしくは ループ用変数からしか参照されていないし
 ループ用変数もそれにしか使われてないみたいなので
 for(a=1;a<n+1;a++) としてno[a]はaという表現もできる

・題意より3≦n≦100を満たさないnを入力された場合は跳ねる(errorを出力する)べきである

→invalid input

・効率のいいアルゴリズムに

→順番による重複分を調べないアルゴリズムが存在します
 組み合わせの数値はすべて異なるので i<j<k が常に成り立つと考えても問題がないから...

・コメントを記述する

→他の人が見てわかりません、特に唐突に出てくるcountを6で割っている理由

◆より高みを目指すなら(拡張性,汎用性を高める,必要性はないけど再利用しやすい)

・今回の場合、重複した場合の数が重複しない場合の数の6倍であるが
 この6の値は組み合わせる数値の数に対し柔軟に可変にすべき
 (ただし、上で効率のいいアルゴリズムを変えていない場合)

→組み合わせる数値の数(=3)を定数に,重複した時の倍率(3!=6)を求める部分を関数に

・上のように組み合わせる数値の数が異なればループの回数も異なるので
 再帰関数を用いるべきである


→いろいろな方法があるけど引数は 組み合わせる数値の残り数を入れることがポイント
 組み合わせる数値の残り数を参照されるたびに1引いて0になったらreturn

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

Re: コードの間違いを指摘して下さい

#5

投稿記事 by box » 11年前

much さんが書きました: ・上のように組み合わせる数値の数が異なればループの回数も異なるので
 再帰関数を用いるべきである
AOJの当該の問題では多重ループでよいと書いてあるので、
特に再帰を使うこともないと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: コードの間違いを指摘して下さい

#6

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

much さんが書きました:◆悪くはないが改善すべき点

・printfの最後の改行

→省略
これはこのままだとほぼ確実にWrong Answerになるので、◆不適切な点に入ると思います。
much さんが書きました:・no[]の必要性がない

→no[a]は(a+1)などで表現できる もしくは ループ用変数からしか参照されていないし
 ループ用変数もそれにしか使われてないみたいなので
 for(a=1;a<n+1;a++) としてno[a]はaという表現もできる
for(a=1;a<=n;a++) という表現もできます。(自分はこっちの方が好みです)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: コードの間違いを指摘して下さい

#7

投稿記事 by YuO » 11年前

うーん,回答がなされていますが,この件名で少なくとも4回は質問しているようなので,
「自身による正しいデバッグがなされていない」
のが間違いという回答をしたくなります。

入力が5 9の場合,17行目が実行される回数は高く見積もっても高々5³ = 125回です。
14行目にブレイクポイントを設定し,i, j, k, no, no[j], no[k], no + no[j] + no[k], countあたりをウオッチしながらステップ実行すれば, みけCATさんが最初に指摘された18行目のbreakの問題に気付くはずです。
デバッガが無い環境でも,現17行目の前に

コード:

printf("i=%d, j=%d, k=%d, no[i]=%d, no[j]=%d, no[k]=%d, no[i]+no[j]+no[k]=%d, count=%d\n", i, j, k, no[i], no[j], no[k], no[i] + no[j] + no[k], count);
を,現18行目の前に

コード:

puts("break");
を,現20行目の前に

コード:

puts("count++");
を,現27行目の前に

コード:

printf("count = %d\n", count);
を書いて実行すれば,その出力結果を読み解くことで想定している動作では無いことがわかるはずです。


個人的には,原因を見つけるための方法が不足しているのが問題とみなしています。
なので,デバッグ手法を覚えることが,根本的な解決策に思えてなりません。
オフトピック
AOJの問題が他人に訊こうが何しようが解きさえできれば良い,というだけであればデバッグを他人に任せても良いでしょうが……。

mkt
記事: 9
登録日時: 11年前

Re: コードの間違いを指摘して下さい

#8

投稿記事 by mkt » 11年前

返信遅れました。皆様、回答ありがとうございます。疑問は解決しました。

>YuO様
言われた通りにプログラムを実行してみると、どこが、何故間違えなのかが、よく分かりました。C言語を使いこなせるようにしたいので、デバッグの手法を覚えていきたいと思います。

>みけCAT様、box様、much様
間違えの端的な指摘と+αのアドバイスありがとうございます。改善して効率のよいプログラムを目指します。

閉鎖

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