Spotify拼图问题

Posted

技术标签:

【中文标题】Spotify拼图问题【英文标题】:Spotify puzzle problem 【发布时间】:2011-11-14 17:06:37 【问题描述】:

我正在尝试解决此 page 中描述的“之前最好的”Spotify 难题。基本上,输入由斜杠分隔的三个整数(例如 11/3/4),您应该生成一个最早可能日期为 2011-03-04 格式的输出。如果没有日期,则应返回原始字符串,后跟“非法”。

下面我的解决方案的想法是从我在github 找到的相同问题的 Python 解决方案中借用的。当我提交这个 Python 代码时,它被接受了。不熟悉 Python,这是我使用 Java 进行类似操作的最佳尝试,并且不使用任何日历函数,如在 *** 上发布的this 解决方案中所见。

但是,当我提交解决方案时,我收到“错误答案”作为响应。尽我所能,我找不到此代码的任何错误。我觉得我已经尝试了每一种可能的输入组合,并且我的所有输出都正确输出。有人知道我可能会错过什么吗?

由于我对一般编程比较陌生,如果您愿意,请随时就如何改进代码提供建议。我敢肯定它看起来很笨拙。谢谢!

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);
    


我是提出这个问题的人,但由于我注册到 *** 并丢失了我原来的 cookie 或其他东西,我似乎无法再正常评论和回复答案。

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

关于getBestDate() 方法最后两行的问题。我把它们放在那里只是因为 Eclipse IDE 否则会给我错误“此方法必须返回 Integer [] 类型的结果”。将所有返回值都放在 if 括号中似乎并不满意。有没有办法解决?谢谢。

【问题讨论】:

【参考方案1】:

一个错误:它接受 2100/02/29。 2100 不是闰年,所以没有 2011/02/29。

如果我是你,我会使用 SimpleDateFormat 进行解析和验证(提示:lenient 解析)。它更简单,更直观,代码更容易阅读。 (不要重新发明***)

上面的一些其他想法。

不必要的分配: 返回日期OK = 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;

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

【讨论】:

【参考方案2】:

您的“年份”处理存在问题。拼图文字说

给定一个可能不明确的日期“A/B/C”,其中 A、B、C 是整数 在 0 到 2999 之间,输出可能的最早合法日期 2000 年 1 月 1 日和 2999 年 12 月 31 日(含)使用它们作为日、月和 年(但不一定按此顺序)。

但是,当我在您的程序中输入 1000 到 2000 之间的年份时,它会逐字报告它们,即使它们不是有效的输出。

【讨论】:

我认为这不应该是一个问题,因为问题指出“您可以假设年份,当给出四位数时,在 2000 和 2999 之间。”和“给定一个可能不明确的日期‘A/B/C’,其中 A、B、C 是 0 到 2999 之间的整数”。尽管如此,我确实尝试通过添加“if (year > 100 && year

以上是关于Spotify拼图问题的主要内容,如果未能解决你的问题,请参考以下文章

Spotify 谜题:避免异常处理错误

拼图游戏 v1.1

移动迷宫——拼图游戏

移动迷宫——拼图游戏

积木拼图游戏-儿童游戏免费拼图3-6岁

android滑动拼图验证码控件