Ngày lễ tiếp theo


18

Người Úc thích các ngày lễ, và uống rượu. Hôm qua, ngày 26 tháng 1, là ngày của Úc, đó là một ngày lễ. Tôi rất vui vì không được làm việc ngày hôm qua, và háo hức muốn biết lần sau tôi được nghỉ lễ! Thật không may, tôi đã uống quá nhiều và tôi không thể tự mình giải quyết được.

Viết chương trình sẽ lấy một ngày theo ký hiệu ngày / giờ của Úc (dd / mm) làm đầu vào và xuất số lượng ngày cho đến ngày nghỉ lễ tiếp theo. Bởi vì tôi là cư dân Queensland (QLD), tôi chỉ quan tâm đến các ngày lễ ảnh hưởng đến người Queensland :

25/03 | Thứ sáu tốt lành
26/03 | Thứ bảy Phục sinh
28/03 | Thứ Hai Phục Sinh
25/04 | Ngày Anzac
02/05 | Ngày lao động
03/10 | Sinh nhật nữ hoàng
25/12 | Ngày giáng sinh
26/12 | Ngày Quyền anh
27/12 | Ngày lễ Giáng sinh

Lưu ý những điều sau từ trang web:

Ngày lễ Giáng sinh

Một ngày nghỉ lễ bổ sung sẽ được thêm vào khi Năm mới, Ngày Giáng sinh hoặc Ngày Quyền anh rơi vào cuối tuần.

Bởi vì ngày Giáng sinh là vào Chủ nhật, có thêm một ngày lễ. Ngày Giáng sinh vẫn là một ngày lễ.

Bởi vì tôi là một người buổi sáng, bạn nên bao gồm ngày hiện tại là một ngày (vì đó là thời gian có khả năng nhất tôi sẽ kiểm tra chương trình của bạn cho kỳ nghỉ lễ tiếp theo). Đó là, nếu ngày nghỉ lễ được nhập, đầu ra của bạn sẽ là 0; nếu một ngày trước khi một ngày nghỉ lễ được nhập vào, đầu ra của bạn sẽ là 1.

Tôi chỉ quan tâm đến những ngày từ nay đến 27/01) cho đến cuối năm. Ngày cuối cùng bạn cần tính đến là 31/12, nơi đầu ra của bạn sẽ là 1(cho ngày đầu năm mới).

Sơ hở tiêu chuẩn bị cấm.

Đầu vào

  • Đầu vào sẽ luôn có 5 ký tự: 4 chữ cái, được phân tách bằng dấu gạch nối -hoặc dấu gạch chéo/
  • Đầu vào sẽ chỉ là một ngày từ 27/01 đến 31/12

Đầu ra

  • Số ngày cho đến ngày nghỉ lễ tiếp theo ở Queensland Australia, bao gồm ngày đầu vào: nên là một số giữa 0153(khoảng cách dài nhất)
  • Không có dòng hoặc lỗi mới

Ví dụ

01-05 = 1  
02-05 = 0  
03-05 = 153  
25/12 = 0
26-12 = 0
27/12 = 0
30/12 = 2
31-12 = 1

Hy vọng điều này là rõ ràng và không có gì bị bỏ lỡ; tuy nhiên, đây là câu hỏi thứ hai của tôi vì vậy tôi sẽ đánh giá cao bất kỳ phản hồi nào và cố gắng hết sức để khắc phục sự cố càng sớm càng tốt.


@insertusernamehere Cảm ơn lời đề nghị tuyệt vời! Tôi đã thêm ngày vào câu hỏi
Tas

@ Bạn có chắc là những ngày đó là chính xác? Những cái trong ví dụ không khớp với trích dẫn và cả hai đều không khớp với trang web.
Adam Martin

@AdamMartin Cảm ơn bạn đã chỉ ra điều đó. Tôi đã đặt không chính xác trong những ngày tháng mười hai. Những người trong ví dụ chỉ là bất kỳ ngày nào, không cụ thể cho các ngày lễ. Chúng chỉ là ví dụ về ngày có thể được nhập và đầu ra phải là gì. Những người được trích dẫn nên (và hy vọng làm) phù hợp với những người từ trang web.
TAS

