Tanggal Mengalikan Tantangan


19

(Terinspirasi oleh Riddler minggu lalu di FiveThirtyEight.com. Posting Sandbox .)

Diberi tahun antara 2001 dan 2099, hitung dan kembalikan jumlah hari selama tahun kalender itu di mana mm * dd = yy(di mana yytahun 2 digit ).

2018, misalnya, memiliki 5:

  • 18 Januari (1 * 18 = 18)
  • 9 Februari (2 * 9 = 18)
  • 6 Maret (3 * 6 = 18)
  • 3 Juni (6 * 3 = 18)
  • 2 September (9 * 2 = 18)

Input dapat berupa tahun numerik 2 atau 4 digit.

Output harus berupa bilangan bulat. Ruang trailing opsional atau pengembalian tidak masalah.

Daftar input / output lengkap:

Input = Output
 2001 = 1     2021 = 3     2041 = 0     2061 = 0     2081 = 2
 2002 = 2     2022 = 3     2042 = 4     2062 = 0     2082 = 0
 2003 = 2     2023 = 1     2043 = 0     2063 = 3     2083 = 0
 2004 = 3     2024 = 7     2044 = 3     2064 = 2     2084 = 5
 2005 = 2     2025 = 2     2045 = 3     2065 = 1     2085 = 1
 2006 = 4     2026 = 2     2046 = 1     2066 = 3     2086 = 0
 2007 = 2     2027 = 3     2047 = 0     2067 = 0     2087 = 1
 2008 = 4     2028 = 4     2048 = 6     2068 = 1     2088 = 3
 2009 = 3     2029 = 1     2049 = 1     2069 = 1     2089 = 0
 2010 = 4     2030 = 6     2050 = 3     2070 = 3     2090 = 5
 2011 = 2     2031 = 1     2051 = 1     2071 = 0     2091 = 1
 2012 = 6     2032 = 3     2052 = 2     2072 = 6     2092 = 1
 2013 = 1     2033 = 2     2053 = 0     2073 = 0     2093 = 1
 2014 = 3     2034 = 1     2054 = 4     2074 = 0     2094 = 0
 2015 = 3     2035 = 2     2055 = 2     2075 = 2     2095 = 1
 2016 = 4     2036 = 6     2056 = 4     2076 = 1     2096 = 4
 2017 = 1     2037 = 0     2057 = 1     2077 = 2     2097 = 0
 2018 = 5     2038 = 1     2058 = 0     2078 = 2     2098 = 1
 2019 = 1     2039 = 1     2059 = 0     2079 = 0     2099 = 2
 2020 = 5     2040 = 5     2060 = 6     2080 = 4

Ini adalah tantangan , jumlah byte terendah dalam setiap bahasa menang.

Pra-perhitungan dan hanya mencari jawaban biasanya dikecualikan sesuai aturan celah kami , tapi saya secara eksplisit mengizinkannya untuk tantangan ini. Hal ini memungkinkan untuk beberapa strategi alternatif yang menarik, meskipun tidak kemungkinan 98 99-item daftar lookup akan menjadi terpendek.


Jika itu membuatnya lebih mudah dalam bahasa Anda, jawabannya akan sama terlepas dari abad; 1924 dan 2124 memiliki jumlah hari yang sama dengan 2024.
BradC

jika hasil mm * dd lebih besar dari 100 maka secara otomatis disaring?
DanielIndie

@DanielIndie Benar, tidak ada tanggal "sampul" harus dihitung. Dengan kata lain, 12 Desember 2044 tidak masuk hitungan, meskipun 12 * 12 = 144.
BradC

Karena kita hanya perlu menangani sejumlah input, saya sudah mengedit semuanya. Jangan ragu untuk mengembalikan atau memformat ulang.
Shaggy

1
@ gwaugh Hanya bahwa Anda dapat memutuskan mana yang akan diterima sebagai input yang valid (sehingga Anda tidak perlu mengeluarkan karakter tambahan untuk mengkonversi keduanya).
BradC

Jawaban:


14

Excel, 48 byte

Hore! Akhirnya, sesuatu yang sangat baik dimiliki oleh Excel.

=COUNT(VALUE(ROW(1:12)&"/"&A1/ROW(1:12)&"/"&A1))

