Libur umum berikutnya

18

Orang Australia suka hari libur nasional, dan minum. Kemarin, 26 Januari, adalah hari Australia, yang merupakan hari libur umum. Saya senang tidak berada di tempat kerja kemarin, dan ingin tahu kapan saya mendapat libur umum! Sayangnya, saya terlalu banyak minum, dan saya tidak bisa mengatasinya sendiri.

Tulis program yang akan memasukkan tanggal dalam notasi tanggal / waktu Australia (dd / mm) sebagai input, dan tampilkan jumlah hari hingga hari libur umum berikutnya. Karena saya seorang penduduk Queensland (QLD), saya hanya tertarik pada hari libur nasional yang memengaruhi warga Queensland :

25/03 | Jumat Agung
26/03 | Sabtu Paskah
28/03 | Senin Paskah
25/04 | Hari Anzac
02/05 | Hari Buruh
03/10 | Ulang Tahun Ratu
25/12 | Hari Natal
26/12 | Boxing Day
27/12 | Liburan Hari Natal

Perhatikan hal berikut dari situs:

Liburan Hari Natal

Hari libur umum tambahan akan ditambahkan ketika Hari Tahun Baru, Hari Natal atau Boxing Day jatuh pada akhir pekan.

Karena hari Natal adalah pada hari Minggu, ada hari libur umum tambahan . Hari Natal masih menjadi hari libur umum.

Karena saya orang pagi, Anda harus memasukkan tanggal saat ini sebagai hari (karena itu kemungkinan besar saya akan memeriksa program Anda untuk hari libur umum berikutnya). Artinya, jika tanggal hari libur nasional dimasukkan, output Anda seharusnya 0; jika hari sebelum hari libur dimasukkan, output Anda akan menjadi 1.

Saya hanya tertarik pada tanggal antara sekarang (tanggal 27/01) hingga akhir tahun. Tanggal akhir yang harus Anda pertanggungjawabkan adalah 31/12 di mana output Anda akan berada 1(untuk hari Tahun Baru).

Celah standar dilarang.

Memasukkan

  • Input akan selalu 5 karakter: 4 huruf, dipisahkan dengan tanda hubung -atau garis miring/
  • Input hanya akan berupa tanggal antara 27/01 dan 31/12

Keluaran

  • Jumlah hari sampai hari libur umum berikutnya di Queensland Australia, termasuk tanggal input: harus berupa angka antara 0dan 153(jeda terpanjang)
  • Tidak ada baris atau kesalahan baru

Contohnya

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

Semoga ini jelas dan tidak ada yang terlewatkan; Namun, ini adalah pertanyaan kedua saya jadi saya akan menghargai setiap umpan balik dan melakukan yang terbaik untuk memperbaiki masalah secepatnya.

Tas
sumber
@insertusernamehere Terima kasih atas sarannya! Saya telah menambahkan tanggal ke pertanyaan
Tas
@ Apakah Anda yakin tanggal-tanggal itu benar? Yang ada dalam contoh tidak cocok dengan kutipan dan keduanya tidak cocok dengan situs web.
Adam Martin
@AdamMartin Terima kasih telah menunjukkannya. Saya salah memasukkan tanggal Desember. Yang dalam contoh hanyalah tanggal, tidak spesifik untuk hari libur umum. Itu hanya contoh tanggal yang bisa dimasukkan, dan seperti apa hasilnya. Yang dikutip harus (dan mudah-mudahan cocok) dengan yang dari situs web.
Tas
Anda merayakan ulang tahun Ratu pada bulan Oktober di Queensland? Itu sangat aneh, tetapi tampaknya benar dari tautan.
Level River St
Wow, kalian tidak punya liburan mulai Juni hingga September? Itu kasar.
Joe Z.

Jawaban:

2

Pyth , 98 84 62 67 Bytes

Pembaruan: Disimpan 14 Bytes dengan memperpendek daftar hitungan hari untuk semua 12 bulan untuk perhitungan nomor hari. Belum menemukan cara yang baik untuk mengompres daftar yang lain, masih mencoba!

Update2: Menyimpan 22 byte lainnya dengan meng-endcoding daftar angka-hari sebagai string base256.

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

Cobalah online!

Algoritma yang sama seperti pada jawaban Python saya. Dan tidak ada builtin untuk mendapatkan hari dalam setahun, jadi saya harus melakukannya sendiri. Membuat 2 daftar itu untuk perhitungan hari-of-the-tahun dan untuk hari-hari liburan cukup mahal ... akan melihatnya lagi dan mencoba untuk menghasilkan mereka dalam byte lebih sedikit.