Bạn tổ chức sinh nhật Nữ hoàng vào tháng 10 ở Queensland? Điều đó thật kỳ lạ, nhưng dường như chính xác từ liên kết.
Cấp sông St

Ồ, các bạn không có ngày nghỉ nào từ tháng 6 đến hết tháng 9 phải không? Đó là thô.
Joe Z.

Câu trả lời:


2

Pyth , 98 84 62 67 byte

Cập nhật: Đã lưu 14 byte bằng cách rút ngắn danh sách đếm ngày trong tất cả 12 tháng để tính số ngày. Không tìm thấy một cách tốt để nén danh sách khác tho, vẫn đang cố gắng!

Update2: Đã lưu thêm 22 byte bằng cách mã hóa danh sách các số ngày dưới dạng chuỗi base256.

J30KhJ=Yc:z"\W"dd=N+s<[KtJKJKJKKJKJK)tseYshY-hfgTNCMc"UVXt{ĕŨũŪů"1N

Hãy thử trực tuyến!

Thuật toán tương tự như trong câu trả lời Python của tôi. Và không có nội dung nào để có được ngày trong năm, vì vậy tôi phải tự làm điều đó. Tạo 2 danh sách đó để tính toán trong ngày và cho những ngày nghỉ lễ khá tốn kém ... sẽ xem xét lại và thử tạo chúng theo ít byte hơn.


Nó dường như không thích đầu vào được phân tách bằng dấu gạch nối, nhưng nếu không thì thật tuyệt
TAS

@Tas Cảm ơn bạn đã gợi ý, đã đọc hết phần đó ... Đã sửa nó với chi phí thêm 5 byte. Có lẽ bạn nên thêm một số dấu gạch nối vào testcase, vì bạn muốn chúng bao gồm mọi biến thể đầu vào có thể.
Denker

5

Visual Basic cho Ứng dụng, 155 hoặc 118 byte

Phiên bản 1 - độc lập với miền địa phương, 155 byte

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-DateSerial(16,Val(Right(d,2)),Val(Left(d,2)))
If h>=0Goto 9
Next
9 End Function

Phiên bản 2 - phụ thuộc vào miền địa phương, 118 byte

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-CDate(d)
If h>=0Goto 9
Next
9 End Function

Số lượng byte là dành cho tệp .BAS cuối cùng, bao gồm các ký tự dòng. Đã chỉnh sửa bên ngoài trình soạn thảo VBA tiêu chuẩn (vì nó áp dụng các không gian bổ sung và hình thức dài dòng của một số từ khóa) - nhưng nhập và chạy trơn tru trên bất kỳ Ứng dụng Office nào (để kiểm tra loại, ví dụ như ? h("10/08")trong cửa sổ ngay lập tức hoặc trong Excel sử dụng trực tiếp trong công thức ô).

(EDITED) Ban đầu tôi chọn sử dụng DateSerialđể làm cho chức năng định vị an toàn (phiên bản 1). Khi tôi sống ở Brazil và do đó, hệ thống của tôi được cấu hình để sử dụng định dạng "dd / mm / yy" cho các ngày (giống như Úc), tôi có thể viết một phiên bản thậm chí nhỏ hơn bằng cách sử dụng CDatethay thế (phiên bản 2). CDatesử dụng thông tin ngôn ngữ hệ thống để chuyển đổi văn bản thành ngày. Tôi cũng giả định trong phiên bản này rằng mã sẽ chỉ được chạy trong năm 2016 (nếu năm bị bỏ qua (-6 byte) CDategiả định năm hiện tại theo đồng hồ hệ thống).

Số 42454 trên dòng thứ ba là tổng của 42450, là đại diện số của ngày 01/01/2016 trên VBA và 84 là ngày của năm cho kỳ nghỉ đầu tiên. Mảng chứa ngày trong năm cho mỗi ngày lễ (bao gồm cả ngày 01/01) được bù bằng -84 vì điều này làm mất đi một số chữ số. Sử dụng 16 thay vì năm 2016 DateSerialsẽ lấy đi thêm hai byte.

