Комбінований 100-річний день народження


26

Нещодавно я підсумовував віки себе і своєї дружини та дітей і зрозумів, що в певний момент у не надто віддаленому майбутньому наші віки складатимуться рівно до 100 років.

Виклик

Для введення даних, що складається з комбінованого (загального) віку та списку дат народження, виведіть дату, на яку всі комбіновані віки становлять усі ці дані.

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

Приклади

Тут я даю всі дати у форматі РРР / ММ / DD, але ви можете будь-якого формату, який вам подобається.

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? ;-)
Digital Trauma

Відповіді:


4

Mathematica 138 107 237 байт

Мої перші спроби були неохайними і недостойними. Це повинно діяти загалом за умови, що дати народження вказуються в найдавнішому порядку, як у тестових випадках.

Тестові справи були правильно підібрані і їх важко правильно виконати. Код виявився набагато довшим, ніж я сподівався.

Загальна логіка полягає в тому, щоб

  1. Вирішіть для x (в днях) таким чином, щоб відстань від x до кожної дати народження становила цільовий проміжок часу (наприклад, 100 років, перераховані в дні).
  2. Якщо найдавніша дата + х днів> остання дата народження, видаліть останню дату народження та повторіть крок (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}}]

фото


Крім того, вам не потрібно місця.
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 байтів, розміщених на базі 20, змінюючи те, як ми повторюємо дні народження та використовуючи функцію while замість того, щоб робити / поки


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');
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.