合并100岁生日


26

我最近将自己以及我的妻子和孩子的年龄相加,并意识到在不久的将来,我们的年龄总和将恰好达到100岁。

挑战

对于由合并的(总计)年龄和出生日期列表组成的输入,请输出所有合并年龄加起来等于给定总数的日期。

  1. 输入的合并年龄(以年为单位)将为正整数
  2. 输入的出生日期列表将是日期列表(无论哪种格式对您的语言来说都是方便的),日期列表必须包含日,月和年的数字表示形式。自特定纪元以来的天数,该数值不可接受。您可以假设输入日期列表按时间顺序排序。
  3. 输出将是单个日期,格式与输入日期相同
  4. 就合并年龄而言,一年即被视为365.25天
  5. 对于某些输入,将不可能找到所有出生日期之后的日期,如果它们都加起来等于合计年龄。例如,考虑两个相隔20年的出生日期,但我们希望相加10年。在这种情况下,输出将是较早出生日期的10岁生日。换句话说,对于该人的出生日期之前的所有日期,其年龄均为0
  6. 输出将是组合年龄加起来至少等于输入年龄的第一个日期
  7. 您可以使用内置的功能
  8. 您必须支持可追溯到1970/01/01的日期。

例子

在这里,我以YYYY / MM / 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。
Digital Trauma 2015年

5
规则7是五月规则。可以安全地忽略本月(以及下半年)。
马丁·恩德

实际上,我认为一个家庭会在每个生日时进行检查,将年份作为整数进行计数,而不是试图将天数相加(使问题复杂化为0.25)。
edc65 2015年

@ edc65谁让现实阻碍了良好的PPCG挑战?;-)
Digital Trauma

Answers:


4

数学138 107 237字节

我的第一次尝试是草率的,不值得的。只要在测试案例中按最早到最晚的顺序给出出生日期,这通常就可以正常工作。

测试用例选择精良,难以正确实施。结果比我期望的更长。

一般逻辑是

  1. 求解x(以天为单位),以使x到每个出生日期的距离等于目标时间(例如,将100年转换为天)。
  2. 如果最早的日期+ x天>最晚的出生日期,请删除最晚的出生日期并重复步骤(1),否则移至(3)。
  3. 返回(最早的日期+ x天)

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,145125字节

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格式(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

编辑-通过更改我们遍历生日的方式并使用while代替do / until来获得20个字节


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');
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.