Lịch Rollover


17

Điều này được lấy cảm hứng từ một trong những câu hỏi của Downgoat trong Sandbox, nơi tôi đề nghị anh ấy đưa ngày 31 tháng 4 là ngày Pi cho những người sử dụng định dạng ngày / tháng, chỉ để anh ấy thông báo cho tôi rằng không có ngày 31 tháng 4!

Đưa ra một chuỗi ngày ở định dạng tháng / ngày có thể không hợp lệ, hãy xuất ngày chính xác bằng cách sử dụng cuộn qua. (Đầu tiên cuộn qua tháng, sau đó cuộn qua ngày).

Ví dụ:

"15/43" - Đây là ngày thứ 43 của tháng thứ 15. Đầu tiên, chúng tôi lăn qua tháng này sang năm tiếp theo, vì vậy chúng tôi kết thúc với 3 (tháng 3). Bây giờ, kể từ tháng 3 chỉ có 31 ngày, chúng tôi tái đầu tư các ngày thêm vào tháng 4, vì vậy chúng tôi đưa ra ngày thực tế là "4/12" (ngày 12 tháng 4).

"3/16" - Đây là một ngày hợp lệ (ngày 16 tháng 3). Trả lại nó như là.

"12/64" - Ah, rất nhiều kỷ niệm đẹp từ ngày 64 tháng 12 ... Tháng 12 có 31 ngày, tháng 1 có 31 ngày, vì vậy điều tôi thực sự muốn nói là "2/2" (ngày 2 tháng 2).

"19/99" - Đầu tiên, ngày 19 trở thành ngày 7 (tháng 7). Tháng 7 có 31 ngày, tháng 8 có 31 ngày, tháng 9 có 30 ngày, do đó, sản lượng là "10/7" (ngày 7 tháng 10).

"1/99999" - Một năm có 365 ngày. 99999 (mod 365) = 354. Ngày 354 trong năm là "12/20" .

"9999999/10" - Rõ ràng, 9999999 (mod 12) = 3, vì vậy đây là "3/10" (ngày 10 tháng 3).

Tiêu chí:

Tháng đầu vào là một số nguyên> 0. Ngày đầu vào là một số nguyên> 0. Năm không bao giờ cần được chỉ định, do đó không có năm nhuận để xử lý.

Cập nhật:

Theo tôi nghĩ, nó sẽ đơn giản hóa quá mức thách thức, các hàm lịch, chẳng hạn như các hàm trong lớp Lịch Java , bị cấm. Chức năng phân tích cú pháp / định dạng ngày vẫn được cho phép.



1
Một trường hợp thử nghiệm quan trọng khác sẽ là một trường hợp có đủ số ngày để kéo dài hơn 8 năm, như vậy các câu trả lời sử dụng tích hợp phải chú ý đến những phần tử tích hợp sử dụng năm nhuận.
Martin Ender

Ồ, đó là câu trả lời mà ... Tôi vừa định đăng một câu trả lời Mathicala sử dụng tích hợp sẵn. : /
Martin Ender

@Martin Xin lỗi về điều đó;).
geokavel

Để tham khảo, giải pháp Mathicala vẫn dài 90 byte (mặc dù điều đó bị chi phối ồ ạt bởi quá trình xử lý chuỗi). Nếu bạn muốn thêm một trường hợp thử nghiệm như vậy, tôi nghĩ 1/99999nên mang lại 12/19.
Martin Ender

Câu trả lời:


11

Nó thật nhanh.
Addison Crump

Bạn có thể đảm bảo với tôi không có chức năng lịch được sử dụng ở đây?
geokavel

Điểm hay của LabVIEW là về cơ bản nó trông như thế nào. Điều đầu tiên quét các số từ một mô-đun 2 chuỗi, hộp là một cấu trúc trường hợp chuyển đổi đưa ra 28,30 hoặc 31 và sau đó nó được ghép lại thành một chuỗi.
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;}

Biên tập : Đã để hoạt động cho các trường hợp như 24/1, 36/1, v.v. và chơi golf một chút. Cảm ơn các ý kiến, có một số nơi tôi đã lưu một chút!

Ung dung:

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