Tạo một mảng giống hệt nhau chín lần trong vòng lặp là mã "xấu", nhưng hoạt động và lưu thêm 3 byte (một cho tên mảng và một cho dấu bằng bên ngoài vòng lặp, và một lần nữa để tham chiếu mảng bên trong vòng lặp).

Không gian "thiếu" giữa 0 và từ khóa sau trên dòng thứ hai và thứ tư là không cần thiết vì chúng được giới thiệu lại tự động bởi VBE khi mô-đun được nhập. Được sử dụng lỗi thời nhưng giá rẻ byte If <...> Goto <linenumber>để thoát khỏi vòng lặp (cả hai If <...> Then Exit ForIf <...> Then Exit Functionsử dụng nhiều ký tự hơn).

Cũng lợi dụng thực tế là tên hàm trong VBA hoạt động như một biến cục bộ và giá trị của nó là tự động được trả về bởi hàm khi kết thúc thực thi.


Chào mừng đến với PPCG! Ở đây chúng tôi xác định ngôn ngữ lập trình bởi trình thông dịch, do đó, hoàn toàn chấp nhận được khi yêu cầu một ngôn ngữ nhất định.
lirtosiast

Cảm ơn! Chỉnh sửa để thêm một phiên bản phụ thuộc địa phương nhỏ hơn.
dnep

4

JavaScript (ES6), 131 128 byte

d=>[56,57,59,87,94,248,331,332,333,338].map(n=>r=r||(q=1454e9+n*864e5-new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`))>=0&&q/864e5,r=0)|r

Giải trình

Sử dụng hàm tạo tích hợp JavaScript Dateđể chuyển đổi chuỗi đầu vào thành một số mili giây kể từ epoch, sau đó so sánh số này với số mili giây cho mỗi ngày nghỉ lễ.

Nó thực hiện điều này bằng cách lưu trữ các ngày nghỉ lễ trong một mảng dưới dạng số ngày kể từ ngày tham chiếu. Tôi đã chọn 2016-01-29cho ngày tham chiếu vì số mili giây kể từ epoch có thể được cô đọng ngắn nhất cho ngày này. Bất kỳ số mili giây nào giữa ngày này và ngày tiếp theo đều hoạt động vì kết quả được làm tròn xuống và giữ số ở giữa để tránh hiệu ứng tiết kiệm ánh sáng ban ngày (mặc dù múi giờ của OP không tiết kiệm ánh sáng ban ngày). Số của ngày này là 1453986000000và làm tròn nó lên 1454000000000(thêm một vài giờ) có nghĩa là nó có thể được viết là 1454e9.

d=>
  [56,57,59,87,94,248,331,332,333,338]             // list of day offsets from 01/29
  .map(n=>                                         // for each public holiday offset n
    r=r||                                          // if r is already set, do nothing
      (q=                                          // q = approximate difference in ms
        1454e9+n*864e5                             // time of public holiday
        -new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`)    // time of input date
      )
      >=0&&                                        // if q >= 0
        q/864e5,                                   // r = q in days
    r=0                                            // r = result
  )
  |r                                               // floor and return r

Kiểm tra

Giải pháp này phụ thuộc vào múi giờ của người dùng. Điều này hoạt động trong múi giờ của OP (và của tôi) (GMT +1000). Nếu bạn muốn kiểm tra nó theo múi giờ khác, việc thêm numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000vào số ngày tham chiếu sẽ hoạt động. (ví dụ: GMT +0430 sẽ là -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)


Điều này luôn luôn cho 0 khi ngày được phân tách bằng dấu gạch nối. Tôi đã yêu cầu OP điều chỉnh các cặp thử nghiệm của mình, vì tất cả chúng đều có dấu gạch chéo là ngăn cách.
Denker

@DenkerAffe Ồ, tôi nghĩ rằng anh ta có nghĩa là chúng tôi được tự do chọn một dải phân cách. Ngẫu nhiên, làm cho nó phân tách-ambivalent đã tiết kiệm cho tôi 3 byte, cảm ơn!
dùng81655

