2012-11-06 8 views
8

Problema 19:Il codice del progetto Eulero # 19 sembra giusto. Cosa mi manca?

Si sono dati le seguenti informazioni, ma si può scegliere di fare qualche ricerca per te stesso.

1 gennaio 1900 era un lunedì.

Trenta giorni ha settembre, aprile, giugno e novembre.

Tutti gli altri hanno trentuno, risparmiando solo febbraio, che ha ventotto, pioggia o sole. E negli anni bisestili, ventinove.

un anno bisestile si verifica su qualsiasi anno uniformemente divisibile per 4, ma non su un secolo meno che non sia divisibile per 400.

Quante domeniche cadde sulla primo giorno del mese nel corso del XX secolo (1 Dal 1901 al 31 dicembre 2000)?

Ho pensato che usare PHP per questo sarebbe un gioco da ragazzi dato che ha così tante funzioni integrate di data e ora. Il mio codice è davvero piuttosto semplice, quindi ho difficoltà a vedere che cosa sto facendo è sbagliato.

Il mio codice:

<?php 
    echo "<pre>"; 
    $sunday_count = 0; 
    for($year = 1901; $year <= 2000; $year++) { 
     for($month = 1; $month <= 12; $month++) { 
      // Produces a date in format: 1/1/2000 
      $date = $month . "/1/" . $year; 
      $time = strtotime($date); 
      $is_sunday = (date('l', $time) == "Sunday"); 
      echo "$date " 
       . ($is_sunday ? 'was a Sunday. ' : '') 
       . "<br>"; 
      if($is_sunday) $sunday_count++; 
     } 
    } 
    echo "Answer: $sunday_count"; 
    echo "</pre>"; 
?> 

La soluzione mio codice viene in mente è 169, che non è corretto. Qualche idea?

Modifica 1

La soluzione si suppone essere 171.

Utilizzando Wolfram Alpha e il mio orologio di Windows, ho raddoppiato controllato alcune delle domeniche che i miei rapporti di codice. Tutti loro controllano OK.

Quindi sembra che il mio codice stia segnalando domeniche valide e legittime, ma in qualche modo ne ha persi due.

Edit 2

ho fatto la seguente modifica di lieve entità alla formattazione della data nel mio codice:

$date = sprintf('%d-%02d-01', $year, $month); // formats yyyy-mm-dd 

Allora ho usato @ il codice di MadaraUchiha per generare una matrice contenente le 171 date corrette .

Dopo aver confrontato le sue date con la mia, questi sono i due perse date:

1901-09-01 1901-12-01

Edit 3

Codepad also shows che queste date non sono domeniche (ma dovrebbero essere davvero).

E sono certo che le date vengono interpretate correttamente come YYYY-MM-DD perché una delle date che il mio codice offre alla soluzione è 2000-10-01, che sarebbe solo una domenica se 10 è il mese non il giorno

Edit 4

Quindi, a quanto pare, se su un sistema a 32 bit, timestamp Unix non funzionano al di fuori del campo:

Fri, 13 Dec 1901 20:45:54 GMT 

a

Tue, 19 Jan 2038 03:14:07 GMT 
+0

Probabilmente è correlato a questa nota su [phpdoc] (http://php.net/strtotime): "In PHP 5 precedenti alla 5.2.7, richiedendo una data occorrenza di un determinato giorno della settimana in un mese in cui quel giorno della settimana il primo giorno del mese avrebbe aggiunto in modo errato una settimana al timestamp restituito, che è stato corretto in 5.2.7 e versioni successive. " ? – Prasanth

+0

Sto eseguendo la versione 5.3.10 di PHP, quindi sospetto che sia qualcos'altro. – Joncom

+0

Risulta, questo non è affatto collegato al php. È la definizione del 20 ° secolo che ha causato la confusione. Vedi la discussione su [questo] (http://java.dzone.com/articles/thursday-code-puzzler-all) thread. Ma, mi chiedo come la gente ha ottenuto 171. Wikipedia definisce l'intervallo in caso contrario. ProjEuler forse sta usando una definizione e una risposta diversa. – Prasanth

risposta

4

La ragione per cui potrebbe non funzionare su alcuni sistemi che utilizzano timestamp è che l'intervallo di un timestamp Unix su sistemi a 32 bit è da Fri, 13 Dec 1901 20:45:54 GMT a Tue, 19 Jan 2038 03:14:07 GMT, quindi ti manca quasi tutti i mesi nel primo anno.

I sistemi a 64 bit hanno numeri interi maggiori che rendono l'intervallo più grande (in PHP).

+0

Sembra coprire le due date. Apache è in esecuzione a 64 bit sul mio sistema. È questo che intendi con un sistema a 64 bit? – Joncom

+0

Controlla 'PHP_INT_MAX'. È '9223372036854775807' sul mio sistema a 64 bit. –

+0

PHP_INT_MAX è 2147483647 sul mio sistema. Suppongo che questa sia la risposta che stavo cercando! – Joncom

2

ottengo 171 con questo codice (molto più breve e più leggibile), usando gli oggetti DateTime:

header("Content-type: text/plain"); //Browser display 

$time = new DateTime("1901-01-01"); 
$end = new DateTime("2000-12-31"); 

$counter = 0; 

while (!$time->diff($end)->invert) { //$time isn't greater than $end 
    $time->modify("+1 month"); 
    if ($time->format("l") == "Sunday") { 
     $counter++; 
     echo $time->format("Y-m-d") . " was a Sunday!\n"; 
    } 
} 

echo "\nTotal number of Sundays: $counter"; 

Quando si usano oggetti DateTime, si sta trattando date come Date e non come numeri o stringhe. Ciò offre un enorme vantaggio in termini di flessibilità rispetto a qualsiasi altro approccio.

+0

Ciao. Grazie. Anche il tuo codice funziona bene sul mio sistema. Comunque sono curioso di sapere se potresti essere in grado di dirmi perché nel mio codice 2 mesi sembrano essere "saltati"? Saluti. – Joncom

0

Il problema su questo codice è la linea

$date = $month . "/1/" . $year;

questo dovrebbe essere

$date = "1/".$month."/" . $year;

È mescolato i luoghi di mesi e giorni.

Problemi correlati