Cumpleaños combinado de 100 años

26

Recientemente estaba sumando las edades de mí y mi esposa e hijos y me di cuenta de que en algún momento en un futuro no muy lejano, nuestras edades sumarán exactamente 100 años.

Reto

Para una entrada que consta de una edad combinada (total) y una lista de fechas de nacimiento, indique la fecha en que las edades combinadas se suman al total dado.

  1. La edad combinada de entrada (en años) será un número entero positivo
  2. La lista de entrada de fechas de nacimiento será una lista (cualquier formato que sea conveniente para su idioma) de fechas que deben contener una representación numérica de Día, Mes y Año. Número de días desde que una época específica no es aceptable. Puede suponer que la lista de fechas de entrada está ordenada en orden cronológico.
  3. La salida será una sola fecha en el mismo formato que las fechas de entrada
  4. A los efectos de la edad combinada, 1 año se considera exactamente 365,25 días.
  5. Para algunas entradas, será imposible encontrar una fecha después de todas las fechas de nacimiento cuando todas sumen la edad combinada. Por ejemplo, considere dos fechas de nacimiento separadas por 20 años, pero queremos una combinación de 10 años. En ese caso, la salida sería el décimo cumpleaños de la fecha de nacimiento más antigua. En otras palabras, las edades individuales se consideran 0 para todas las fechas anteriores a la fecha de nacimiento de ese individuo.
  6. La salida será la primera fecha en que las edades combinadas sumen al menos la edad de entrada
  7. Puede usar funciones integradas de
  8. Debe admitir fechas que se remontan a 1970/01/01.

Ejemplos

Aquí estoy dando todas las fechas en formato AAAA / MM / DD, pero puede elegir el formato que desee.

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

Tenga en cuenta que en los últimos dos ejemplos, la fecha de salida se encuentra dentro del rango de fechas de entrada, según la regla 5.

Trauma digital
fuente
1
@TimmyD. La regla 7 es una regla de mayo , por lo que no tiene que seguirla si no lo desea. Sospecho que las funciones de fecha y hora serán útiles para analizar las fechas de entrada y formatear las fechas de salida. YMMV.
Trauma digital
55
La regla 7 es una regla de mayo . Se puede ignorar con seguridad este mes (y para el próximo medio año).
Martin Ender
Siendo realistas, creo que una familia verificaría en cada cumpleaños, contando los años como enteros y no tratando de resumir los días (con 0.25 para complicar las cosas).
edc65
@ edc65 ¿Quién dejó que la realidad se interpusiera en un buen desafío PPCG? ;-)
Trauma digital

Respuestas:

4

Mathematica 138107 237 bytes

Mis primeros intentos fueron descuidados e indignos. Esto debería funcionar en general, siempre que las fechas de nacimiento se den en orden de más temprano a más reciente, como en los casos de prueba.

Los casos de prueba fueron bien elegidos y difíciles de implementar correctamente. El código resultó mucho más largo de lo que esperaba.

La lógica general es

  1. Resuelva para x (en días) de modo que la distancia desde x hasta cada fecha de nacimiento sume al paso del tiempo objetivo (por ejemplo, 100 años convertidos en días).
  2. Si la fecha más temprana + x días> última fecha de nacimiento, elimine la última fecha de nacimiento y repita el paso (1), de lo contrario, vaya a (3).
  3. Retorno (fecha más temprana + x días)

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]

Casos de prueba

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

fotos

DavidC
fuente
Además, no necesitas el espacio.
LegionMammal978
1

PowerShell, 145125 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

Desafío bastante complicado, pero relativamente sencillo una vez entendido.

Ampliado y comentado:

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

Ejemplo:

La entrada debe contener una matriz formateada explícitamente de representaciones de fecha de cadena. La salida está en MM/DD/YYYYformato (predeterminado para la localización en-us en 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

Editar: jugó 20 bytes cambiando la forma en que iteramos a través de los cumpleaños y usando while en lugar de do / hasta

AdmBorkBork
fuente
0

PHP, 220 bytes

He agregado algunas líneas nuevas para facilitar la lectura.

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

Aquí está la versión sin golf:

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');
    }
}
Agujero negro
fuente