質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

java コラッツ予想のプログラム

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,842

前提・実現したいこと

このページの問題を解きたいです。
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36

概要としては、

「コラッツ予想とは、任意の整数において、それが偶数ならば2で割り、
奇数だったら3を掛けたものに1を足すという操作を繰り返して行くと、必ず最終的に1になる。つまり、 

f(n) = n/2 (nは偶数) 
f(n) = 3n+1 (nは奇数) 

今、2つの整数の組を入力として与えた時、その範囲内の全ての整数においてこの操作を繰り返し、その中で、1に辿り着くまでにかかった操作の回数が一番多かった時の回数を出力させる。この時、一緒に入力した2整数も出力させる。」

というものです。
例えば入力を1と10とした場合は、1〜10の全ての数字に対して上記の操作を行い、1と、10と、その中で一番手順数が多かった回数、つまり3つの整数を出力させる、ということです。また、入力は2つの整数の組は1セットに限らないそうです。

上記ページの例では、入力を

1 10 
100 200 
201 210 
900 1000 


としたとき、出力は

1 10 20 
100 200 125 
201 210 89 
900 1000 174


こうなると書いてあります。

発生している問題・エラーメッセージ

一度は正しい出力がされたのですが、その後はいくらやっても4行分の出力がされません。
「試したこと」にも書きましたが、indexのインクリメントは正しくされているみたいです。どこがおかしいのでしょう??

また、他のプログラムを書いていてもたまに起こるのですが、その時によって実行結果が変わるというのはどういう仕組み?なのかも合わせて教えてくれると嬉しいです。

追記

あと、入力を終了させたいときはどうすればいいのでしょう?自分で実行する際はCtrl+Cで強制終了させていましたが、上記のサイトはプログラムを自動採点するため、Ctrl+Cを押させるということはできないと思われるので、プログラムがいつまで経っても終わらない(キーボードからの入力待ちの状態が一生続く)んじゃないかと推測してます。
前は入力は2つの整数が1組だけだと勘違いしていたので、scan.nextIntを2回だけ実行して終わればいいと思っていたのですが、
そうじゃなかったためにwhile(scan.hasNext())を使わざるを得なくなってしまい、入力側(人間)がまだ入力を続けたいのか、そうでないのかを判別させる方法が分からないという問題も出てしまいました。

1 10
100 200
201 210
900 1000  (ここまで入力)
1 10 20
100 200 125
201 210 89

追記2

fuzzballさんに言われた通り変更したところ、

[0]1 10 20 
[1]100 200 125 
[2]201 210 89 
[3]900 1000 174


と、一旦正しい結果が出力されたのですが、
次のような入力を与えたところ、それ以降に正しく出力されたときと同じ入力を行っても、上記のような不具合が発生するようになりました。

1 10 100 2000 201 210 900 1000

再び正しい出力がされたときは、一旦PCの電源を落とし、再びONにした後でしたが、これは何か関係あるのでしょうか?
そもそも、プログラムを実行し終わった後、もう1回プログラムを実行したところで、2つの事象は別個のものなので、
前の実行時の入力に、あとの実行時の出力が引っ張られるなんて考えられませんが…

該当のソースコード

import java.util.Scanner;
import java.util.InputMismatchException;

class Collatz {
    public static void main (String[] args) {
        Scanner scan = new Scanner(System.in);
        int input[][] = new int[100000][2];  //入力の2つの整数組を行列に入れて覚えておく
        int output[] = new int[100000];      //出力となる手順数の最大値を入れておく
        int index = 0;                    //何組目の2つの整数組を見ているかを表す

        while(scan.hasNext()) {
            try {
                int countmax = 0;
                int count = 1;

                input[index][0] = scan.nextInt();
                input[index][1] = scan.nextInt();
                int a = input[index][0];
                int b = input[index][1];

//以下のループで第1引数の方が小さいことを前提としているため、第2引数の方が小さい場合は値を交換しておく          

                if(b<a) {
                    int tmp = b;
                    b = a;
                    a = tmp;
                }

                for(int n=a; n<=b; n++) {
                    int m = n;
                    while(m!=1) {
                        if(m%2==0) m/=2;
                        else m = 3*m+1;
                        count++;
                    }
                    if(count>countmax) 
                        countmax = count;  //手順数が暫定最大手順数より多かったら値を更新
                    count = 1;
                }

            output[index] = countmax;
            index++;  //次の2つの整数組に進む

            } catch(InputMismatchException e) {
                System.out.println("Input must be type int.");
            }
        }

        System.out.println("index="+index); //デバッグ用
        for(int i=0; i<index; i++) {
            System.out.println(input[i][0]+" "+input[i][1]+" "+output[i]);  //結果の出力
        }
    }
}

試したこと

4行分の出力がされないので、indexのインクリメントが適切な回数行われていないのかな?と思い、
ソースコード下から6行目にindexの値を出力させる行を足しましたが、ちゃんとindex=4と出力されたので、
まるで原因が分かりません。それどころか、この1行を追加しただけで実行結果が以下のように変わってしまい、もう何が起きてるのやらという感じです…

1 10
100 200
201 210
900 1000  (ここまで入力)
index=4
1 10 20
100 200 125


indexが4なので、for文でi=0~3の4回分プリントが行われるはずですが、何がおかしいのでしょう?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ozwk

    2017/04/18 12:35

    コンソールを下までスクロールしたら出てくるとか無いですか

    キャンセル

  • RinT_hinabita39

    2017/04/18 13:35

    それはないですね…

    キャンセル

回答 1

checkベストアンサー

0

とりあえず、

System.out.println("["+i+"] "+input[i][0]+" "+input[i][1]+" "+output[i]); //結果の出力

こうして下さい。

【追記】

paiza.ioで試してみたら、ちゃんと4行表示されました。
https://paiza.io/projects/x36e89d40dffDyoD8CX7qg

index=4
1 10 20
100 200 125
201 210 89
900 1000 174

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/18 13:50

    追記2で述べたような特殊な入力を行った後だと、挙動がおかしくなるという不具合は解決しませんでしたが、UVaにもう1回投げてみたところ正しくできていると認定されました…(特に何も変えていない) 結局原因がよくわかりませんでした… お手数おかけしてすいません。

    キャンセル

  • 2017/04/18 13:57

    入力を「1 10 100 2000 201 210 900 1000」にしても4行出力されました。
    動作環境がおかしいのでは?

    キャンセル

  • 2017/04/21 03:54

    そうなんですか!?自分は全然詳しい人じゃないのでよくわかりませんが、とりあえずWindowsにjavaを入れて使っています。そのサイトでちゃんと動くということは、自分のPCが何かおかしいってことなんですかね…?今度別のPCで同じコードを実行してみたいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る