Date validation challenge from coding contest

I’m working on a coding challenge where I need to parse three numbers separated by forward slashes and find the earliest valid date. The output should be in YYYY-MM-DD format, or return “is illegal” if no valid date can be formed.

I have a working Python solution but my Java implementation keeps getting rejected. The logic seems correct when I test it manually, but something must be wrong. Here’s my Java code:

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

public class DateValidator {

    static int num1, num2, num3;
    static int firstSlash, secondSlash;
    static String yearStr, monthStr, dayStr;

    public static void main(String[] args) throws IOException {
        String input = getUserInput();
        parseNumbers(input);
        Integer[] numbers = {num1, num2, num3};
        Arrays.sort(numbers);
        Integer validDate[] = findEarliestDate(numbers, input);
        formatOutput(validDate);
        displayResult(validDate);
    }

    public static String getUserInput() throws IOException {
        BufferedReader reader = new BufferedReader
          (new InputStreamReader(System.in));
        String input; 
        input = reader.readLine();
        return input;
    }

    public static void parseNumbers(String input) {
        try {
        firstSlash = input.indexOf('/');
        secondSlash = input.lastIndexOf('/');
        num1 = Integer.parseInt(input.substring(0, firstSlash));
        num2 = Integer.parseInt(input.substring(firstSlash+1, secondSlash));
        num3 = Integer.parseInt(input.substring(secondSlash+1, input.length()));
        }catch (StringIndexOutOfBoundsException e){
            invalidDate(input);
        }catch (NumberFormatException e){
            invalidDate(input);
        }
    }

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

    public static Integer[] findEarliestDate(Integer[] numbers, String input){
        num1 = numbers[0];
        num2 = numbers[1];
        num3 = numbers[2];
        if (isValidDate(num1, num2, num3)){
            Integer[] result = {num1, num2, num3};
            return result;
        }
        else if (isValidDate(num1, num3, num2)){
            Integer[] result = {num1, num3, num2};
            return result;
        }
        else if (isValidDate(num2, num1, num3)){
            Integer[] result = {num2, num1, num3};
            return result;
        }
        else if (isValidDate(num2, num3, num1)){
            Integer[] result = {num2, num3, num1};
            return result;
        }
        else if (isValidDate(num3, num1, num2)){
            Integer[] result = {num3, num1, num2};
            return result;
        }
        else if (isValidDate(num3, num2, num1)){
            Integer[] result = {num3, num2, num1};
            return result;
        }else{
            invalidDate(input);
        }
        Integer[] result = {num1, num2, num3};
        return result;
    }

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

    public static void formatOutput(Integer[] dateArray){
        if (dateArray[0] < 1000){
            dateArray[0]+=2000; 
        }
        yearStr = String.valueOf(dateArray[0]); 
        if (dateArray[1] < 10){ 
            monthStr = "0" + dateArray[1];
        }else{
            monthStr = String.valueOf(dateArray[1]);
        }
        if (dateArray[2] < 10){
            dayStr = "0" + dateArray[2];
        }else{
            dayStr = String.valueOf(dateArray[2]);
        }
    }

    public static void displayResult(Integer[] dateArray){
        System.out.println(yearStr + "-" + monthStr +"-" + dayStr);
    }
}

I’m pretty new to programming so any tips on what might be wrong or how to improve the code would be great. Also wondering about those last two lines in the findEarliestDate method - I only added them because Eclipse complained about missing return statement. Is there a better way to handle this?

Your year range validation is backwards. You’ve got year > 100 && year < 2000 which rejects most valid 4-digit years like 1995, 1850, etc. If you want to reject 3-digit years, it should be year > 100 && year < 1000. Made this exact mistake in a contest once when handling 2-digit vs 4-digit years. Also, sorting first then trying permutations won’t find the earliest date. You need to generate all valid date combinations first, then sort those actual dates chronologically. Right now you’re just ordering raw numbers, not the final dates.

Found the bug in your leap year logic! In isValidDate, you’ve got if (year % 100 == 0 && year % 400 != 0) setting isLeap to false, but then the next line sets it back to true because it’s outside the nested if block. So 1900 gets treated as a leap year when it shouldn’t be. You need to either wrap isLeap = true; in an else block or redo the logic completely. I hit the exact same issue on a similar problem and it drove me crazy trying to find it. Also, that unreachable code at the end of findEarliestDate shows the method structure needs work - try using one return statement after all the conditionals instead of multiple returns in each if block.

you’re sorting the numbers array but then reassigning num1, num2, num3 back to the sorted values - that breaks your permutation logic. keep the original values and try different combinations instead of sorting them first. also, your year validation is off - year > 100 && year < 2000 will reject 1999 and other valid years. double check that range.

Your findEarliestDate method is broken - it finds the first valid date permutation, not the earliest one chronologically. After sorting, you need to check combinations in chronological order instead of just trying all six permutations randomly. Try smallest number as year first, then work through systematically. I hit this exact bug on a similar contest problem and wasted hours debugging before I realized I needed to actually compare dates, not just grab any valid one. Also, your invalidDate method calls System.exit(0) which’ll mess with automated testing - throw an exception or return a special value instead.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.