Mengambil input dari A1 dalam bentuk bilangan bulat 1-99 yang mewakili tahun, dan menampilkan ke mana pun Anda memasukkan rumus ini. Ini adalah rumus array, jadi gunakan Ctrl-Shift-Enter, bukan Enter untuk memasukkannya.

Ini mengambil keuntungan dari fakta yang COUNTmengabaikan kesalahan, sehingga kesalahan yang disebabkan oleh bulan tidak membagi tahun (mengarahkan Excel untuk menguraikan sesuatu seperti 2/12.5/25atau dengan tanggal yang tidak valid, seperti 2/29/58, hanya diabaikan dalam hati.


1
Sangat bagus. Mungkin perlu disebutkan membutuhkan tahun 2 digit A1. Memasuki tahun 4 digit hanya mengembalikan 0.
BradC

Benar! Saya akan mengeditnya ke dalam deskripsi.
Sophia Lechner

Juga saya harus menyebutkan bahwa itu spesifik lokal; itu tergantung pada memiliki lokal yang menggunakan pemesanan mm / dd / yy. Di lokal dengan pemesanan dd / mm / yy, jawabannya tentu saja dengan jumlah byte yang sama.
Sophia Lechner

1
Super pintar; Saya suka bagaimana Anda hanya menguji 12 kandidat tanggal (satu per bulan), daripada menjalankan setiap hari sepanjang tahun.
BradC

Perbaiki tahun ini menjadi byte save non-leap satu byte?
14m2

6

Python 2 , 44 byte

[k/32%13*(k%32)for k in range(96,509)].count

Cobalah online!

Fungsi anonim yang diberikan sebagai objek metode. Memproduksi semua produk dari (month, day)pasangan (m, d)yang dikodekan oleh k=32*m+ddengan 0≤m≤12, 0≤d≤31, membungkus di sekitar. Hilangkan 29-31 Februari dengan mengecualikan mereka dari jangkauan.


5

Java (JDK 10) , 65 byte

y->{int m=13,c=0;for(;m-->1;)if(y%m<1&y/m<29+m%2*3)c++;return c;}

Cobalah online!

Kredit


Tidak ada tahun 29*n
kabis yang

Terima kasih atas masukan Anda. Saya bisa menghapus 27 byte secara total dengan banyak perubahan lainnya.
Olivier Grégoire

1
Berganti (m==2?29:32)menjadi 29+m%2*3masih tampaknya memberikan semua OKhasil. Kredit untuk @AsoneTuhid 's Ruby jawabannya .
Kevin Cruijssen

4

PowerShell , 94 byte

param($a)for($x=Date 1/1/$a;$x-le(Date 12/9/$a);$x=$x.AddDays(1)){$z+=$x.Month*$x.Day-eq$a};$z

Cobalah online!

Mengambil input sebagai tahun dua digit, kemudian membuat satu forloop dari 1/1/yearke 12/9/year(karena 12/10 dan seterusnya tidak akan pernah dihitung dan ini menghemat satu byte). Setiap iterasi, kami menambah $zjika .Monthkali .Daysama dengan tahun input kami. Di luar loop, $zdibiarkan pada pipa dan output tersirat.

Sunting - ini tergantung budaya. Kode di atas berfungsi untuk en-us. Format tanggal mungkin perlu diubah untuk budaya lain.


2
"budaya"? Apakah maksud Anda "lokal"? ...
user202729

1
@ user202729 Bahasa sehari-hari, ya, tapi dokumentasi PowerShell menyebutnya sebagai "budaya."
AdmBorkBork

"Budaya" adalah kata yang umumnya digunakan MS untuk berbicara tentang lokal, misalnya. System.Globalization.CultureInfo dalam .NET.
sundar - Reinstate Monica




3

JavaScript (ES6), 91 byte

Saya ingin tahu bagaimana hardcoding dibandingkan dengan perhitungan berulang. Sudah pasti lebih lama (lihat jawaban @ Shaggy ), tetapi tidak terlalu lama.

Sunting : Ini, bagaimanapun, jauh lebih lama daripada formula yang lebih langsung (lihat @ l4m2 jawaban ).

Mengambil input sebagai integer dalam [1..99] .

n=>(k=parseInt('8ijkskercdtbnqcejh6954r1eb2kc06oa3936gh2k0d83d984h'[n>>1],36),n&1?k>>3:k&7)

Cobalah online!

Bagaimana?

Tahun ganjil memiliki kemungkinan lebih kecil untuk memiliki mm * dd = yy daripada tahun bahkan. Lebih konkretnya, tahun ganjil memiliki 0 hingga 3 pertandingan, sementara tahun bahkan memiliki 0 hingga 7 pertandingan. Ini memungkinkan kita untuk mengkodekan setiap pasangan tahun hanya dengan 5 bit, yang dapat dengan mudah direpresentasikan sebagai satu karakter dalam basis 36.




3

Utilitas Bash + GNU , 57

  • 1 byte disimpan berkat @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Perhatikan bahwa seqperintah selalu menghasilkan daftar 366 tanggal - untuk tahun non-kabisat 1 Januari tahun berikutnya akan dimasukkan. Namun dalam rentang tanggal 2001..2099, MM * DD tidak akan pernah menjadi YY untuk 1 Januari tahun berikutnya untuk tahun-tahun ini, jadi hari tambahan ini tidak akan mempengaruhi hasilnya.

Cobalah online!


Sangat bagus - Aku bahkan belum tahu date akan melakukan matematika tanggal seperti itu saat parsing. seqtidak perlu spasi setelah -f, sehingga Anda dapat menyimpan byte di sana.
Sophia Lechner

3

T-SQL, 123 121 byte

Sesuai aturan IO kami , input diambil melalui tabel t yang sudah ada dengan bidang integer y , yang berisi tahun 2 digit.

WITH c AS(SELECT 1m UNION ALL SELECT m+1FROM c WHERE m<12)
SELECT SUM(ISDATE(CONCAT(m,'/',y/m,'/',y)))FROM c,t WHERE y%m=0

Line break hanya untuk keterbacaan. Terinspirasi sebagian besar oleh solusi Excel Sophia .

  • Baris teratas menghasilkan tabel angka 12-item c yang digabungkan dengan tabel input t .
  • Jika itu berlalu saya tumbuk bersama kandidat tanggal menggunakan CONCAT(), yang tidak varcharkonversi data tipe implisit . Kalau tidak, aku harus melakukan banyak CASTatau CONVERTpernyataan.
  • Menemukan fungsi evaluasi yang sempurna ISDATE(), yang mengembalikan 1 untuk tanggal yang valid dan 0 untuk tanggal yang tidak valid.
  • Bungkus dalam SUM dan aku sudah selesai.
  • EDIT : Pindahkan cek divisi integer ( y%m=0) ke WHEREklausa untuk menyimpan 2 byte, terima kasih @RazvanSocol.

Sayangnya, ini tidak jauh lebih pendek daripada versi tabel pencarian (menggunakan string dari versi osdavison ):

Pencarian T-SQL, 129 byte

SELECT SUBSTRING('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)FROM t

EDIT : Meninggalkan dokumen asli saya di atas, tetapi kami dapat menyimpan beberapa byte dengan menggunakan beberapa fungsi baru:

  • STRING_SPLIT tersedia dalam MS SQL 2016 ke atas.
  • CONCAT_WS tersedia dalam MS SQL 2017 ke atas.
  • Seperti di atas, diganti IIFdenganWHERE

MS-SQL 2017, 121 118 byte

SELECT SUM(ISDATE(CONCAT_WS('/',value,y/value,y)))
FROM t,STRING_SPLIT('1-2-3-4-5-6-7-8-9-10-11-12','-')
WHERE y%value=0

MS-SQL 2017, edisi cheaty ekstra: 109 byte

SELECT SUM(ISDATE(CONCAT_WS('/',number,y/number,y)))
FROM t,spt_values WHERE number>0AND y%number=0AND'P'=TYPE

Perlu Anda berada di masterdatabase, yang berisi tabel sistem spt_valuesyang (ketika difilter oleh TYPE='P'), memberi Anda penghitungan angka dari 0 hingga 2048.


Mirip dengan jawaban lain, urutan saya merakit tanggal ( m/d/y) tergantung pada pengaturan lokalitas contoh SQL. Daerah lain mungkin memerlukan urutan yang berbeda, atau pemisah yang berbeda, tetapi menurut saya tidak akan memengaruhi panjang kode.
BradC

Saya kira Anda menyadari bahwa mengubah '2/29/64' ke tanggal menghasilkan 1964-02-29 (bukan 2064-02-29), tetapi mengingat bahwa tahun 2000 dan 2100 dikecualikan, ini cara yang bagus untuk mendapatkan yang lebih pendek kode.
Razvan Socol

Menggunakan SPLIT_STRINGbukannya CTE membawanya ke 120 byte. Menggunakan CONCAT_WSalih-alih CONCATmenyimpan karakter lain, membuatnya menjadi 119 byte.
Razvan Socol

@RazvanSocol Ya, saya tidak yakin di mana jeda antara tanggal 2-digit yang dipetakan ke 19xx vs 20xx, tetapi keduanya memberikan jawaban yang sama. Saya akan mencoba dua saran lainnya, terima kasih!
BradC

1
Ganti IIFdengan WHERE.
Razvan Socol

3

Julia 0,6 , 49 44 42 byte

y->sum(y/i1:28+3(i%2i÷8)for i=1:12)

Cobalah online!

-5 byte terinspirasi oleh jawaban Ruby Asone Tuhid.
-2 byte menggantikan hitungan dengan jumlah

Penjelasan:

Untuk setiap bulan i dari 1 hingga 12, hitung y/i, dan periksa apakah itu salah satu dari hari-hari di bulan itu. Bulan dengan 31 hari adalah 1, 3, 5, 7, 8, 10, 12 - jadi mereka aneh di bawah 8 dan bahkan pada dan di atas 8. Jadi salah satu i%2atau i÷8(yaitu 0 untuk i <8 dan 1 untuk i> = 8 di sini) harus 1, tetapi tidak keduanya - jadi kami XOR mereka. Jika hasil xor benar, kami memeriksa tanggal 1:28+3yaitu 1:31, kalau tidak, kami memeriksa tanggal saja 1:28.

1:28cukup untuk sisa bulan (peningkatan ini terinspirasi oleh jawaban Asone Tuhid's Ruby ) karena:

  • untuk bulan Februari, satu-satunya kemungkinan adalah 2*29 = 58, tetapi 2058bukan tahun kabisat, jadi kita dapat menganggap Feb selalu memiliki 28 hari.

  • bulan-bulan lainnya dengan 30 hari adalah bulan ke 4 dan di atasnya - yang i*29(dan i*30) akan di atas 100, yang dapat diabaikan.

Akhirnya, kami menghitung berapa kali y/iberada dalam daftar hari ini (dengan menggunakan boolean di sumsini), dan mengembalikannya.


3

JavaScript, 91 85 82 81 77 byte

Mengambil input sebagai string 2 digit (atau integer 1 atau 2 digit).

Mengambil keuntungan dari fakta yang new Dateakan bergulir ke bulan berikutnya, dan terus melakukannya, jika Anda memberikannya nilai hari yang melebihi jumlah hari dalam bulan yang Anda berikan, jadi, pada iterasi pertama, ia mencoba untuk membangun tanggal yyyy-01-345yang menjadi yyyy-12-11, atau yyyy-12-10pada tahun kabisat. Kami tidak perlu memeriksa tanggal setelah itu karena 12*11+menghasilkan angka 3 digit.

y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)

3 byte disimpan berkat Arnauld .


Menguji

f=
y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>



2

Excel, 83 byte

{=SUM(IF(MONTH(DATE(A1,1,0)+ROW(1:366))*DAY(DATE(A1,1,0)+ROW(1:366))=A1-2000,1,0))}

Input ada di sel A1dalam format yyyy. Ini adalah rumus array dan dimasukkan dengan Ctrl+ Shift+ Enteruntuk mendapatkan kurung keriting {}. Ini cukup mudah dan tanpa kepintaran.

Ketika dalam rumus array, DATE(A1,1,0)+ROW(1:366)beri kami array dengan nilai tanggal 366. Pada tahun-tahun non-kabisat, ini akan termasuk 1 Januari tahun depan tetapi itu tidak menjadi masalah karena 1*1=1dan hanya akan dihitung sebagai false positive jika tahun berikutnya adalah2001 , tetapi karena rentang tahun yang diperlukan adalah2001 - 2099 , itu tidak akan pernah muncul sebagai isu.

Jika Anda menyingkat sedikit menjadi sederhana ~, rumusnya karena lebih mudah diikuti:

{=SUM(IF(MONTH(~)*DAY(~)=A1-2000,1,0))}

Saya mencoba menggunakan COUNTIF()alih-alih SUM(IF())tetapi Excel bahkan tidak membiarkan saya memasukkannya sebagai rumus array, apalagi memberi saya hasil. Saya memang menemukan solusi Google Sheets menggunakan CountIf()tetapi metode yang sama kalau tidak ternyata menjadi 91 byte, terutama karena menggunakan ArrayFormula()bukan hanya { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)

Saya belum melihat konsensus, tetapi saya umumnya belum memasukkan tanda kurung kurawal luar dalam hitungan byte saya untuk Excel. Mereka merasa lebih seperti cara Excel memformat tampilan daripada bagian dari rumus. Pendapat?
Sophia Lechner

@SophiaLechner Saya sudah memasukkan mereka alih-alih memutuskan bagaimana memasukkan penekanan tombol tambahan yang diperlukan untuk memasukkannya sebagai formula array. Ada pertanyaan meta tentang itu dan satu-satunya jawaban mengatakan bahwa perintah CTRL + ALT + ENTER akan dihitung sebagai 1 keystroke. Jika Anda menggunakan yang sama dengan vim ( per meta ), maka keystroke itu akan dihitung sebagai 1 byte. Namun, saya biasanya tidak menghitung ENTER di akhir memasukkan rumus sebagai 1 byte di jawaban lain.
Engineer Toast

2

Retina 0.8.2 , 55 byte

..
$*
(?<=^(1{1,12}))(?=(?(?<=^11$)\1{0,27}|\1{0,30})$)

Cobalah online! Membutuhkan waktu dua digit tahun; tambahkan 1 byte untuk mendukung tahun 4-digit. Penjelasan: Tahap pertama hanya dikonversi ke unary. Tahap kedua dimulai dengan mencocokkan 1 hingga 12 karakter sebelum posisi pertandingan, mewakili bulan, dan kemudian mencoba melihat ke depan untuk sejumlah pengulangan bulan itu. Namun, lookahead berisi persyaratan, yang memilih antara hingga 27 atau 30 pengulangan lebih lanjut tergantung pada bulan. Hitungan posisi pertandingan kemudian merupakan hasil yang diinginkan.


2

R , 22 122 byte

x=scan();substr("122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012",x,x)

Cobalah online!

Memutuskan untuk pergi dengan pendekatan tabel pencarian. Tahun input harus 2 digit.


1
Juga di TIO Anda dapat menekan tombol "tautan" dan itu akan memformat jawabannya secara otomatis. Terima kasih kepada Dennis untuk pengaturannya!
Giuseppe

Anda dapat menghapus inisial if, karena input dapat berupa 2 digit atau 4 digit, pilihan Anda (sehingga Anda dapat memilih untuk hanya menerima input 2 digit). Tapi sepertinya kode menganggap setiap bulan mengandung 31 hari, jadi misalnya, 62 (untuk 2062) mengembalikan 1 di mana ia harus mengembalikan 0.
sundar - Reinstate Monica

2
Saya salah paham. Yang sedang berkata, saya cukup yakin tabel pencarian harus dimasukkan dalam jumlah byte.
ngm

@ ngm Saya juga tidak yakin apakah tabel pencarian perlu dimasukkan, tapi saya akan menambahkannya ke jumlah byte agar aman.
Robert S.

Saya masih tidak yakin apa semua peraturannya!
ngm


2

J , 29 byte

1#.(,x*i."+29+3*2~:x=.i.13)=]

Cobalah online!

Bagaimana itu bekerja

1#.(,x*i."+29+3*2~:x=.i.13)=]    Input: year (2-digit, 1..99)
                   x=.i.13       array of 0..12; assign to x
                2~:              1 1 0 1 .. 1
              3*                 3 3 0 3 .. 3
           29+                   32 32 29 32 .. 32
       i."+                      for each item of above, generate a row 0 .. n
    ,x*                          each row times 0 .. 12 and flatten
                           =]    1 for each item == input, 0 otherwise
1#.                              sum

Berusaha keras untuk mendapatkan di bawah 2 kali solusi Jelly :)

