Spotify 拼图问题
我正在尝试解决此页面上描述的“最佳之前”Spotify 难题。基本上,输入三个由斜杠分隔的整数(例如 11/3/4),您应该生成一个具有 2011-03-04 格式的最早可能日期的输出。如果没有可能的日期,则应返回原始字符串,后跟“is Illegal”。
下面我的解决方案的想法是借用了我在 github。当我提交这个Python代码时,它被接受了。由于不熟悉Python,这是我用Java制作类似东西的最佳尝试,并且不使用任何日历函数,如这个解决方案发布在 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
括号中。有什么办法解决这个问题吗?谢谢。
I'm trying to solve the "best before" Spotify puzzle described on this page. Basically, with an input of three integers separated by slashes (e.g. 11/3/4) you're supposed to generate an output with the earliest possible date in 2011-03-04 format. If no date is possible, it should return the original string followed by "is illegal".
The idea for my solution below was borrowed from a Python solution I found for the same problem at github. When I submit this Python code, it is accepted. Not being familiar with Python, this is my best attempt at making something similar with Java, and without using any Calendar functions as can be seen in this solution posted here at stackoverflow.
When I submit my solution, however, I get "Wrong Answer" as the response. Try as I might, I cannot find any errors with this code. I feel like I've tried every single possible combination of inputs, and all my outputs come out correctly. Anyone have any idea what I might be missing?
Since I'm relatively new to programming in general, feel free to also give advice on how the code can be improved in general if you want. I'm sure it might look noobish. Thanks!
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);
}
}
I'm the one who asked the question, but can't seem to comment and reply normally to the answers anymore since I registered to stackoverflow and lost my original cookies or something.
Anyway, thanks palacsint for your answer. I fixed the leap year problem and now my answer finally got accepted!
A question about the last two lines in the getBestDate()
method. I put those there just because Eclipse IDE otherwise gives me the error "This method must return a result of type Integer[]". It doesn't seem satisfied with having all the returns in if
brackets. Is there any way around this? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一个错误:它接受 2100/02/29。 2100 年不是闰年,因此没有 2011/02/29。
如果我是你,我会使用
SimpleDateFormat
进行解析和验证(提示:lenient
解析)。它更简单、更直观,代码也更容易阅读。 (不要重新发明轮子)上面还有一些其他想法。
不必要的任务:
返回日期OK = false;
只需使用
false
返回:(在您的情况下,
dataOK
变量是不必要的。)抛出异常而不是
System.exit()
。在
getBestDate()
方法中,最后两行永远不会运行。它们是死代码(因为illegal()
调用System.exit()
):如果可能,请避免静态方法和字段。最后,学习如何编写单元测试是一个好问题。
One bug: it accepts 2100/02/29. 2100 is not a leap year, so there is no 2011/02/29.
If I were you, I would use
SimpleDateFormat
for parsing and validating (hint:lenient
parsing). It's much simpler, much intuitive and the code would be easier to read. (Don't Reinvent The Wheel)Some other thoughts above.
Unnecessary assignments:
return dateOK = false;
Just return with
false
:(The
dataOK
variable is unnecessary in your case.)Throw exceptions instead of
System.exit()
.In the
getBestDate()
method the last two lines never run. They are dead code (sinceillegal()
callsSystem.exit()
):If it's possible avoid static methods and fields. Lastly, it's a good problem to learn how to write unit tests.
你的“年”处理有问题。谜题文字说
但是,当我在程序中输入 1000 到 2000 之间的年份时,它会逐字报告它们,即使它们不是有效的输出。
There are problems in your 'year' handling. The puzzle text says
However, when I enter years between 1000 and 2000 into your program, it will report them verbatim, even though they aren't valid output.