2011-09-11 20 views
5

Sto cercando di risolvere il "migliore prima" puzzle di Spotify descritto su questo page. Fondamentalmente, con un input di tre numeri interi separati da barre (ad es. 11/3/4), si suppone di generare un output con la data più remota possibile nel formato 2011-03-04. Se nessuna data è possibile, dovrebbe restituire la stringa originale seguita da "è illegale".Problema del puzzle di Spotify

L'idea per la mia soluzione di seguito è stata presa in prestito da una soluzione Python che ho trovato per lo stesso problema a github. Quando invio questo codice Python, è accettato. Non avendo dimestichezza con Python, questo è il mio miglior tentativo di creare qualcosa di simile con Java, e senza usare alcuna funzione di Calendar come si può vedere nella soluzione this postata qui su StackOverflow.

Quando invio la mia soluzione, tuttavia, ricevo "Risposta errata" come risposta. Prova come potrei, non riesco a trovare errori con questo codice. Mi sento come se avessi provato ogni singola combinazione possibile di input e tutte le mie uscite fossero uscite correttamente. Qualcuno ha idea di cosa mi possa sfuggire?

Dato che sono relativamente nuovo alla programmazione in generale, sentiti libero di dare anche consigli su come il codice può essere migliorato in generale, se vuoi. Sono sicuro che potrebbe sembrare un nonno. Grazie!

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

io sono quello che ha fatto la domanda, ma non riesco a commentare e rispondere normalmente alle risposte più da quando ho registrato a StackOverflow e ho perso i miei biscotti originali o qualcosa del genere.

In ogni caso, grazie palacsint per la risposta. Ho risolto il problema degli anni bisestili e ora la mia risposta è finalmente stata accettata!

Una domanda relativa alle ultime due righe nel metodo getBestDate(). Li metto solo perché l'IDE di Eclipse in caso contrario mi dà l'errore "Questo metodo deve restituire un risultato di tipo Integer []". Non sembra soddisfatto di avere tutti i ritorni nelle parentesi if. C'è un modo per aggirare questo? Grazie.

risposta

1

Un bug: accetta 2100/02/29. 2100 è non un anno bisestile, quindi non c'è 2011/02/29.

Se fossi in te, vorrei utilizzare SimpleDateFormat per l'analisi e la convalida (suggerimento: lenient analisi). È molto più semplice, molto intuitivo e il codice sarebbe più facile da leggere. (Non reinventare la ruota)

Alcune altre considerazioni precedenti.

Assegni inutili: data di restituzioneOK = falso;

basta tornare con false:

return false; 

(La variabile dataOK non è necessaria nel tuo caso.)

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

generano eccezioni, invece di System.exit().

Nel metodo getBestDate() le ultime due righe non vengono mai eseguite. Sono codice morto (dal illegal() chiamate System.exit()):

}else{ 
    illegal(dateInput); 
} 

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

Se si tratta di metodi e campi statici possibile evitare. Infine, è un buon problema imparare a scrivere test unitari.

0

Ci sono problemi nella gestione del 'anno'. Il testo di puzzle dice

indicata una data forse ambiguo "A/B/C", dove A, B, C sono interi tra 0 e 2999, in uscita la data legale possibile prima tra 1 gen 2000 e 31 dicembre 2999 (compresi) che li usano come giorno, mese e anni (ma non necessariamente in questo ordine).

Tuttavia, quando si immettono anni tra 1000 e 2000 nel programma, verranno segnalati alla lettera, anche se non sono risultati validi.

+1

Suppongo che questo non dovrebbe essere un problema poiché il problema afferma "Si può presumere che l'anno, quando viene fornito con quattro cifre, sia compreso tra 2000 e 2999." e "Data una data forse ambigua" A/B/C ", dove A, B, C sono numeri interi tra 0 e 2999". Ciononostante, ho provato a ripararlo aggiungendo una riga "if (year> 100 && year <2000)" come puoi vedere nel codice aggiornato. Ricevo comunque risposte "sbagliate". Grazie! – mattboy