Catatan samping

Jika seseorang benar-benar ingin meng-hardcode data 99 digit, berikut ini sedikit informasinya:

Membagi 99 digit menjadi potongan 2 digit. Kemudian digit pertama adalah <4dan yang kedua <8, yang berarti lima bit dapat mengkodekan dua angka. Kemudian seluruh data dapat dikodekan dalam 250 bit, atau 32 byte.


2

Python 3 , 158 162 215 241 byte

Dihapus 4 Terima kasih kepada Stephen untuk bermain golf bersyarat.

Dihapus 53 terima kasih Stephen untuk menunjukkan ruang putih

Dihapus 26 berkat tautan yang diberikan oleh caird

Saya cukup baru dalam hal ini. Tidak dapat memikirkan cara melakukan ini tanpa ada hari dalam sebulan yang dijelaskan.

r=range
def n(Y):
 a,b,c=31,30,0
 for x in r(12):
  for y in r([a,(28if Y%4else 29),a,b,a,b,a,a,b,a,b,a][x]):
   if(x+1)*(y+1)==int(str(Y)[2:]):c+=1
 return c

Cobalah online!


5
Selamat datang di situs ini, dan posting pertama yang bagus! Ada beberapa cara yang adil untuk bermain golf ini, seperti menghapus beberapa spasi putih, jadi pastikan untuk memeriksa tips ini untuk bermain golf di Python
caird coinheringaahing

