Kalender Rollover

17

Ini terinspirasi oleh salah satu pertanyaan Downgoat di Sandbox, di mana saya menyarankan agar dia memasukkan 31 April sebagai hari Pi untuk orang yang menggunakan format hari / bulan, hanya agar dia memberi tahu saya bahwa tidak ada 31 April!

Diberikan string tanggal dalam format bulan / hari yang mungkin tidak valid, tampilkan tanggal yang benar menggunakan rollover. (Rollover pertama bulan, lalu rollover hari).

Contoh:

"15/43" - Ini berbunyi sebagai hari ke 43 di bulan ke 15. Pertama, kami memutar bulan ke tahun berikutnya, jadi kami berakhir dengan 3 (Maret). Sekarang, sejak Maret hanya memiliki 31 hari, kami memperpanjang hari ekstra menjadi April, jadi kami menampilkan tanggal aktual sebagai "4/12" (12 April).

"3/16" - Ini adalah tanggal yang valid (16 Maret). Kembalikan apa adanya.

"12/64" - Ah, begitu banyak kenangan indah dari 64 Desember ... Desember 31 hari, Januari 31 hari, jadi yang saya maksud sebenarnya adalah "2/2" (2 Februari).

"19/99" - Pertama, 19 menjadi 7 (Juli). Juli memiliki 31 hari, Agustus memiliki 31 hari, September memiliki 30 hari, sehingga hasilnya adalah "10/7" (7 Oktober).

"1/99999" - Setahun memiliki 365 hari. 99999 (mod 365) = 354. Hari 354 tahun ini adalah "12/20" .

"9999999/10" - Rupanya, 9999999 (mod 12) = 3, jadi ini "3/10" (10 Maret).

Kriteria:

Bulan input adalah bilangan bulat> 0. Hari input adalah bilangan bulat> 0. Tahun tidak perlu ditentukan, karena itu tidak ada tahun kabisat untuk menangani.

Memperbarui:

Karena saya pikir itu akan terlalu menyederhanakan tantangan, fungsi kalender, seperti yang ada di kelas Kalender Java , dilarang. Fungsi parsing / pemformatan tanggal masih diizinkan.

geokavel
sumber
1
Terkait
kucing
1
Kasus uji penting lainnya adalah kasus dengan hari yang cukup untuk bergulir lebih dari 8 tahun, sehingga jawaban yang menggunakan built-in harus memperhatikan yang built-in menggunakan tahun kabisat.
Martin Ender
Oh, itu jawaban yang ... Saya baru saja memposting jawaban Mathematica yang menggunakan built-in. : /
Martin Ender
@ Martin Maaf tentang itu;).
geokavel
Untuk referensi, solusi Mathematica masih panjang 90 byte (meskipun itu secara besar-besaran didominasi oleh pemrosesan string). Jika Anda ingin menambahkan test case seperti itu,1/99999 sebaiknya 12/19saya hasilkan .
Martin Ender

Jawaban:

11

LabVIEW, 32 LabVIEW Primitif

Eumel
sumber
Itu tadi cepat.
Addison Crump
Bisakah Anda meyakinkan saya bahwa tidak ada fungsi kalender yang digunakan di sini?
geokavel
Hal yang baik tentang LabVIEW adalah pada dasarnya seperti apa kelihatannya. Hal pertama yang memindai angka dari modul 2 string, kotak adalah struktur sakelar kasus yang menghasilkan 28,30 atau 31 dan kemudian disatukan sebagai string lagi.
Eumel
4

C #, 269 223

string v(string n){var x=new[]{31,28,31,30,31,30,31,31,30,31,30,31};var s=n.Split('/');Func<string,int> p=int.Parse;var m=p(s[0]);var d=p(s[1]);m=m>=12?m%12:m;while(d>x[m]){d-=x[m];m=++m>=12?m%12:m;}return(m==0?1:m)+"/"+d;}

Sunting : Tetap bekerja untuk kasus-kasus seperti 24/1, 36/1, dll. Dan sedikit bermain golf. Terima kasih atas komentarnya, ada beberapa tempat yang saya simpan sedikit!

Tidak Disatukan:

string v(string n)
{
    var x = new [] { 31 ,28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31 };

    var s = n.Split('/');
    Func<string,int> p = int.Parse;
    var m = p(s[0]);
    var d = p(s[1]);
    m = m >= 12 ? m % 12 : m;
    while (d > x[m])
    {
        d -= x[m];
        m = ++m >= 12 ? m % 12 : m;
    }
    return (m==0?1:m) + "/" + d;
}
DrewJordan
sumber
Pertama-tama: Selamat datang di komunitas! Saya kira Anda bisa menyimpan beberapa Bytes dengan menetapkan kamus dalam satu lingkaran atau menggunakan fungsi sakelar (tidak ada C # pro di sini). Juga secara langsung mencetak ´m + "/" + d´ mungkin membantu sedikit. Dan yang terakhir (ini mungkin atau mungkin tidak berhasil) menggunakan char * bukannya string dalam argumen.
Eumel
Ini gagal pada kasus uji tertentu, misalnya 24/1.
LegionMammal978
@Eumel, terima kasih! Langsung menggunakan pencetakan Console.Writeyang lebih dari return, dan dalam C # saya akan gunakan char[]sebagai pengganti string, tetapi jumlah karakter yang sama, dan membuat pemisahan pada yang /lebih bermasalah. Tapi, catatan Anda tentang Kamus memang menuntun saya ke versi yang jauh lebih baik!
DrewJordan
4

R, 208 182 byte

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/");n=(e[1]/12-1)*12;if(!n%%12)n=12;if(n<0)n=e[1];j=e[2];while((j<-j-m[n])>0){n=n+1;if(n>12)n=1};j=m[n]+j;cat(n,j,sep="/")

Dapatkan bulan dengan membaginya dengan 12, lalu lilitkan, hapus jumlah hari pada bulan ini sampai Anda mendapatkan angka negatif., Balikkan langkah terakhir dan cetak.

Pada banyak baris (perlu menggunakan file dan sumbernya):

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/")
n=(e[1]/12-1)*12
if(!n%%12)n=12
if(n<0)n=e[1]
j=e[2]
while((j<-j-m[n])>0){n=n+1;if(n>12)n=1}
j=m[n]+j;cat(n,j,sep="/")
Tensibai
sumber
Ini adalah pesan yang saya dapatkan ketika mencoba menjalankan program Anda di R: pastebin.com/dPh1n64a
geokavel
Aneh, aku akan periksa kembali nanti
Tensibai
Saya juga mendapat pesan ini. Program Anda tampaknya memiliki masalah dengan beberapa bulan. Kalau tidak, itu sedang berjalan. pastebin.com/g3BCUDi8
geokavel
Terima kasih untuk umpan baliknya. Sebenarnya saya sedang dalam perjalanan, saya akan memperbaikinya
Tensibai
1
@Tensibai ya Anda benar, salah saya (saya seharusnya ingat bahwa pesan kesalahan mengatakan bahwa ia mengharapkan "nyata").
plannapus
3

PHP> = 5.5, 181 byte

list($m,$d)=explode("/",$argv[1]);$m%=12;$d%=365;$i=0;while($d>100)$d-=[31,28,31,30,31,30,31,31,30,31,30,31][$i++];$m+=$i;echo date_create_from_format("m/d","$m/$d")->format("n/j");

PHP hampir mendukung rollover dengan instruksi penguraian tanggal dan format saja. Sebagai contoh:

echo date_create_from_format("m/d","12/64")->format("n/j"); // Output: 2/2

Namun, begitu salah satu angka menjadi lebih besar dari 100, PHP menolak mem-parsing dan mengembalikan kesalahan (mungkin karena alasan sewenang-wenang). Jadi, teori dengan jawaban ini adalah mengembalikannya ke tempat PHP akan menguraikannya, lalu mengirimkannya ke date_create_from_format().

Tidak Disatukan:

list($month, $day) = explode("/", $argv[1]);
$month = $month % 12;
$day = $day % 365;
$i = 0;
$days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
while($day > 31) $day -= $days[$i++];
$month += $i;
echo DateTime::createFromFormat("m/d", $month . "/" . $day)->format("n/j");

Cobalah online

nickb
sumber
1
Anda perlu memberi saya cara untuk memasukkan string tanggal, atau menjadikannya fungsi.
geokavel
Parameter GET tidak dapat diterima sebagai metode input dalam PHP . Anda harus menjadikan fungsi ini dan meneruskan input sebagai parameter fungsi, atau mendapatkan input dari $argvatau STDIN.
Mego
@Mego jeeze, memberi saya beberapa waktu untuk memperbarui jawaban saya karena OP tidak menyatakan persyaratan untuk input - itu cukup sederhana untuk perubahan $tke $argv[1]dan sekarang dibaca dari masukan baris perintah.
julukan
OP yang menyatakan persyaratan untuk input tidak relevan; kami memiliki daftar metode I / O standar yang dapat diterima (yang saya tautkan) sehingga penulis tantangan tidak harus menentukannya pada setiap tantangan.
Mego
2

JavaScript (ES6), 106 byte

s=>eval('q="030101001010";p=s.split`/`;for(d=i=p[1],m=p[0]-1;i--;d>n&&(m++,d-=n))n=31-q[m%=12];m+1+"/"+d')

Penjelasan

s=>
  eval(`              // use eval to enable for loop without needing to write {} or return
    q="030101001010"; // q = array of 31 - days in each month
    p=s.split\`/\`;   // p = array of [ month, day ]
    for(
      d=i=p[1],       // d = day
        m=p[0]-1;     // m = month - 1
      i--;            // loop for each day, this is more iterations than needed but extra
                      //     iterations do not affect the result and it's the shortest way
                      //     to guarantee all months have been subtracted from d, it also
                      //     ensures the loop runs at least once to get m % 12
      d>n&&(m++,d-=n) // if too many days, subtract the month's days and increment month
    )
      n=31-q[m%=12];  // n = number of days in month, get m % 12
    m+1+"/"+d         // return the result
  `)

Uji

pengguna81655
sumber
1

Jawaban yang tidak bersaing - Bash + coreutils, 55

date -d1-$[(${1%/*}-1)%12+1]-1+$[${1#*/}-1]day +%-m/%-d

"Fungsi parsing / pemformatan tanggal masih diizinkan" - Saya menganggap ini berarti dateutilitas diizinkan.

Input dibaca dari baris perintah, misalnya:

$ ./rollovercal.sh 15/43
4/12
$ 

Ini tidak bersaing karena perintah tanggal diperluas ke sesuatu seperti ini yang menambahkan beberapa hari:

date -d1-3-1+42day +%-m/%-d
Trauma Digital
sumber
Ini diizinkan selama tidak melakukan apa pun seperti date.add(875)menambah tanggal 875 hari. Itu sebagian besar yang saya cari.
geokavel
@geokavel oh, begitu. datePerintah yang diperluas sepenuhnya di sini adalah date -d1-3-1+42day +%-m/%-d, jadi melakukan hal itu. Saya kira ini adalah jawaban yang tidak bersaing maka :(
Digital Trauma