1
Có vẻ như các quy tắc separated with a hyphen - or slash /là một chút mơ hồ. Đối với tôi điều đó có nghĩa là chúng tôi phải đối phó với cả hai, nhưng tôi chắc chắn có thể nhìn thấy phía bạn. Đoán OP nên làm rõ điều này.
Denker

3

T-SQL, 210 , 206 , 194 byte

(Bài đăng đầu tiên ở đây, Hy vọng điều này là ok, nhưng xin vui lòng :)

Đầu vào đi vào @i, phục vụ cho cả hai /-như là dấu phân cách. Tôi đang ở Úc, vì vậy định dạng ngày của tôi giống như @Tas

DECLARE @i CHAR(5)='23-09';DECLARE @c INT=DATEPART(dy,CAST(REPLACE(@i,'-','/')+'/2016' AS DATE))-1;SELECT MIN(b)-@c FROM(VALUES(84),(85),(87),(115),(122),(276),(359),(360),(361))a(b)WHERE b>=@c;

Cập nhật varchar để chartiết kiệm 3 byte cộng với xóa một khoảng trống :)

Cập nhật 2 khai báo @cvà gán mà không cần chọn


2

T-SQL, 296 byte

Được tạo như một hàm có giá trị bảng

create function d(@ char(5))returns table return select min(o)o from(select datediff(day,cast('2016'+right(@,2)+left(@,2)as date),cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1)o from(values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231))d(d))d where 0<=o

Được sử dụng theo cách sau

SELECT *
FROM (
    VALUES
        ('01/05') --= 1  
        ,('02/05') --= 0  
        ,('03/05') --= 153  
        ,('25/12') --= 0
        ,('26/12') --= 0
        ,('27/12') --= 0
        ,('30/12') --= 2
        ,('31/12') --= 1
    )testData(i)
    CROSS APPLY (
        SELECT * FROM d(t)
    ) out

i     o
----- -----------
01/05 1
02/05 0
03/05 153
25/12 0
26/12 0
27/12 0
30/12 2
31/12 1

(8 row(s) affected)

Một lời giải thích ngắn gọn

create function d(@ char(5)) returns table  -- function definition
return 
select min(o)o -- minimum set value
from(
    select datediff( -- date difference
        day, -- day units
        cast('2016'+right(@,2)+left(@,2)as date), -- convert input parameter to date
        cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1 -- convert int values into datetimes and add a day
        )o 
    from(
        values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231) -- integers representing the day before public holidays
        )d(d)
    )d 
where 0<=o -- only for values >= 0

2

JavaScript (ES6), 134 byte

x=>[0,1,3,31,38,192,275,276,277,282].find(z=>z>=(q=x[0]+x[1]- -[...'20212122121'].slice(0,x[3]+x[4]-1).reduce((a,b)=>+b+a+29,0)-85))-q

user81655 vẫn khiến tôi bị đánh bại bởi 3 byte, nhưng tôi không thể tìm thấy bất cứ nơi nào khác để vắt kiệt mọi thứ ở đây. Hoạt động bằng cách tính số ngày đã qua thay vì sử dụng Ngày, sau đó so sánh nó với một loạt các ngày nghỉ.


2

Python 2, 204 185 165 166 byte

Cập nhật: Đánh gôn xuống ~ 20 Byte bằng cách tính ngày trong năm. Không cần nhập khẩu lâu nữa :)

Cập nhật 2: Giảm thêm 20 byte bằng cách nhận ra rằng tôi có thể xử lý năm mới giống như ngày 367 và thực hiện một số điều chỉnh nhỏ khác.

def f(d):d=[d[:2],d[3:]];y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0]);return filter(lambda n:n>=y,[85,86,88,116,123,277,360,361,362,367])[0]-y

Hãy thử trực tuyến!

Ung dung:

def f(d):
    l=[85,86,88,116,123,277,360,361,362,367]
    d=[d[:2],d[3:]]
    y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0])
    f=filter(lambda n:n>=y,l)
    return f[0]-y