@cairdcoinheringaahing Terima kasih atas sarannya, tautannya sangat berguna!
akozi

1
158 byte - bermain golf beberapa saat, tetapi sebagian besar Anda memiliki garis besar panjang spasi di baris ketiga Anda, tidak tahu bagaimana mereka sampai di sana
Stephen

@Stephen Terima kasih :) Saya menambahkan milik Anda sebagai dua suntingan. Satu untuk ruang putih dan yang lainnya sebagai golf.
akozi

(28if Y%4else 29)dapat disingkat menjadi [29,28][Y%4>0]. Juga, daftar panjang dapat disingkat menjadi [a,...]+2*[a,b,a,b,a]. a,b,cdapat ditambahkan dalam daftar parameter untuk menyimpan garis. int(str(Y)[2:])dapat disingkat menjadi Y%100. Akhirnya, variabel counter sebagian besar dapat disingkat menjadi lendaftar pemahaman, ini juga memungkinkan nuntuk dibuat lambda. Ini menghasilkan 118 .
Black Owl Kai

2

Keempat (gforth) , 60 59 byte

: f 0 13 1 do over i /mod swap 32 i 2 = 3 * + 0 d< - loop ;

Cobalah online!

Versi ini mengambil keuntungan dari kenyataan bahwa tidak boleh ada lebih dari 1 hari pencocokan per bulan, dan bahwa tahun harus dibagi berdasarkan bulan untuk mencocokkan.