Denker
sumber
Tampaknya tidak suka input dipisahkan dengan tanda hubung, tetapi sebaliknya bagus
Tas
@Tas Terima kasih atas petunjuknya, lengkapkan membaca bagian itu ... Memperbaikinya dengan biaya 5 byte lebih. Mungkin Anda harus menambahkan beberapa tanda hubung ke dalam testcases, karena Anda ingin mereka menutupi setiap variasi input yang mungkin.
Denker
5

Visual Basic for Applications, 155 atau 118 byte

Versi 1 - lokal-independen, 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

Versi 2 - tergantung pada lokal, 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

Hitungan byte untuk file .BAS final, termasuk karakter linefeed. Diedit di luar editor VBA standar (karena membebankan ruang tambahan dan bentuk verbose dari beberapa kata kunci) - tetapi impor dan berjalan lancar pada Aplikasi Office apa pun (untuk menguji jenis misalnya ? h("10/08")di jendela langsung, atau dalam penggunaan Excel langsung dalam formula sel).

(EDITED) Awalnya saya memilih untuk menggunakan DateSerialfungsi locale-safe (versi 1). Karena saya tinggal di Brazil dan dengan demikian sistem saya dikonfigurasikan untuk menggunakan format "dd / mm / yy" untuk tanggal (seperti Australia), saya bisa menulis versi yang lebih kecil dengan menggunakan CDatesebagai gantinya (versi 2). CDatemenggunakan informasi lokal sistem untuk mengonversi teks menjadi tanggal. Saya juga berasumsi dalam versi ini bahwa kode hanya akan dijalankan selama 2016 (jika tahun dihilangkan (-6 bytes) CDatemengasumsikan tahun berjalan sesuai jam sistem).

Angka 42454 pada baris ketiga adalah jumlah dari 42450 yang merupakan representasi numerik 01/01/2016 pada VBA, dan 84 yang merupakan hari-of-the-tahun untuk liburan pertama. Array berisi hari-of-the-year untuk setiap liburan (termasuk 01/01/2017) diimbangi dengan -84 karena ini akan menghilangkan beberapa digit. Menggunakan 16 bukannya 2016 pada DateSerialmenghilangkan dua byte lagi.

Membuat array identik sembilan kali di dalam iterasi adalah kode "buruk", tetapi berfungsi dan menyimpan 3 byte lebih (satu untuk nama array dan satu untuk tanda yang sama di luar loop, dan satu lagi untuk referensi array di dalam loop).

Ruang "hilang" antara 0 dan kata kunci berikut pada baris kedua dan keempat tidak diperlukan karena diperkenalkan kembali secara otomatis oleh VBE ketika modul diimpor. Digunakan usang tetapi byte-murah If <...> Goto <linenumber>untuk istirahat dari loop (keduanya If <...> Then Exit Fordan If <...> Then Exit Functionmenggunakan lebih banyak karakter).

Juga mengambil keuntungan dari fakta bahwa nama fungsi di VBA berperilaku sebagai variabel lokal, dan nilainya secara otomatis dikembalikan oleh fungsi di akhir eksekusi.

dnep
sumber
Selamat datang di PPCG! Di sini kita mendefinisikan bahasa pemrograman oleh penerjemah, jadi sangat bisa diterima untuk membutuhkan lokal tertentu.
lirtosiast
Terima kasih! Diedit untuk menambahkan versi yang bergantung pada lokal yang lebih kecil.
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

Penjelasan

Menggunakan Datekonstruktor bawaan JavaScript untuk mengubah string input menjadi beberapa milidetik sejak zaman, lalu membandingkannya dengan jumlah milidetik untuk setiap hari libur umum.

Ini dilakukan dengan menyimpan hari libur umum dalam array sebagai jumlah hari sejak tanggal referensi. Saya memilih 2016-01-29untuk tanggal referensi karena jumlah milidetik sejak zaman dapat dipadatkan paling pendek untuk tanggal ini. Sejumlah milidetik antara hari ini dan selanjutnya berfungsi karena hasilnya dibulatkan ke bawah, dan mempertahankan angka di tengahnya menghindari efek penghematan siang hari (meskipun zona waktu OP tidak memiliki penghematan siang hari). Jumlah hari ini adalah 1453986000000dan membulatkannya menjadi 1454000000000(menambahkan beberapa jam) berarti dapat ditulis sebagai 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

Uji

Solusi ini tergantung pada zona waktu pengguna. Ini berfungsi di zona waktu OP (dan saya) (GMT +1000). Jika Anda ingin mengujinya di zona waktu yang berbeda, menambah numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000nomor tanggal referensi harus berfungsi. (mis. GMT +0430 akan menjadi -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)

