Kết hợp sinh nhật 100 năm


26

Gần đây tôi đã thêm tuổi của bản thân và vợ con và nhận ra rằng đến một lúc nào đó trong tương lai không xa, tất cả các lứa tuổi của chúng ta sẽ có chính xác đến 100 năm.

Thử thách

Đối với đầu vào bao gồm tuổi kết hợp (tổng cộng) và danh sách ngày sinh, hãy xuất ngày mà tất cả các độ tuổi kết hợp cộng với tổng số đã cho.

  1. Tuổi kết hợp đầu vào (tính bằng năm) sẽ là số nguyên dương
  2. Danh sách đầu vào của ngày sinh sẽ là một danh sách (bất kỳ định dạng nào thuận tiện cho ngôn ngữ của bạn) của ngày phải chứa đại diện bằng số của Ngày, Tháng và Năm. Số ngày kể từ một kỷ nguyên cụ thể không được chấp nhận. Bạn có thể giả sử danh sách ngày đầu vào được sắp xếp theo thứ tự thời gian.
  3. Đầu ra sẽ là một ngày có cùng định dạng với ngày đầu vào
  4. Đối với mục đích của độ tuổi kết hợp, 1 năm được coi là chính xác 365,25 ngày
  5. Đối với một số đầu vào, sẽ không thể tìm thấy ngày sau tất cả các ngày sinh khi tất cả đều cộng với tuổi kết hợp. Chẳng hạn, hãy xem xét hai ngày sinh cách nhau 20 năm, nhưng chúng tôi muốn kết hợp 10 năm. Trong trường hợp đó, đầu ra sẽ là sinh nhật lần thứ 10 của ngày sinh cũ. Nói cách khác, độ tuổi cá nhân được coi là 0 cho tất cả các ngày trước ngày sinh của cá nhân đó
  6. Đầu ra sẽ là ngày đầu tiên mà độ tuổi kết hợp cộng với ít nhất là tuổi đầu vào
  7. Bạn có thể sử dụng hàm tích hợp
  8. Bạn phải hỗ trợ ngày trở lại cho đến ngày 1970/01/01.

Ví dụ

Ở đây tôi đang đưa ra tất cả các ngày ở định dạng YYYY / MM / DD, nhưng bạn có thể bất kỳ định dạng nào bạn thích.

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

Lưu ý rằng trong hai ví dụ gần nhất, ngày đầu ra nằm trong phạm vi ngày đầu vào, theo quy tắc 5.


1
@TimmyD. Quy tắc 7 là quy tắc có thể , vì vậy bạn không cần phải tuân theo quy tắc này nếu bạn không muốn. Tôi nghi ngờ các hàm thời gian ngày sẽ hữu ích cho việc phân tích ngày đầu vào và định dạng ngày đầu ra. YMMV.
Chấn thương kỹ thuật số

5
Quy tắc 7 là quy tắc tháng năm . Nó có thể được bỏ qua một cách an toàn trong tháng này (và trong nửa năm tới).
Martin Ender

Thực tế, tôi nghĩ rằng một gia đình sẽ kiểm tra vào mỗi sinh nhật, tính số năm là số nguyên và không cố gắng tổng hợp các ngày (với 0,25 để làm phức tạp vấn đề).
edc65

@ edc65 Ai đã từng để thực tế cản trở một thách thức PPCG tốt? ;-)
Chấn thương kỹ thuật số

Câu trả lời:


4

Toán học 138 107 237 byte

Những nỗ lực đầu tiên của tôi là cẩu thả và không xứng đáng. Điều này sẽ làm việc nói chung, với điều kiện là ngày sinh được đưa ra theo thứ tự sớm nhất đến muộn nhất, như trong các trường hợp thử nghiệm.

Các trường hợp thử nghiệm đã được lựa chọn tốt và khó thực hiện chính xác. Các mã hóa ra cách lâu hơn tôi đã hy vọng.

Logic chung là

  1. Giải quyết x (tính theo ngày) sao cho khoảng cách từ x đến mỗi ngày sinh tổng hợp đến thời gian trôi qua mục tiêu (ví dụ 100 năm được chuyển đổi thành ngày).
  2. Nếu ngày sớm nhất + x ngày> ngày sinh gần nhất, hãy xóa ngày sinh gần nhất và lặp lại bước (1), Khác chuyển sang (3).
  3. Trả lại (ngày sớm nhất + x ngày)

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]

Các trường hợp thử nghiệm

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

bức ảnh


Ngoài ra, bạn không cần không gian.
LegionMammal978

1

PowerShell, 145 125 byte

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

Thử thách khá khó khăn, nhưng tương đối đơn giản một khi đã hiểu.

Mở rộng và bình luận:

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

Thí dụ:

Đầu vào cần phải chứa một mảng được định dạng rõ ràng của các biểu diễn ngày chuỗi. Đầu ra có MM/DD/YYYYđịnh dạng (mặc định cho nội địa hóa en-us trong 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

Chỉnh sửa - Đánh gôn 20 byte bằng cách thay đổi cách chúng tôi lặp lại qua ngày sinh nhật và bằng cách sử dụng while thay vì làm / cho đến khi


0

PHP, 220 byte

Tôi đã thêm một số dòng mới để dễ đọc.

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

Đây là phiên bản chưa được chỉnh sửa:

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');
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.