Penjelasan

Iterate selama berbulan-bulan, periksa apakah tahun dapat dibagi berdasarkan bulan, dan jika hasil bagi adalah <31 (28 untuk Februari) Bulan setelah Maret tidak dapat mencocokkan dengan hari yang lebih besar dari 25, jadi kami dapat mengasumsikan semua bulan (selain Februari) punya 31 hari untuk tujuan puzzle.

Penjelasan Kode

: f                   \ start new word definition
  0                   \ set up counter
  13 1 do             \ start a counted loop from 1 to 12
    over i /mod       \ get the quotient and remainder of dividing year by month
    swap              \ default order is remainder-quotient, but we want to swap them
    32 i 2= 3 * +     \ we want to compare to 32 days unless month is Feb
    0 d<=             \ treat the 4 numbers on the stack as 2 double-length numbers
                      \ and compare [1]
    -                 \ subtract result from counter (-1 is true in Forth)
  loop                \ end loop
;                     \ end word definition    

[1] - Keempat memiliki konsep angka panjang ganda, yang disimpan di tumpukan sebagai dua angka panjang tunggal (dari bentuk xy, di mana nilai ganda = di y * 2^(l) + xmana l adalah ukuran dalam bit dari satu tunggal di implementasi yang sedang Anda kerjakan).