pengguna81655
sumber
Ini memberi selalu 0 ketika tanggal dipisahkan oleh tanda hubung. Saya sudah meminta OP untuk menyesuaikan testcases-nya, karena semuanya dengan garis miring sebagai pemisah.
Denker
@ DenkerAffe Oh, saya pikir maksudnya kami bebas memilih pemisah. Kebetulan, membuatnya separator-ambivalen menyelamatkan saya 3 byte, jadi terima kasih!
user81655
1
Sepertinya aturannya separated with a hyphen - or slash /agak ambisius. Bagi saya itu berarti kita harus berurusan dengan keduanya, tetapi saya pasti bisa melihat sisi Anda. Tebak OP harus mengklarifikasi ini.
Denker
3

T-SQL, 210 , 206 , 194 Bytes

(Posting pertama di sini, Semoga ini ok, tapi tolong bersikap baik :)

Masukan dimasukkan @i, melayani keduanya /dan -sebagai pemisah. Saya di Australia, jadi format tanggal saya sama dengan @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;

Pembaruan varchar untuk charmenghemat 3 byte plus menghapus ruang :)

Perbarui 2 deklarasikan @cdan tetapkan tanpa pilih

Liesel
sumber
2

T-SQL, 296 byte

Dibuat sebagai fungsi bernilai tabel

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

Digunakan dengan cara berikut

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)

Penjelasan singkat

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
MickyT
sumber
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 masih membuat saya kalah 3 byte, tapi saya tidak dapat menemukan tempat lain untuk memeras apa pun dari sini. Bekerja dengan menghitung jumlah hari berlalu alih-alih menggunakan Tanggal, lalu membandingkannya dengan serangkaian offset liburan.

Mwr247
sumber
2

Python 2, 204 185 165 166 Bytes

Pembaruan: Dipotong turun ~ 20 Bytes dengan menghitung hari dalam setahun sendirian. Tidak perlu lagi impor lama :)

Perbarui 2: Lain 20 Bytes turun dengan menyadari bahwa saya dapat memperlakukan tahun baru seperti hari 367 dan membuat beberapa penyesuaian kecil lainnya.

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

Cobalah online!

Tidak Disatukan:

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

Bekerja dengan menyimpan jumlah hari libur dalam daftar, menyaring yang sebelum tanggal yang ditentukan, mengambil elemen pertama dalam daftar yang difilter dan mengurangi hari-tahun-tahun, yang dihitung dari input.

Denker
sumber
1

PHP, 116 byte

Pendekatan yang cukup lurus ke depan. Ini menyimpan hari-hari dalam setahun untuk liburan dan muncul selama mereka di masa lalu. Akhirnya hari yang diminta tahun itu dikurangi.

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;

Melewati semua kasus uji. Berjalan dari baris perintah dan menerima input menggunakan tanda hubung, seperti:

$ php holidays.php "12-05"
masukkan nama pengguna di sini
sumber
1

ruby 1.9.3, 155 153 byte

Setelah liburan Hari Natal, kami membutuhkan 366 hari istimewa kami! Kasus serupa dengan @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

Pemakaian:

$ ruby i_want_to_break_free.rb "03/05"
Tarod
sumber
Saya tidak tahu banyak tentang Ruby, tetapi saya pikir Anda dapat menyimpan 3 Bytes dengan menghapus spasi putih pada baris 1 dan 3. Anda juga harus menentukan metode input mana yang Anda gunakan, karena tidak begitu jelas dalam kode Anda. Anda mungkin menyimpan beberapa Bytes dengan mendefinisikan suatu fungsi, sehingga Anda dapat mengambil input sebagai argumen dan menggunakan nilai balik sebagai output.
Denker
@DenkerAffe Terima kasih banyak! Saya telah menyimpan 2 byte, tetapi saya pikir suatu fungsi akan menambah jumlahnya. Saya telah memperbarui jawabannya dengan contoh penggunaan.
Tarod
0

05AB1E , 45 byte

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

Mungkin bukan 2016 lagi, tapi apa pun ..;) Masih menganggap tahun ini 2016 demi tahun kabisat 29untuk Februari.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

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)

Lihat ini 05AB1E ujung tambang (bagian Cara kompres bilangan bulat besar? Dan Cara daftar bilangan bulat kompres? ) Untuk memahami mengapa •9JRt€ª´Q®Ië•adalah 10549819042671399072072399; •9JRt€ª´Q®Ië•368вadalah [85,86,88,116,123,277,360,361,362,367]; dan •Σ₁t•adalah 5354545.

Kevin Cruijssen
sumber