Aniversário de 100 anos combinado

26

Recentemente, acrescentei as idades de mim e de minha esposa e filhos e percebi que, em algum momento de um futuro não muito distante, nossas idades somariam exatamente 100 anos.

Desafio

Para uma entrada que consiste em uma idade combinada (total) e uma lista de datas de nascimento, imprima a data na qual todas as idades combinadas somam o total determinado.

  1. A idade combinada de entrada (em anos) será um número inteiro positivo
  2. A lista de entrada de datas de nascimento será uma lista (qualquer formato conveniente para o seu idioma) de datas que devem conter representação numérica de dia, mês e ano. Número de dias desde que uma época específica não é aceitável. Você pode assumir que a lista de datas de entrada está classificada em ordem cronológica.
  3. A saída será uma única data no mesmo formato das datas de entrada
  4. Para os fins da idade combinada, considera-se 1 ano exatamente 365,25 dias
  5. Para algumas entradas, será impossível encontrar uma data após todas as datas de nascimento, quando todas elas somam a idade combinada. Por exemplo, considere duas datas de nascimento com 20 anos de diferença, mas queremos um total de 10 anos. Nesse caso, a saída seria o 10º aniversário da data de nascimento mais antiga. Em outras palavras, as idades individuais são consideradas 0 para todas as datas anteriores à data de nascimento dessa pessoa
  6. A saída será a primeira data em que as idades combinadas somam pelo menos a idade de entrada
  7. Você pode usar funções
  8. Você deve oferecer suporte a datas desde 1970/01/01.

Exemplos

Aqui estou fornecendo todas as datas no formato AAAA / MM / DD, mas você pode usar o formato que desejar.

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

Observe que nos dois últimos exemplos, a data de saída está dentro do intervalo de datas de entrada, conforme a regra 5.

Trauma Digital
fonte
1
@TimmyD. A regra 7 é uma regra de maio , então você não precisa segui-la se não quiser. Suspeito que funções de data e hora sejam úteis para analisar datas de entrada e formatar datas de saída. YMMV.
Digital Trauma
5
A regra 7 é uma regra de maio . Pode ser ignorado com segurança este mês (e no próximo semestre).
22815 Martin Ender13:
Realisticamente, acho que uma família verificaria a cada aniversário, contando anos como números inteiros e não tentando resumir os dias (com 0,25 para complicar a questão).
Edc65
@ edc65 Quem deixou a realidade atrapalhar um bom desafio de PPCG? ;-)
Digital Trauma

Respostas:

4

Mathematica 138 107 237 bytes

Minhas primeiras tentativas foram desleixadas e indignas. Isso deve funcionar geralmente, desde que as datas de nascimento sejam especificadas da ordem mais recente à mais recente, como nos casos de teste.

Os casos de teste foram bem escolhidos e difíceis de implementar corretamente. O código ficou muito mais longo do que eu esperava.

A lógica geral é

  1. Resolva para x (em dias) de modo que a distância de x a cada data de nascimento seja igual à passagem do tempo pretendida (por exemplo, 100 anos convertidos em dias).
  2. Se a data mais antiga + x dias> data de nascimento mais recente, remova a data de nascimento mais recente e repita a etapa (1), depois vá para (3).
  3. Retorno (data mais antiga + x dias)

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 teste

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
fonte
Além disso, você não precisa do espaço.
precisa
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

Desafio bastante complicado, mas relativamente simples uma vez entendido.

Expandido e 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

Exemplo:

A entrada precisa conter uma matriz explicitamente formatada de representações de data e sequência. A saída está no MM/DD/YYYYformato (padrão para localização en-us no 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 - Golpeou 20 bytes, alterando a forma como iteramos nos aniversários e usando while em vez de fazer / até

AdmBorkBork
fonte
0

PHP, 220 bytes

Eu adicionei algumas novas linhas para facilitar a leitura.

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

Aqui está a versão não destruída:

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');
    }
}
Blackhole
fonte