Dalam kasus ini, saya membandingkan hasil bagi dan sisanya menjadi 32 (atau 29) 0. Jika sisanya lebih besar dari 0 (tahun tidak dibagi menurut bulan), ganda pertama akan secara otomatis lebih besar dari 32 (atau 29) 0 dan hasilnya akan salah. Jika sisanya adalah 0, maka itu memutuskan untuk secara efektif memeriksa hasil bagi <<32 (atau 29)

Keempat (gforth) , 61 byte

: f 0 13 1 do i 2 = 3 * 32 + 1 do over i j * = - loop loop ; 

Cobalah online!

Menyimpan beberapa byte dengan menyadari bahwa hanya Februari yang penting dalam hal memiliki jumlah hari yang benar dalam sebulan

Penjelasan

Untuk (setidaknya gforth) perbandingan mengembalikan -1 untuk true dan 0 untuk false

0                     \ place 0 on top of the stack to use as a counter
13 1 do               \ begin the outer loop from 1 to 12
  i 2 = 3 *           \ if i is 2 place -3 on top of the stack, otherwise 0
  32 + 1 do           \ begin the inner loop from 1 to 31 (or 28)
    over              \ copy the year from stack position 2 and place it on top of the stack
    i j * = -         \ multiply month and day compare to year, subtract result from counter 
  loop                \ end the inner loop
