Compleanno di 100 anni combinato


26

Recentemente stavo sommando le età di me stesso, di mia moglie e dei miei figli e mi sono reso conto che ad un certo punto in un futuro non troppo lontano le nostre età si sommeranno esattamente a 100 anni.

Sfida

Per un input costituito da un'età (totale) combinata e un elenco di date di nascita, fornire la data in cui tutte le età combinate si sommano al totale dato.

  1. L'età combinata di input (in anni) sarà un numero intero positivo
  2. L'elenco di input delle date di nascita sarà un elenco (qualunque sia il formato più comodo per la tua lingua) di date che devono contenere una rappresentazione numerica di Giorno, Mese e Anno. Numero di giorni trascorsi da un'epoca specifica non accettabile. Si può presumere che l'elenco delle date di input sia ordinato in ordine cronologico.
  3. L'output sarà una singola data nello stesso formato delle date di input
  4. Ai fini dell'età combinata, 1 anno è considerato esattamente 365,25 giorni
  5. Per alcuni input, sarà impossibile trovare una data dopo tutte le date di nascita quando tutte si sommano all'età combinata. Ad esempio, prendiamo in considerazione due date di nascita distanti 20 anni, ma vogliamo una combinazione di 10 anni. In tal caso, l'output sarebbe il decimo compleanno della data di nascita più vecchia. In altre parole, le singole età sono considerate 0 per tutte le date precedenti alla data di nascita dell'individuo
  6. L'output sarà la prima data in cui le età combinate si sommano almeno all'età di input
  7. È possibile utilizzare le funzioni di integrate
  8. È necessario supportare le date che risalgono al 1970/01/01.

Esempi

Qui sto dando tutte le date nel formato AAAA / MM / GG, ma puoi in qualunque formato tu voglia.

Input                                               Output

 10  2000/01/01                                     2010/01/01
100  1975/03/05,1978/07/23,2008/11/12,2012/12/20    2018/11/22
100  1975/03/06,1978/07/23,2008/11/12,2012/12/20    2018/11/23
100  1975/03/09,1978/07/23,2008/11/12,2012/12/20    2018/11/23
100  1975/03/10,1978/07/23,2008/11/12,2012/12/20    2018/11/24
  3  1990/08/01,1995/07/02                          1993/08/01
 50  1975/03/05,1978/07/23,2008/11/12,2012/12/20    2001/11/13

Si noti che negli ultimi due esempi, la data di output rientra nell'intervallo di date di input, come da regola 5.


1
@TimmyD. Regola 7 è un può governare, in modo da non dover seguire se non si vuole. Sospetto che le funzioni data-ora saranno utili per l'analisi delle date di input e la formattazione delle date di output. YMMV.
Trauma digitale,

5
La regola 7 è una regola di maggio . Può essere tranquillamente ignorato questo mese (e per il prossimo semestre).
Martin Ender,

Realisticamente, penso che una famiglia controllerebbe ogni compleanno, contando anni come numeri interi e non cercando di riassumere i giorni (con 0,25 per complicare la questione).
edc65,

@ edc65 Chi ha mai lasciato che la realtà si mettesse in mezzo a una buona sfida PPCG? ;-)
Digital Trauma,

Risposte:


4

Mathematica 138 107 237 byte

I miei primi tentativi furono sciatti e indegni. Questo dovrebbe funzionare in generale, a condizione che le date di nascita siano indicate in ordine decrescente, come nei casi di test.

I casi di test sono stati ben scelti e difficili da implementare correttamente. Il codice è risultato molto più lungo di quanto sperassi.

La logica generale è

  1. Risolvi per x (in giorni) in modo tale che la distanza da x a ciascuna data di nascita sia sommata al passare del tempo target (ad es. 100 anni convertiti in giorni).
  2. Se la prima data + x giorni> ultima data di nascita, rimuovi l'ultima data di nascita e ripeti il ​​passaggio (1), altrimenti passa a (3).
  3. Ritorno (prima data + x giorni)

