Совмещенный 100-летний день рождения

26

Недавно я суммировал возрасты себя, своей жены и детей и понял, что в какой-то момент в не слишком отдаленном будущем все наши возрасты составят ровно 100 лет.

Вызов

Для ввода, состоящего из комбинированного (общего) возраста и списка дат рождения, выведите дату, в которую все комбинированные возрасты суммируются с данной общей суммой.

  1. Входной комбинированный возраст (в годах) будет положительным целым числом
  2. Входной список дат рождения будет представлять собой список (в любом удобном для вашего языка формате) дат, который должен содержать числовое представление дня, месяца и года. Количество дней с определенной эпохи недопустимо. Вы можете предположить, что список введенных дат отсортирован в хронологическом порядке.
  3. На выходе будет одна дата в том же формате, что и даты ввода
  4. Для совокупного возраста 1 год считается ровно 365,25 днями.
  5. Для некоторых входных данных будет невозможно найти дату после всех дат рождения, когда все они в сумме составят общий возраст. Например, рассмотрим две даты рождения, которые разнесены на 20 лет, но мы хотим получить в совокупности 10 лет. В этом случае результатом будет 10-й день рождения с более старшей датой рождения. Другими словами, индивидуальный возраст считается равным 0 для всех дат до даты рождения этого человека.
  6. Выходными данными будет первая дата, в которую комбинированные возрасты составляют, по крайней мере, возраст ввода
  7. Вы можете использовать встроенные функции
  8. Вы должны поддержать даты, начиная с 1970/01/01.

Примеры

Здесь я даю все даты в формате ГГГГ / ММ / ДД, но вы можете использовать любой формат, который вам нравится.

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

Обратите внимание, что в последних двух примерах дата выхода находится в пределах диапазона дат ввода, согласно правилу 5.

Цифровая травма
источник
1
@TimmyD. Правило 7 является майским правилом, поэтому вам не нужно следовать ему, если вы не хотите. Я подозреваю, что функции даты и времени будут полезны для разбора входных дат и форматирования выходных дат. YMMV.
Цифровая травма
5
Правило 7 - это майское правило. Его можно смело игнорировать в этом месяце (и в течение следующего полугодия).
Мартин Эндер,
Реально, я думаю, что семья будет проверять каждый день рождения, считая годы как целые числа и не пытаясь суммировать дни (с 0,25, чтобы усложнить вопрос).
edc65
@ edc65 Кто когда-нибудь позволял реальности мешать хорошим вызовам PPCG? ;-)
Цифровая травма

Ответы:

4

Mathematica 138 107 237 байт

Мои первые попытки были неаккуратными и недостойными. Это должно работать, как правило, при условии, что даты рождения указаны в порядке от самого раннего до последнего, как в тестовых случаях.

Контрольные примеры были выбраны правильно и их трудно правильно реализовать. Код оказался намного длиннее, чем я надеялся.

Общая логика заключается в

  1. Решите для x (в днях) так, чтобы расстояние от x до каждой даты рождения суммировалось с целевым проходом времени (например, 100 лет, преобразованные в дни).
  2. Если самая ранняя дата + x дней> самая поздняя дата рождения, удалите самую позднюю дату рождения и повторите шаг (1), в противном случае перейдите к (3).
  3. Возврат (самая ранняя дата + х дней)

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]

Тестовые случаи

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

фото

DavidC
источник
Кроме того, вам не нужно место.
LegionMammal978
1

PowerShell, 145 125 байт

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

Довольно сложная задача, но однажды сравнительно понятная.

Расширено и прокомментировано:

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

Пример:

Входные данные должны содержать явно отформатированный массив представлений со строковой датой. Вывод в MM/DD/YYYYформате (по умолчанию для en-us локализации в 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

Редактировать - Гольф 20 байтов, изменив, как мы повторяем через дни рождения, и используя время вместо делать / до

AdmBorkBork
источник
0

PHP, 220 байт

Я добавил несколько строк для удобства чтения.

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

Вот негольфированная версия:

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');
    }
}
Черная дыра
источник