Ulang tahun gabungan 100 tahun

26

Saya baru-baru ini menambahkan usia saya dan istri saya dan anak-anak dan menyadari bahwa pada suatu titik di masa depan yang tidak terlalu jauh usia kita semua akan bertambah hingga tepat 100 tahun.

Tantangan

Untuk input yang terdiri dari gabungan usia (total) dan daftar tanggal lahir, cantumkan tanggal di mana semua umur gabungan ditambahkan hingga total yang diberikan.

  1. Input gabungan usia (dalam tahun) akan menjadi bilangan bulat positif
  2. Daftar input tanggal lahir akan menjadi daftar (format apa pun yang sesuai untuk bahasa Anda) dari tanggal yang harus mengandung representasi numerik dari Hari, Bulan dan Tahun. Jumlah hari sejak zaman tertentu tidak dapat diterima. Anda dapat mengasumsikan daftar tanggal input diurutkan dalam urutan kronologis.
  3. Output akan berupa satu tanggal dalam format yang sama dengan tanggal input
  4. Untuk keperluan usia gabungan, 1 tahun dianggap tepat 365,25 hari
  5. Untuk beberapa input, tidak mungkin untuk menemukan tanggal setelah semua tanggal lahir ketika mereka semua menambahkan hingga usia gabungan. Sebagai contoh, pertimbangkan dua tanggal lahir yang terpisah 20 tahun, tetapi kami ingin gabungan 10 tahun. Dalam hal ini, hasilnya adalah ulang tahun ke 10 dari tanggal lahir yang lebih tua. Dengan kata lain, usia individu dianggap 0 untuk semua tanggal sebelum tanggal lahir individu itu
  6. Output akan menjadi tanggal pertama di mana usia gabungan ditambahkan hingga setidaknya usia input
  7. Anda dapat menggunakan fungsi bawaan
  8. Anda harus mendukung tanggal sejak 1970/01/01.

Contohnya

Di sini saya memberikan semua tanggal dalam format YYYY / MM / DD, tetapi Anda dapat memformat apa pun yang Anda suka.

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

Perhatikan bahwa dalam dua contoh terakhir, tanggal keluaran terletak dalam kisaran tanggal input, sesuai aturan 5.

Trauma Digital
sumber
1
@TimmyD. Aturan 7 adalah aturan may , jadi Anda tidak harus mengikutinya jika tidak mau. Saya menduga fungsi tanggal-waktu akan berguna untuk menguraikan tanggal input dan memformat tanggal output. YMMV.
Digital Trauma
5
Aturan 7 adalah aturan Mei . Itu dapat diabaikan dengan aman bulan ini (dan untuk setengah tahun ke depan).
Martin Ender
Secara realistis, saya pikir sebuah keluarga akan memeriksa setiap ulang tahun, menghitung tahun sebagai bilangan bulat dan tidak mencoba meringkas hari-hari (dengan 0,25 untuk memperumit masalah).
edc65
@ edc65 Siapa yang pernah membiarkan kenyataan menghalangi tantangan PPCG yang bagus? ;-)
Trauma Digital

Jawaban:

4

Mathematica 138 107 237 byte

Upaya pertama saya ceroboh dan tidak layak. Ini harus bekerja secara umum, asalkan tanggal lahir diberikan dalam urutan paling awal hingga terbaru, seperti dalam kasus-kasus tes.

Kasus uji dipilih dengan baik dan sulit diimplementasikan dengan benar. Kode ternyata jauh lebih lama dari yang saya harapkan.

Logikanya umum adalah untuk

  1. Memecahkan untuk x (dalam hari) sehingga jarak dari x ke setiap tanggal lahir sama dengan target waktu (misalnya 100 tahun dikonversi menjadi hari).
  2. Jika tanggal paling awal + x hari> tanggal lahir terakhir, hapus tanggal lahir terakhir dan ulangi langkah (1), Pindah ke (3).
  3. Return (tanggal paling awal + x hari)

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]

Uji Kasus

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

foto

DavidC
sumber
Juga, Anda tidak membutuhkan ruang.
LegionMammal978
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

Tantangan yang cukup rumit, tetapi relatif mudah dipahami.

Diperluas dan Dikomentari:

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

Contoh:

Input perlu mengandung array yang diformat secara eksplisit dari representasi string-date. Output dalam MM/DD/YYYYformat (default untuk lokalisasi en-us di 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

Sunting - Memotong 20 byte dengan mengubah cara kita mengulangi ulang tahun, dan dengan menggunakan saat alih-alih melakukan / sampai

AdmBorkBork
sumber
0

PHP, 220 byte

Saya telah menambahkan beberapa baris baru untuk keterbacaan.

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

Ini adalah versi yang tidak dikoleksi:

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');
    }
}
Lubang hitam
sumber