t_~f~d_:=If[DateDifference[a=DateObject[DatePlus[d[[1]],Solve[t 365.25==Tr@(x-Join[{0},
QuantityMagnitude@(DateDifference[d[[1]],#,"Day"]&/@Rest@d)]),{x}][[1,1,2]]]/.
{y_,m_,n_,h_}:>{y,m,n+1}],d[[-1]]]>Quantity[0,"Days"],f[t,Most@d],a]

Casi test

f[10, {{2000, 1, 1}}]
f[100, {{1975, 3, 5}, {1978, 7, 23}, {2008, 11, 12}, {2012, 12, 20}}]
f[100, {{1975, 3, 6}, {1978, 7, 23}, {2008, 11, 12}, {2012, 12, 20}}]
f[100, {{1975, 3, 9}, {1978, 7, 23}, {2008, 11, 12}, {2012, 12, 20}}]
f[100, {{1975, 3, 10}, {1978, 7, 23}, {2008, 11, 12}, {2012, 12,  20}}]
f[3, {{1990, 8, 1}, {1995, 7, 2}}]
f[50, {{1975, 3, 5}, {1978, 7, 23}, {2008, 11, 12}, {2012, 12, 20}}]

le foto


Inoltre, non è necessario lo spazio.
LegionMammal978,

1

PowerShell, 145 125 byte

param($a,$b)$c=@();$b|%{$c+=date $_};$t=$a*365.25;$d=$c[0];while($t-gt0){$c|%{if($_-le$d){$t--}};$d=$d.AddDays(1)}"{0:d}"-f$d

Una sfida piuttosto complicata, ma relativamente semplice una volta capito.

Espanso e commentato:

param($a,$b)          # Take our input
$c=@()                # Make a new array $c
$b|%{$c+=date $_}     # Change our input array $b of strings into dates, store in $c
$t=$a*365.25          # Target number of days we need to account for
$d=$c[0]              # Our starting date, also our cumulative date for output
while($t-gt0){        # While we still have days remaining
  $c|%{               # Iterate through our birthdays
    if($_-le$d){$t--} # If the birthday is less than our cumulutive day, subtract a day
  }
  $d=$d.AddDays(1)    # We've accounted for another day, so increment our cumulative day
}
"{0:d}"-f$d           # Format output

Esempio:

L'input deve contenere un array formattato in modo esplicito di rappresentazioni di stringhe-date. L'output è in MM/DD/YYYYformato (impostazione predefinita per la localizzazione en-us in PowerShell).

PS C:\Tools\Scripts\golfing> .\combined-100-year-birthday.ps1 50 @('03/05/1975','07/23/1978','11/12/2008','12/20/2012')
11/13/2001

Modifica: golfato di 20 byte modificando il modo in cui passiamo in rassegna i compleanni e utilizzando while invece di do / until


0

PHP, 220 byte

Ho aggiunto alcune nuove righe per la leggibilità.

function c($y,$s){for($d=$y*365.25;++$i<count($l=array_map(date_create,$s));)$d+=
$l[0]->diff($l[$i])->days;($l[$i-1]>$r=$l[0]->add(new DateInterval(P.ceil($d/$i).D)
))?c($y,array_slice($s,0,-1)):print$r->format('Y/m/d');}

Ideone

Ecco la versione ungolfed:

function printCombinedBirthday($combinedAgeInYears, $listOfBirthDatesStrings)
{
    $combinedAgeInDays = $combinedAgeInYears * 365.25;
    $listOfBirthDates = array_map('date_create', $listOfBirthDatesStrings);
    $numberOfBirthDates = count($listOfBirthDates);

    for ($i = 0; $i < $numberOfBirthDates; ++$i) {
        $combinedAgeInDays += $listOfBirthDates[0]->diff($listOfBirthDates[$i])->days;
    }

    $combinedAgeInDays = ceil($combinedAgeInDays / $numberOfBirthDates);
    $interval = new DateInterval('P'. $combinedAgeInDays .'D');
    $result = $listOfBirthDates[0]->add($interval);

    if ($listOfBirthDates[$numberOfBirthDates - 1] > $result)
    {
        printCombinedBirthday(
            $combinedAgeInYears,
            array_slice($listOfBirthDatesStrings, 0, -1)
        );
    }
    else {
        echo $result->format('Y/m/d');
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.