Kombinierter 100-jähriger Geburtstag

26

Ich habe kürzlich das Alter von mir und meiner Frau und meinen Kindern addiert und festgestellt, dass sich in nicht allzu ferner Zukunft unser Alter auf genau 100 Jahre summieren wird.

Herausforderung

Geben Sie für eine Eingabe, die aus einem kombinierten (Gesamt-) Alter und einer Liste von Geburtsdaten besteht, das Datum aus, an dem sich alle kombinierten Alter zur angegebenen Summe addieren.

  1. Das eingegebene kombinierte Alter (in Jahren) ist eine positive ganze Zahl
  2. Die eingegebene Liste der Geburtsdaten ist eine Liste (unabhängig vom für Ihre Sprache geeigneten Format) der Daten, die eine numerische Darstellung von Tag, Monat und Jahr enthalten muss. Anzahl der Tage seit einer bestimmten Epoche ist nicht akzeptabel. Sie können davon ausgehen, dass die Liste der Eingabedaten in chronologischer Reihenfolge sortiert ist.
  3. Die Ausgabe erfolgt als einzelnes Datum im selben Format wie die Eingabedaten
  4. Für die Zwecke des kombinierten Alters gilt 1 Jahr als genau 365,25 Tage
  5. Bei einigen Eingaben ist es nicht möglich, ein Datum nach allen Geburtsdaten zu finden, wenn sich alle zum kombinierten Alter addieren. Nehmen wir zum Beispiel zwei Geburtsdaten, die 20 Jahre auseinander liegen, aber wir wollen eine Kombination von 10 Jahren. In diesem Fall wäre die Ausgabe der 10. Geburtstag des älteren Geburtsdatums. Mit anderen Worten, das individuelle Alter wird für alle Daten vor dem Geburtsdatum dieser Person als 0 betrachtet
  6. Die Ausgabe ist das erste Datum, an dem das kombinierte Alter mindestens dem eingegebenen Alter entspricht
  7. Sie können integrierte Uhrzeitfunktionen verwenden
  8. Sie müssen Daten unterstützen, die bis zum 01.01.1970 zurückreichen.

Beispiele

Hier gebe ich alle Daten im Format JJJJ / MM / TT an, aber Sie können jedes beliebige Format angeben.

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

Beachten Sie, dass in den letzten beiden Beispielen das Ausgabedatum gemäß Regel 5 im Bereich der Eingabedaten liegt.

Digitales Trauma
quelle
1
@TimmyD. Regel 7 ist eine Mai- Regel, Sie müssen sie also nicht befolgen, wenn Sie nicht möchten. Ich vermute, dass Datum / Uhrzeit-Funktionen nützlich sind, um Eingabedaten zu analysieren und Ausgabedaten zu formatieren. YMMV.
Digitales Trauma
5
Regel 7 ist eine Mai- Regel. Sie kann diesen Monat (und für das nächste halbe Jahr) ignoriert werden.
Martin Ender
Realistisch gesehen würde eine Familie an jedem Geburtstag nachsehen, wobei Jahre als ganze Zahlen gezählt würden und nicht versucht würde, die Tage zusammenzufassen (mit 0,25, um die Sache zu komplizieren).
edc65
@ edc65 Wer hat jemals die Realität einer guten PPCG-Herausforderung im Weg stehen lassen? ;-)
Digitales Trauma

Antworten:

4

Mathematica 138 107 237 Bytes

Meine ersten Versuche waren schlampig und unwürdig. Dies sollte im Allgemeinen funktionieren, vorausgesetzt, die Geburtsdaten werden wie in den Testfällen in der Reihenfolge von frühestens bis spätesten angegeben.

Die Testfälle waren gut ausgewählt und schwer korrekt umzusetzen. Der Code fiel viel länger aus, als ich gehofft hatte.

Die allgemeine Logik ist zu

  1. Berechnen Sie x (in Tagen) so, dass sich der Abstand von x zu jedem Geburtsdatum auf den angestrebten Zeitablauf summiert (z. B. 100 Jahre in Tage umgerechnet).
  2. Wenn das früheste Datum + x Tage> das späteste Geburtsdatum ist, entfernen Sie das späteste Geburtsdatum und wiederholen Sie Schritt (1). Andernfalls fahren Sie mit (3) fort.
  3. Rückgabe (frühestes Datum + x Tage)

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]

Testfälle

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}}]

Bilder

DavidC
quelle
Außerdem brauchen Sie keinen Platz.
LegionMammal978
1

PowerShell, 145 125 Bytes

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

Ziemlich knifflige Herausforderung, aber einmal verstanden relativ einfach.

Erweitert und kommentiert:

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

Beispiel:

Die Eingabe muss ein explizit formatiertes Array von Zeichenfolgendatumsdarstellungen enthalten. Die Ausgabe erfolgt im MM/DD/YYYYFormat (Standard für die En-Us-Lokalisierung 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

Bearbeiten - 20 Bytes durch Ändern der Iterationsmethode für Geburtstage und durch Verwenden von while anstelle von do / until

AdmBorkBork
quelle
0

PHP, 220 Bytes

Ich habe einige Zeilen hinzugefügt, um die Lesbarkeit zu verbessern.

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

Hier ist die ungolfed Version:

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');
    }
}
Schwarzes Loch
quelle