loop                  \ end the outer loop

1

Java (JDK 10) , 79 72 70 byte

y->{int a=0,m=13;for(;m-->1;)a+=y%m<1&&y/m<(m==2?29:32)?1:0;return a;}

Cobalah online!


@Shaggy Terima kasih! (sisa dari versi sebelumnya di mana saya mengulangi semua d
ays

Jika Anda beralih &&ke &jawaban yang sama dengan jawaban Java OlivierGrégoire, meskipun ia telah menjawab 19 menit sebelumnya.
Kevin Cruijssen

@KevinCruijssen Kebetulan acak. Meskipun versi saya sedikit lebih buruk (tidak perlu menggunakan ternary).
user202729

1

JavaScript (Node.js) , 108 byte

a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]

f=a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>


Pencarian kasar, bagus!
BradC

Selamat datang di PPCG!
Shaggy


1

Python 3, 132 byte

Ini benar-benar program yang cukup lama, tetapi saya pikir ini mungkin menarik.

Semua nilai adalah antara 0-7 jadi saya menyandikan setiap angka dengan 3 bit dalam string biner yang panjang. Saya mencoba menempelkan string biner mentah ke dalam program python saya, tetapi saya tidak bisa membuatnya bekerja, jadi saya memilih base64 dalam file tersebut.

Saya menggunakan string berikut sebagai tabel pencarian (berakhir 7 digunakan untuk padding): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

Program mengambil string ini dan menerjemahkannya sebagai angka, lalu menggunakan bit shifting untuk mengekstrak hasilnya.

import base64
lambda n:int.from_bytes(base64.b64decode(b'pNRRxYtw01s9Jw4tFYE0QNkYsoRQgYBosEsYBFIRAUgsUkgwFQM='),'big')>>(6306-3*n)&7

66 byte + file 37 byte = 103 byte

Ini membaca file biner yang dipanggil edan menghindari penggunaan base64.

lambda n:int.from_bytes(open('e','rb').read(),'big')>>(6306-3*n)&7

Berikut ini adalah hexdump dari file baca (tanpa padding):