Trước hết: Chào mừng đến với cộng đồng! Tôi đoán bạn có thể lưu một số Byte bằng cách gán từ điển trong một vòng lặp hoặc sử dụng chức năng chuyển đổi (mặc dù không có C # pro ở đây). Ngoài ra, in trực tiếp ônm + "/" + d trọng có thể giúp một chút. Và cuối cùng (điều này có thể hoặc có thể không hoạt động) bằng cách sử dụng char * thay vì chuỗi trong các đối số.
Eumel

Điều này thất bại trong các trường hợp thử nghiệm nhất định, ví dụ 24/1.
LegionMammal978

@Eumel cảm ơn! In trực tiếp sử dụng Console.Writenhiều hơn returnvà trong C # tôi sẽ sử dụng char[]để thay thế string, nhưng nó có cùng số lượng ký tự và khiến việc phân tách /trở nên khó khăn hơn. Nhưng, ghi chú của bạn trên Từ điển đã đưa tôi đến một phiên bản tốt hơn!
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="/")

Nhận tháng bằng cách chia cho 12, sau đó lặp lại, xóa số ngày của tháng hiện tại cho đến khi bạn nhận được số âm., Đảo ngược bước cuối cùng và in.

Trên nhiều dòng (cần sử dụng tệp và nguồn):

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="/")

Đây là thông điệp tôi nhận được khi cố gắng chạy chương trình của bạn trong R: pastebin.com/dPh1n64a
geokavel

Lạ tôi sẽ kiểm tra lại sau
Tensibai

Tôi cũng nhận được tin nhắn này. Chương trình của bạn dường như có vấn đề với một số tháng. Nếu không thì nó đang chạy. pastebin.com/g3BCUDi8
geokavel

Cảm ơn vì bạn đã phản hồi. Tôi thực sự đang trên đường, tôi sẽ sửa nó
Tensibai

1
@Tensibai vâng, bạn đúng, xấu của tôi (tôi nên nhớ rằng thông báo lỗi nói rằng nó mong đợi "có thật").
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 gần như chỉ hỗ trợ cuộn qua với các hướng dẫn phân tích cú pháp và định dạng ngày. Ví dụ:

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

Tuy nhiên, một khi một trong hai số lớn hơn 100, PHP sẽ từ chối phân tích cú pháp và trả về một lỗi (có thể vì một số lý do tùy ý). Vì vậy, lý thuyết với câu trả lời này là đưa nó trở lại nơi PHP sẽ phân tích cú pháp, sau đó gửi nó tớidate_create_from_format() .

Ung dung:

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");

Dùng thử trực tuyến


1
Bạn cần cho tôi một cách để nhập chuỗi ngày hoặc làm cho nó thành một hàm.
geokavel

Các tham số GET không được chấp nhận như một phương thức nhập liệu trong PHP . Bạn sẽ cần phải biến nó thành một hàm và truyền đầu vào dưới dạng tham số hàm hoặc lấy đầu vào từ $argvhoặc STDIN.
Mego

@Mego Jeeze, cho tôi một chút thời gian để cập nhật câu trả lời của tôi kể từ khi OP không nêu bất cứ yêu cầu đầu vào - nó đủ đơn giản để thay đổi $tđể $argv[1]và bây giờ nó đọc từ đầu vào dòng lệnh.
nickb

Các yêu cầu của OP cho đầu vào là không liên quan; chúng tôi có một danh sách các phương thức I / O mặc định được chấp nhận (mà tôi đã liên kết) để các tác giả thách thức không phải chỉ định chúng cho mọi thử thách.
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')

Giải trình

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
  `)

Kiểm tra


1

Câu trả lời không cạnh tranh - Bash + coreutils, 55

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

"Mặc dù chức năng phân tích cú pháp / định dạng vẫn được cho phép" - Tôi cho rằng điều này có nghĩa làdate tiện ích được cho phép.

Đầu vào được đọc từ dòng lệnh, ví dụ:

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

Điều này không cạnh tranh vì lệnh date mở rộng thành một thứ như thế này đang thêm một số ngày:

date -d1-3-1+42day +%-m/%-d

Nó được cho phép miễn là nó không làm bất cứ điều gì muốn date.add(875)tăng ngày thêm 875 ngày. Đó chủ yếu là những gì tôi sẽ theo đuổi.
geokavel

@geokavel oh, tôi hiểu rồi. Lệnh được mở rộng hoàn toàn dateở đây là date -d1-3-1+42day +%-m/%-d, vì vậy nó thực hiện chính xác điều đó. Tôi đoán đây là một câu trả lời không cạnh tranh sau đó :(
Digital Trauma
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.