5

このページで説明されている「ベスト ビフォー」の Spotify パズルを解こうとしています。基本的に、スラッシュで区切られた 3 つの整数 (例: 11/3/4) を入力すると、2011-03-04 形式で最も早い日付の出力を生成することになっています。日付が不可能な場合は、元の文字列の後に「is illegal」が続くものを返す必要があります。

以下のソリューションのアイデアは、同じ問題に対してgithubで見つけた Python ソリューションから借用したものです。この Python コードを提出すると、受け入れられます。Python に慣れていないので、これは Java と同様のものを作成するための私の最善の試みであり、ここでスタックオーバーフローに投稿されたこのソリューションに見られるように、カレンダー関数を使用しません。

ただし、ソリューションを送信すると、応答として「間違った回答」が返されます。このコードでエラーを見つけることができません。考えられるすべての入力の組み合わせを試したような気がしますが、すべての出力が正しく出力されます。私が何を見逃しているのか、誰にも分かりますか?

私は一般的にプログラミングに比較的慣れていないので、必要に応じて、コードを一般的に改善する方法についてもアドバイスをお願いします。私はそれが野蛮に見えるかもしれないと確信しています。ありがとう!

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class DateProggy3 {

    static int var1, var2, var3;
    static int slashPosition1, slashPosition2;
    static String yearString, monthString, dayString;

    public static void main(String[] args) throws IOException {
        String dateInput = readDate();
        splitInputToInts(dateInput);
        Integer[] dateArray = {var1, var2, var3};
        Arrays.sort(dateArray);
        Integer bestDate[] = getBestDate(dateArray, dateInput);
        convertDate(bestDate);
        printDate(bestDate);
    }

    public static String readDate() throws IOException {
        BufferedReader stdin = new BufferedReader
          (new InputStreamReader(System.in));
        String dateInput; 
        dateInput = stdin.readLine();
        return dateInput;
    }

    public static void splitInputToInts(String dateInput) {
        try {
        slashPosition1 = dateInput.indexOf('/');
        slashPosition2 = dateInput.lastIndexOf('/');
        var1 = Integer.parseInt(dateInput.substring(0, slashPosition1));
        var2 = Integer.parseInt(dateInput.substring(slashPosition1+1, slashPosition2));
        var3 = Integer.parseInt(dateInput.substring(slashPosition2+1, dateInput.length()));
        }catch (StringIndexOutOfBoundsException e){
            illegal(dateInput);
        }catch (NumberFormatException e){
            illegal(dateInput);
        }
    }

    public static void illegal(String dateInput){
        System.out.println(dateInput + " is illegal");
        System.exit(0); 
    }

    public static Integer[] getBestDate(Integer[] dateArray, String dateInput){
        var1 = dateArray[0];
        var2 = dateArray[1];
        var3 = dateArray[2];
        if (testDate(var1, var2, var3)){
            Integer[] bestDate = {var1, var2, var3};
            return bestDate;
        }
        else if (testDate(var1, var3, var2)){
            Integer[] bestDate = {var1, var3, var2};
            return bestDate;
        }
        else if (testDate(var2, var1, var3)){
            Integer[] bestDate = {var2, var1, var3};
            return bestDate;
        }
        else if (testDate(var2, var3, var1)){
            Integer[] bestDate = {var2, var3, var1};
            return bestDate;
        }
        else if (testDate(var3, var1, var2)){
            Integer[] bestDate = {var3, var1, var2};
            return bestDate;
        }
        else if (testDate(var3, var2, var1)){
            Integer[] bestDate = {var3, var2, var1};
            return bestDate;
        }else{
            illegal(dateInput);
        }
        Integer[] bestDate = {var1, var2, var3};
        return bestDate;
    }

    public static boolean testDate(int year, int month, int day){
        boolean leapYear = false;
        boolean dateOK;
        if (year > 100 && year < 2000){
            return dateOK = false;
        }
        if (year < 1000){
            year+=2000;
        }
        if (year < 0){
            return dateOK = false;
        }
        if (year % 4 == 0) {
            if (year % 100 == 0 && year % 400 != 0) {
                leapYear = false; 
            }
            leapYear = true;
        }else{
            leapYear = false;
        }
        if (month > 12 || month < 1){
            return dateOK = false;
        }
        switch (month){
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                if (day > 31 || day < 1){
                    return dateOK = false;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if (day > 30 || day < 1){
                    return dateOK = false;
                }
                break;
            case 2:
                int maxDay;
                if (leapYear){
                    maxDay = 29;
                }else{
                    maxDay = 28;
                }
                if (day > maxDay || day < 1){
                    return dateOK = false;
                }
        }
        return dateOK = true;
    }


    public static void convertDate(Integer[] dateArray){
        if (dateArray[0] < 1000){
            dateArray[0]+=2000; 
        }
        yearString = String.valueOf(dateArray[0]); 
        if (dateArray[1] < 10){ 
            monthString = "0" + dateArray[1];
        }else{
            monthString = String.valueOf(dateArray[1]);
        }
        if (dateArray[2] < 10){
            dayString = "0" + dateArray[2];
        }else{
            dayString = String.valueOf(dateArray[2]);
        }
    }

    public static void printDate(Integer[] dateArray){
        System.out.println(yearString + "-" + monthString +"-" + dayString);
    }
}

私は質問をした人ですが、stackoverflowに登録して元のCookieなどを紛失したため、コメントして回答に正常に返信できなくなったようです。

とにかく、答えてくれてありがとう。うるう年の問題を修正し、ついに私の答えが受け入れられました!

getBestDate()メソッドの最後の 2 行についての質問です。Eclipse IDE が「このメソッドは Integer[] 型の結果を返さなければなりません」というエラーを表示するからです。ifすべてのリターンを括弧内に収めることに満足していないようです。これを回避する方法はありますか?ありがとう。

4

2 に答える 2

1

1 つのバグ: 2100/02/29 を受け入れます。2100年はうるう年ではないため、2011/02/29 はありません

私があなたなら、SimpleDateFormat解析と検証に使用します (ヒント:lenient解析)。はるかにシンプルで直感的で、コードが読みやすくなります。(車輪を再発明しないでください)

上記の他のいくつかの考え。

不要な代入: return dateOK = false;

で戻るだけfalseです:

return false;

dataOKあなたの場合、変数は不要です。)

public static void illegal(String dateInput){
    System.out.println(dateInput + " is illegal");
    System.exit(0); 
}

の代わりに例外をスローしますSystem.exit()

このgetBestDate()メソッドでは、最後の 2 行は実行されません。それらはデッドコードです(illegal()呼び出し以来System.exit()):

}else{
    illegal(dateInput);
}

Integer[] bestDate = {var1, var2, var3};
return bestDate;

可能であれば、静的メソッドとフィールドを避けてください。最後に、単体テストの書き方を学ぶのは良い問題です。

于 2011-09-11T19:33:50.300 に答える
0

「年」の扱いに問題があります。パズルのテキストは言う

あいまいな可能性のある日付 "A/B/C" (A、B、C は 0 から 2999 までの整数) を指定すると、2000 年 1 月 1 日から 2999 年 12 月 31 日まで (両端を含む) の最も早い法定日付を日として使用して出力します。月と年 (必ずしもこの順序である必要はありません)。

ただし、1000 年から 2000 年までの年をプログラムに入力すると、有効な出力ではないにもかかわらず、逐語的に報告されます。

于 2011-09-11T11:07:33.577 に答える