Hoạt động bằng cách lưu trữ số ngày nghỉ trong năm của một ngày trong danh sách, lọc ra những ngày trước ngày đã cho, lấy phần tử đầu tiên trong danh sách được lọc đó và trừ đi ngày của năm đã tính từ đầu vào.


1

PHP, 116 byte

Cách tiếp cận khá thẳng về phía trước. Nó lưu trữ các ngày trong năm cho các ngày lễ và bật chúng miễn là trong quá khứ. Cuối cùng, ngày yêu cầu trong năm được trừ đi.

for($x=[366,361,360,359,276,122,115,87,85,84];($a=date(z,strtotime($argv[1].'-2016')))>$t=array_pop($x););echo$t-$a;

Quá khứ tất cả các trường hợp thử nghiệm. Chạy từ dòng lệnh và chấp nhận đầu vào bằng dấu gạch nối, như:

$ php holidays.php "12-05"

1

ruby 1.9.3, 155 153 byte

Sau kỳ nghỉ lễ Giáng sinh, chúng tôi cần ngày siêu đặc biệt của chúng tôi! Trường hợp tương tự như @DenkerAffe.

require'date'
c=(Date.strptime(ARGV[0],'%d/%m')-Date.parse('01/01')).to_i
print [84,85,87,115,122,276,359,360,361,366].map{|i|(i-c)}.select{|i|i>=0}.min

Sử dụng:

$ ruby i_want_to_break_free.rb "03/05"

Tôi không biết nhiều về Ruby, nhưng tôi nghĩ bạn có thể tiết kiệm 3 Byte bằng cách xóa các khoảng trắng trong dòng 1 và 3. Ngoài ra, bạn nên chỉ định phương thức nhập nào bạn đang sử dụng, vì mã này không rõ ràng trong mã của bạn. Bạn có thể lưu một số byte bằng cách xác định hàm, do đó bạn có thể lấy đầu vào là argum và sử dụng giá trị trả về làm đầu ra.
Denker

@DenkerAffe Cảm ơn bạn rất nhiều! Tôi đã lưu 2 byte, nhưng tôi nghĩ một hàm sẽ tăng số lượng. Tôi đã cập nhật câu trả lời với một ví dụ sử dụng.
Tarod

0

05AB1E , 45 byte

•9JRt€ª´Q®Ië•368вDI„-/S¡`•Σ₁t•ºS₂+s<£O+©@Ïн®-

Nó có thể không còn là năm 2016 nữa, nhưng dù gì đi nữa ..;) Vẫn cho rằng năm đó là năm 2016 với mục đích là một năm nhuận với 29tháng Hai.

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

9JRt€ª´Q®Ië•  # Push compressed integer 10549819042671399072072399
  368в         # Converted to base-368 as list: [85,86,88,116,123,277,360,361,362,367]
      D        # Duplicate this list
I              # Take the input
 „-/S¡         # Split it on ["-","/"]
      `        # Push both integer separated to the stack
•Σ₁t          # Push compressed integer 5354545
     º         # Mirror it without overlap: 53545455454535
      S        # Converted to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
       ₂+      # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
         s     # Swap to get the month-integer
          <    # Decrease it by 1
           £   # Only leave the first month-1 values from the integer-list
            O  # Sum that sublist
             + # And add it to the day-integer (so we now have the N'th day of the year)
©              # Save this in the register (without popping)
 @             # Do a >= check with each integer in the first (duplicated) list we created
  Ï            # Only leave the truthy values from the list
   н           # Then pop this sublist and only leave its first value
    ®-         # And subtract the integer we saved in the register (N'th day of the year)
               # (after which the result is output implicitly)

Xem 05AB1E mẹo này của tôi (phần Làm thế nào để nén các số nguyên lớn?Làm thế nào để liệt kê số nguyên nén? ) Để hiểu tại sao •9JRt€ª´Q®Ië•10549819042671399072072399; •9JRt€ª´Q®Ië•368в[85,86,88,116,123,277,360,361,362,367]; và •Σ₁t•5354545.

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.