Spotify难题问题

5
我正在尝试解决在此页面上描述的“最佳使用日期”Spotify难题。基本上,输入三个以斜杠分隔的整数(例如11/3/4),你应该生成一个格式为2011-03-04的最早可能日期的输出。如果没有可能的日期,则应返回原始字符串后跟“is illegal”。

我下面的解决方案的思路是从我在github上找到的相同问题的Python解决方案中借鉴的。当我提交这个Python代码时,它被接受了。由于不熟悉Python,这是我用Java制作类似东西的最好尝试,并且不使用任何Calendar函数,如可以在此处在stackoverflow发布的解决方案中看到。

然而,当我提交我的解决方案时,我得到“错误答案”的响应。无论我怎么努力,都找不出这个代码的任何错误。我感觉自己已经尝试过每一个可能的输入组合,所有的输出都是正确的。有人有任何想法,我可能会错过什么吗?

由于我对编程比较新手,请随意提供有关代码如何改进的建议。谢谢!

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或者其他原因,现在无法正常评论和回复答案。

无论如何,感谢palacsint提供的答案。我解决了闰年问题,现在我的答案终于被接受了!

有一个关于getBestDate()方法中最后两行的问题。我加了这些内容只是因为Eclipse IDE否则会给出错误提示“此方法必须返回类型为Integer []的结果”。它似乎不满足于所有的返回都在if括号中。有没有什么办法解决这个问题?谢谢。

2个回答

1
一个bug:它接受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()方法中,最后两行永远不会运行。它们是死代码(因为illegal()调用了System.exit()):

}else{
    illegal(dateInput);
}

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

如果可能的话,避免使用静态方法和字段。最后,学习如何编写单元测试是一个好问题。

0

你的“年份”处理存在问题。谜题文本如下:

给定一个可能含糊不清的日期“A/B/C”,其中A、B、C是介于0和2999之间的整数,使用它们作为日、月和年(但不一定按照这个顺序),输出在2000年1月1日至2999年12月31日(包括这两天)之间的最早合法日期。

然而,当我输入1000年到2000年之间的年份时,你的程序会直接报告它们,即使它们并不是有效的输出结果。


1
我认为这不应该是一个问题,因为题目中明确说明“假设年份是用四位数字表示的,介于2000年到2999年之间。”以及“给出一个可能存在歧义的日期‘A/B/C’,其中A、B、C都是0到2999之间的整数”。尽管如此,我还是试图通过在更新的代码中添加“if (year > 100 && year < 2000)”这一行来修复它。但仍然收到“错误答案”的回复。谢谢! - mattboy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接