Anniversaire combiné de 100 ans

26

J'additionnais récemment l'âge de moi-même, de ma femme et de mes enfants et je me suis rendu compte qu'à un moment donné, dans un avenir pas trop lointain, nos âges totaliseraient exactement 100 ans.

Défi

Pour une entrée composée d'un âge combiné (total) et d'une liste de dates de naissance, affichez la date à laquelle les âges combinés s'ajoutent au total donné.

  1. L'âge combiné en entrée (en années) sera un entier positif
  2. La liste d'entrée des dates de naissance sera une liste (quel que soit le format qui convient à votre langue) des dates qui doivent contenir une représentation numérique du jour, du mois et de l'année. Nombre de jours depuis une époque spécifique n'est pas acceptable. Vous pouvez supposer que la liste des dates d'entrée est triée par ordre chronologique.
  3. La sortie sera une seule date dans le même format que les dates d'entrée
  4. Aux fins de l'âge combiné, 1 an est considéré comme étant exactement 365,25 jours
  5. Pour certaines entrées, il sera impossible de trouver une date après toutes les dates de naissance quand elles s'ajouteront toutes à l'âge combiné. Par exemple, considérons deux dates de naissance espacées de 20 ans, mais nous voulons une combinaison de 10 ans. Dans ce cas, la sortie serait le 10e anniversaire de la date de naissance la plus ancienne. En d'autres termes, les âges individuels sont considérés comme 0 pour toutes les dates antérieures à la date de naissance de cet individu
  6. La sortie sera la première date à laquelle les âges combinés totalisent au moins l'âge d'entrée
  7. Vous pouvez utiliser des fonctions intégrées
  8. Vous devez accepter les dates remontant au 1970/01/01.

Exemples

Ici, je donne toutes les dates au format AAAA / MM / JJ, mais vous pouvez choisir le format de votre choix.

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

Notez que dans les deux derniers exemples, la date de sortie se situe dans la plage de dates d'entrée, conformément à la règle 5.

Traumatisme numérique
la source
1
@TimmyD. Règle 7 est peut gouverner, de sorte que vous ne devez pas suivre si vous ne voulez pas. Je soupçonne que les fonctions date-heure seront utiles pour l'analyse des dates d'entrée et le formatage des dates de sortie. YMMV.
Digital Trauma
5
La règle 7 est une règle de mai . Il peut être ignoré en toute sécurité ce mois-ci (et pour le prochain semestre).
Martin Ender
De façon réaliste, je pense qu'une famille vérifierait à chaque anniversaire, comptant les années comme des entiers et n'essayant pas de résumer les jours (avec 0,25 pour compliquer les choses).
edc65
@ edc65 Qui a jamais laissé la réalité entraver un bon défi PPCG? ;-)
Digital Trauma

Réponses:

4

Mathematica 138 107 237 octets

Mes premières tentatives ont été bâclées et indignes. Cela devrait fonctionner de manière générale, à condition que les dates de naissance soient données du plus tôt au plus tard, comme dans les cas de test.

Les cas de test étaient bien choisis et difficiles à mettre en œuvre correctement. Le code s'est avéré bien plus long que je ne l'avais espéré.

La logique générale est de

  1. Résoudre pour x (en jours) de telle sorte que la distance de x à chaque date de naissance soit la somme du temps cible (par exemple 100 ans convertis en jours).
  2. Si la date la plus ancienne + x jours> la dernière date de naissance, supprimez la dernière date de naissance et répétez l'étape (1), sinon passez à (3).
  3. Retour (date la plus ancienne + x jours)

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]

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

photos

DavidC
la source
De plus, vous n'avez pas besoin d'espace.
LegionMammal978
1

PowerShell, 145125 octets

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

Un défi assez délicat, mais relativement simple une fois compris.

Développé et commenté:

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

Exemple:

L'entrée doit contenir un tableau au format explicite de représentations chaîne-date. La sortie est au MM/DD/YYYYformat (par défaut pour la localisation en-us dans 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

Modifier - Golfé de 20 octets en modifiant la façon dont nous parcourons les anniversaires et en utilisant while au lieu de faire / jusqu'à

AdmBorkBork
la source
0

PHP, 220 octets

J'ai ajouté quelques nouvelles lignes pour la lisibilité.

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

Voici la version non golfée:

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');
    }
}
Trou noir
la source