00000000  a4 d4 51 c5 8b 70 d3 5b  3d 27 0e 2d 15 81 34 40  |..Q..p.[='.-..4@|
00000010  d9 18 b2 84 50 81 80 68  b0 4b 18 04 52 11 01 48  |....P..h.K..R..H|
00000020  2c 52 48 30 0a                                    |,RH0.|


1

Oracle SQL, 115 byte

select count(decode(sign(decode(l,2,29,32)-y/l),1,1))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Kita dapat mencatat bahwa tidak terlalu penting berapa hari di bulan April (dan bulan-bulan berikutnya), sejak 100/4 <28. Juga tidak perlu memeriksa apakah tahun itu melompat atau tidak. Kami hanya perlu menentukan bahwa ada 28 hari di bulan Februari (bukan 29 karena validasi itu akan dieksekusi hanya untuk 2058 yang tidak melompat) jika tidak, mungkin hanya 31 untuk setiap bulan.

Pendekatan lain

Oracle SQL (12c Release 2 dan yang lebih baru), 151 byte

select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Oracle SQL (12c Release 2 dan yang lebih baru), 137 byte

select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Kedua solusi bisa menjadi 8 byte lebih pendek jika kita ganti (select level l from dual connect by level<=12)dengan xmltable('1to 12'columns l int path'.')tetapi Oracle melempar pengecualian karena bug (diuji pada versi 12.2.0.1.0, 18.3.0.0.0).

SQL> select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got DATE


SQL> select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-43909: invalid input data type

Satu-satunya kasus di kedua solusi ketika tahun itu penting adalah 2058 yang non-lompatan sehingga literal '-1' digunakan untuk menentukan tahun non-lompatan.

Oracle SQL, 128 byte

select count(d)from t,(select date'1-1-1'+level-1 d from dual connect by level<365)
where to_char(d(+),'mm')*to_char(d(+),'dd')=y

Oracle SQL, 126 byte

select substr('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)from t

Memperbarui

Oracle SQL, 110 byte

select-sum(least(sign(y/l-decode(l,2,29,32)),0))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Oracle SQL, 108 byte

select sum(decode(sign(decode(l,2,29,32)-y/l)*mod(y+1,l),1,1))from t,
xmltable('1to 12'columns l int path'.')

Spark SQL, 137 byte

select count(cast(regexp_replace(concat_ws('-','2001',l,y/l),'.0$','')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

Spark 2.3+ SQL, 126 byte

( replacefungsi menjadi tersedia)

select count(cast(replace(concat_ws('-','2001',l,y/l),'.0')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

1

PHP , 73 byte

Menggunakan input pipa dan php -nR:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argn==$m*$d++;echo$c;

Cobalah online!

PHP , 76 byte

Menggunakan input baris perintah arg php dm.php 18:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argv[1]==$m*$d++;echo$c;

Cobalah online!

Pendekatan berulang. Karena satu-satunya tahun kabisat yang terlihat adalah 2 * 29 = 58, dan 2058 bukan tahun kabisat, maka tidak perlu mempertimbangkan tahun kabisat pada hari-hari Februari. Dan karena sampul bukan masalah - mulai April hingga hari, lebih dari 25 hari akan melebihi 100, kami hanya mengatakan sisa bulan hanya memiliki 25 hari.

Input adalah 2 digit tahun melalui baris perintah (-10 byte sebagai program, terima kasih atas saran dari @Titus).

ATAU:

PHP , 101 byte

$y=$argv[1];for($d=strtotime("$y-1");date(Y,$d)==$y;$d+=86400)eval(date("$\x+=j*n=='y';",$d));echo$x;

Cobalah online!

Masih berulang tetapi menggunakan fungsi timestamp PHP. Menerima tahun sebagai angka empat digit. Terima kasih kepada @Titus untuk saran penggunaan strtotime()alih-alih mktime().


Versi pertama gagal selama 4 digit tahun, kedua gagal untuk dua digit. Tapi pemikiran yang bagus. Cobalah $m<5?$m-2?31:28:25untuk yang pertama dan $d=strtotime("$y-1")yang kedua
Titus

Uhm ... Mengapa Anda memasukkan ytanda kutip di tanda kutip?
Titus

@Itus karena PHP7 sekarang memperlakukan digit yang didahului dengan 0 sebagai oktal, jadi 08 dan 09 sebenarnya tidak valid. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Menggunakan fungsi date () Anda hanya bisa mendapatkan 2 digit, tahun nol-empuk.
640KB

Kekecewaan! tentu saja.
Titus

1
@Itus, memperbarui versi kedua menggunakan dan strtotime()bukan mktime()diimplementasikan kembali sebagai program, -7 byte. Juga, saya melihat sebagian besar kiriman, termasuk yang terpilih teratas, hanya akan menerima tahun sebagai 2 atau 4 digit, jadi saya akan menganggap itu berarti diserahkan kepada pengirim. Sekali lagi untuk saran!
640KB

0

PHP, 74 70 byte

while(++$m<13)for($d=$m<5?$m-2?31:28:25;$d;)$n+=$d--*$m==$argn;echo$n;

hanya menerima dua digit tahun.

Saya mengadopsi pertimbangan gwaugh dan bermain golf mereka; Pendekatan pertama saya lebih lama dari (92 byte):

for($y=$argn%100;++$m<13;)for($d=$m-2?30+($m+$m/8)%2:29-($y%4>0);$d;)$n+=$d--*$m==$y;echo$n;

%100 memungkinkan untuk menggunakan tahun 4-digit.


Jalankan sebagai pipa dengan -nRatau coba online .


Anda dapat menyimpan 4 byte dengan menghapus% 100 dan hanya mengambil input 2 digit, yang OK: codegolf.stackexchange.com/questions/162137/…
640KB
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.