Tarih Çarpma Zorluğu


19

( Geçen haftaki FiveThirtyEight.com'daki Riddler'den esinlenmiştir. Sandbox yayını .)

2001 ve 2099, hesapla arasında bir yıl Verilen ve o takvim yılı içinde gün sayısını döndürür nerede mm * dd = yy(burada yyolduğu 2 basamaklı yılı).

Örneğin 2018'de 5 var:

  • 18 Ocak (1 * 18 = 18)
  • 9 Şubat (2 * 9 = 18)
  • 6 Mart (3 * 6 = 18)
  • 3 Haziran (6 * 3 = 18)
  • 2 Eylül (9 * 2 = 18)

Giriş 2 veya 4 basamaklı bir sayısal yıl olabilir.

Çıktı bir tamsayı olmalıdır. İsteğe bağlı sondaki boşluk veya dönüş iyi.

Komple giriş / çıkış listesi:

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

Bu bir mücadelesi, her dilde en düşük bayt sayısı kazanır.

Önceden hesaplamak ve sadece cevapları aramak normalde boşluk deliği kurallarımıza göre hariç tutulur , ancak açıkça bu zorluğa izin veriyorum. 98 99 maddelik arama listesinin en kısa olması muhtemel olmasa da, bazı ilginç alternatif stratejilere izin verir .


Eğer dilinizde bunu kolaylaştırırsa, cevap yüzyıldan bağımsız olarak aynı olacaktır; 1924 ve 2124, 2024 ile aynı gün sayısına sahiptir.
BradC

mm * dd sonucu 100'den büyükse otomatik olarak filtrelenir mi?
DanielIndie

@DanielIndie Doğru, hiçbir "sarma" tarihi sayılmamalıdır. Başka bir deyişle, 12 Aralık 2044, 12 * 12 = 144 olmasına rağmen sayılmaz.
BradC

Yalnızca sınırlı sayıda girişe ihtiyacımız olduğundan hepsini düzenledim. Geri alma veya yeniden biçimlendirme yapmaktan çekinmeyin.
Shaggy

1
@gwaugh Sadece hangisinin geçerli girdi olarak kabul edeceğinize karar verebilirsiniz (böylece ikisi arasında dönüştürme yapmak için fazladan karakter harcamanız gerekmez).
BradC

Yanıtlar:


14

Excel, 48 bayt

Yaşasın! Sonunda Excel aslında iyi bir şey.

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

A1'den yılı temsil eden 1-99 arasında bir tamsayı şeklinde girdi alır ve bu formülü girdiğiniz her yerde çıktı alır. Bu bir dizi formülüdür, bu nedenle girmek için Enter yerine Ctrl-Shift-Enter tuşlarını kullanın.

Bu, COUNThataları göz ardı ettiği gerçeğinden yararlanır , bu nedenle ya yılı bölmeyen ayın neden olduğu hatalar (Excel'in gibi bir şeyi ayrıştırmasına 2/12.5/25veya geçerli olmayan tarih gibi 2/29/58, örneğin sessizce göz ardı edilir.


1
Çok hoş. Muhtemelen bahsetmeye değer bir 2 haneli yıl gerektirir A1. 4 basamaklı bir yıl girmek basitçe geri döner 0.
BradC

Doğru! Bunu açıklamaya düzenleyeceğim.
Sophia Lechner

Ayrıca bu bölgeye özgü olduğunu belirtmek gerekir; aa / gg / yy sıralaması kullanan bir yerel ayara sahip olmasına bağlıdır. Gg / aa / yy sıralamasına sahip bir yerel ayarda, yanıt elbette aynı sayıda bayt olacaktır.
Sophia Lechner

1
Süper zeki; Yılın her günü yerine, sadece 12 tarih adayını (ayda bir tane) test etmeyi seviyorum.
BradC

Yılı sıçrama olmayan bir bayt olarak düzelt?
l4m2

6

Python 2 , 44 bayt

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

Çevrimiçi deneyin!

Yöntem nesnesi olarak verilen anonim bir işlev. Bütün ürünleri üretir (month, day)çiftleri (m, d)tarafından kodlanan k=32*m+dile 0≤m≤12, 0≤d≤31yaklaşık sarma. 29-31 Şubat'ı aralığın dışında bırakarak ortadan kaldırır.


5

Java (JDK 10) , 65 bayt

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

Çevrimiçi deneyin!

Kredi


Artık yıl uymuyor 29*n, bu yüzden kontrol gerekmiyor
l4m2

Giriş için teşekkürler. Bir sürü başka değişiklikle toplam 27 bayt kaldırabilirim.
Olivier Grégoire

1
Değişen (m==2?29:32)için 29+m%2*3hala tüm vermek görünüyor OKsonuçları. Kredi @AsoneTuhid 'ın Yakut cevap .
Kevin Cruijssen

4

PowerShell , 94 bayt

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

Çevrimiçi deneyin!

İki basamaklı bir yıl olarak girdi alır, daha sonra ile forarasında bir döngü 1/1/yearoluşturur 12/9/year(çünkü 12/10 ve üstü asla sayılmaz ve bu bir bayt tasarrufu sağlar). Her bir yineleme, girdi $zyılımıza eşit olduğu .Monthzamanları artırırız .Day. Döngünün dışında, $zboru hattında kalır ve çıktı örtüktür.

Düzenle - bu kültüre bağlıdır. Yukarıdaki kod çalışır en-us. Tarih formatının diğer kültürler için değişmesi gerekebilir.


2
"kültür"? Şunu mu demek istediniz: "locale"? ...
user202729

1
@ user202729 Halk dilinde, evet, ancak PowerShell belgeleri bunu "kültür"
AdmBorkBork

"Kültür", MS'in genellikle yerel ayar hakkında konuşmak için kullandığı, örn. System.Globalization.CultureInfo . NET'te.
sundar - Monica'yı eski




3

JavaScript (ES6), 91 bayt

Hardcoding'in yinelemeli bir hesaplama ile nasıl karşılaştırılacağını merak ediyordum. Kesinlikle daha uzun ( @ Shaggy'nin cevabına bakınız ), ama çok daha uzun değil .

Düzenleme : Bununla birlikte, daha doğrudan bir formül daha uzun (bkz. @ L4m2 cevap ).

Girişi [1..99] ' da bir tamsayı olarak alır .

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

Çevrimiçi deneyin!

Nasıl?

Tek yılların mm * gg = yy'ye sahip olma şansı çift yıllara göre önemli ölçüde daha azdır . Daha somut olarak, garip yılların 0 ila 3 maçları vardır, hatta yılların 0 ila 7 maçları vardır. Bu, her bir çifti yılda 36 bazda tek bir karakter olarak gösterilebilen sadece 5 bit ile kodlamamızı sağlar.




3

Bash + GNU yardımcı programları , 57

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

O Not seqkomutu daima 366 tarihlerinin listesini üretir - gelecek yılın olmayan, artık yıllar 1 Ocak'ta dahil edilecektir. Bununla birlikte, 2001..2099 tarih aralığında, MM * DD, bu yılların hiçbiri için gelecek yılın 1 Ocak'ı için asla YY olmayacaktır, bu nedenle bu fazladan gün sonucu etkilemez.

Çevrimiçi deneyin!


Çok güzel - dateAyrıştırırken böyle tarih matematik yapacağını bile bilmiyordum. seqsonra bir boşluk gerekmez -f, böylece orada bir bayt kaydedebilirsiniz.
Sophia Lechner

3

T-SQL, 123 121 bayt

ES kurallarımıza göre , giriş, 2 basamaklı bir yıl içeren bir tamsayı alanı y ile önceden var olan tablo t aracılığıyla alınır .

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

Satır sonu yalnızca okunabilirlik içindir. Büyük ölçüde Sophia'nın Excel çözümünden ilham aldı .

  • En üst satır , giriş tablosuna t birleştirilen 12 öğeli bir sayı tablosu c oluşturur .
  • Eğer bu başarılı olursa CONCAT(), örtülü varcharveri tipi dönüşümleri yapan bir tarih adayını birleştiririm . Aksi takdirde, bir demet CASTveya CONVERTifadeler yapmak zorunda kalacaktım .
  • ISDATE()Geçerli tarihler için 1, geçersiz tarihler için 0 döndüren mükemmel değerlendirme işlevini buldu .
  • Bir TOPLA sarın ve bitti.
  • EDIT : @RazvanSocol sayesinde 2 bayt kaydetmek için tamsayı bölme denetimi ( y%m=0) WHEREyan tümcesine taşındı.

Ne yazık ki, arama tablosu sürümünden çok daha kısa değil ( osdavison sürümünden dizeyi kullanarak ):

T-SQL araması, 129 bayt

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

EDIT : Orijinalimi yukarıda bırakarak, ancak birkaç yeni işlev kullanarak birkaç bayt kaydedebiliriz:

  • STRING_SPLIT MS SQL 2016 ve sonraki sürümlerde kullanılabilir.
  • CONCAT_WS MS SQL 2017 ve sonraki sürümlerde kullanılabilir.
  • Yukarıda belirtildiği gibi, ikame IIFileWHERE

MS-SQL 2017, 121 118 bayt

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, ekstra ucuz sürüm: 109 bayt

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

(Filtrelendiğinde ) 0 ile 2048 arasındaki sayıları saymanızı sağlayan masterbir sistem tablosu içeren veritabanında olmanızı gerektirir .spt_valuesTYPE='P'


Diğer yanıtlara benzer şekilde, date ( m/d/y) yöntemini bir araya getirdiğim sıra , SQL örneğinin konum ayarlarına bağlıdır. Diğer yerler farklı bir düzen veya farklı bir ayırıcı gerektirebilir, ancak kod uzunluğunu etkileyeceğini sanmıyorum.
BradC

Sanırım '2/29/64' bir tarihe dönüştürmenin 1964-02-29 (2064-02-29 değil) verdiğini fark ettiniz, ancak 2000 ve 2100 yıllarının hariç tutulduğu düşünüldüğünde, daha kısa bir şekilde almak için güzel bir yol kodu.
Razvan Socol

SPLIT_STRINGCTE yerine kullanmak 120 bayta indirir. CONCAT_WSBunun yerine kullanmak CONCATbaşka bir karakteri kaydederek 119 bayta çıkarır.
Razvan Socol

@RazvanSocol Evet, ara verdiğin 19xx ve 20xx arasındaki 2 basamaklı tarihler arasında nerede olduğundan emin değilim, ama ikisi de aynı cevabı veriyor. Diğer iki öneriyi de deneyeceğim, teşekkürler!
BradC

1
Değiştir IIFile WHERE.
Razvan Socol

3

Julia 0.6 , 49 44 42 bayt

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

Çevrimiçi deneyin!

Asone Tuhid'ün Ruby cevabından esinlenerek -5 bayt.
-2 bayt, sayıyı toplamla değiştirir

Açıklama:

Her ay iiçin 1'den 12'ye kadar, y/io ayın günlerinden biri olup olmadığını hesaplayın ve kontrol edin. 31 güne sahip aylar 1, 3, 5, 7, 8, 10, 12'dir - bu nedenle 8'in altında ve hatta 8'in üzerinde tektirler. Yani ya i%2ya i÷8(i <8 için 0 ve i için = 0> = 8 burada) 1 olmalı, ama her ikisi de olmamalı - bu yüzden onları XOR. Xor sonuç doğruysa, biz tarih kontrol 1:28+3yani 1:31aksi takdirde biz sadece tarihlerini kontrol, 1:28.

1:28ayların geri kalanı için yeterlidir (bu gelişme Asone Tuhid'in Ruby cevabından esinlenmiştir ) çünkü:

  • Şubat için tek olasılık olurdu 2*29 = 58, ancak 2058artık bir yıl değil, bu yüzden Şubat'ın her zaman 28 günü olduğunu varsayabiliriz.

  • 30 güne sahip diğer aylar, 4. ay ve üstüdür; bunun için i*29(ve i*30) 100'ün üzerinde olur ve yok sayılabilir.

Son olarak, y/ibu gün listesine kaç kez dahil olduğunu sayarız ( sumburada boolean kullanarak ) ve bunu geri veririz .


3

JavaScript, 91 85 82 81 77 bayt

Girişi 2 basamaklı bir dize (veya 1 veya 2 basamaklı bir tam sayı) olarak alır.

new DateBir sonraki aya geçilecek ve bundan devam edecek olmanın avantajından yararlanır , eğer geçtiğiniz aydaki gün sayısını aşan bir gün değerini geçerseniz, ilk yinelemede, tarih yyyy-01-345olur yyyy-12-11, ya da yyyy-12-10artık yıllarda. Bundan sonraki tarihleri 12*11+3 haneli bir sayı olarak kontrol etmemiz gerekmez .

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

Arnauld sayesinde 3 bayt kurtardı .


Dene

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 bayt

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

Girdi, A1biçimdeki hücrede yyyy. Bu bir dizi formülüdür ve süslü parantez almak için Ctrl+ Shift+ ile girilir . Oldukça açık ve zekası yoktur.Enter{}

Bir dizi formülündeyken, DATE(A1,1,0)+ROW(1:366)bize 366 tarih değeri içeren bir dizi verir. Artık olmayan yıllarda, bu bir sonraki yılın 1 Ocak'ı içerecektir, ancak bu bir sorun değildir, çünkü 1*1=1sadece gelecek yıl ise yanlış pozitif olarak sayılır, 2001ancak gerekli yıl aralığı olduğundan 2001 - 2099, asla bir konu.

Bu biti basitçe kısalttıysanız ~, formülü takip etmek çok daha kolay:

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

Bunun COUNTIF()yerine kullanmayı denedim SUM(IF())ama Excel bile bir dizi formülü olarak girmeme izin vermedi, çok daha az sonuç verdi. Ben yaptım bir bulabilirsiniz Google Tablolar kullanarak çözüm CountIf()kullandığı çünkü çoğunlukla, 91 byte olduğu ortaya çıktı o aksi fakat aynı yöntemi ArrayFormula()yerine basitçe { }.

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

Bir fikir birliği görmedim, ancak genellikle Excel için bayt sayımlara dış kıvırcık köşeli parantezleri dahil etmedim. Excel'in görüntüsünü formülün bir bölümünden biçimlendirmesinin bir yolu gibi hissediyorlar. Görüşler?
Sophia Lechner

@SophiaLechner Bir dizi formülü olarak girmek için gereken ekstra tuş vuruşlarını nasıl ekleyeceğimize karar vermek yerine onları dahil ettim. Orada bir var meta soru hakkında o ve tek cevap CTRL + ALT + komut 1 tuş olarak sayılır ENTER söylüyor. Vim ( meta başına ) ile aynı kullanırsanız, bu tuş vuruşu 1 bayt olarak sayılır. Ancak, genellikle diğer yanıtlarda 1 bayt olarak bir formül girmenin sonunda ENTER saymaz.
Mühendis Tost

2

Retina 0.8.2 , 55 bayt

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

Çevrimiçi deneyin! İki basamaklı bir yıl alır; 4 basamaklı yılları desteklemek için 1 bayt ekleyin. Açıklama: İlk aşama basit olarak tekli'ye dönüşür. İkinci aşama, maç konumundan önce 1 ila 12 karakter eşleştirerek ayı temsil eder ve ardından o ayın tüm tekrarlarını ileriye bakmaya çalışır. Ancak, ileriye doğru, aya bağlı olarak 27 ila 30 daha fazla tekrar seçen bir koşul içerir. Eşleşme pozisyonlarının sayısı daha sonra istenen sonuçtur.


2

R , 22 122 bayt

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

Çevrimiçi deneyin!

Bir arama tablosu yaklaşımı ile gitmeye karar verdi. Girdi yılı 2 basamaklı olmalıdır.


1
Ayrıca TIO'da "link" düğmesine basabilir ve cevabı sizin için otomatik olarak biçimlendirir. Kurduğu için Dennis'e teşekkürler!
Giuseppe

Sen ilk kaldırabilirsiniz ifgirdi olabilir çünkü ya 2 basamaklı veya 4 basamaklı, seçiminizi (sadece 2 basamaklı girişini kabul etmek seçebilmesi). . O 0. göndermesi gereken kod 31 gün içerecek şekilde her ay gördüğü gibi Ama çok için örneğin arar (2062 için) 62 1 döndürür
eski durumuna Monica - Sundar

2
Yanlış anlamışım. Bununla birlikte, arama tablosunun bayt sayısına dahil edilmesi gerektiğinden eminim.
ngm

@ngm Ayrıca, arama tablosunun dahil edilmesi gerekip gerekmediğinden emin değildim, ancak sadece güvende olmak için bayt sayısına ekleyeceğim.
Robert

Hala tüm kuralların ne olduğundan emin değilim!
ngm


2

J , 29 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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

Jelly çözümü 2 kat altına almak için zor çalıştı :)

Kenar notu

Birisi 99 basamaklı verileri gerçekten kodlamak istiyorsa, işte size biraz bilgi:

99 basamağı 2 basamaklı parçalara bölün. Sonra ilk basamak <4ve ikinci basamak, <8beş bitin iki sayıyı kodlayabileceği anlamına gelir. Daha sonra tüm veriler 250 bit veya 32 bayt olarak kodlanabilir.


2

Piton 3 , 158 162 215 241 bayt

Kaldırıldı 4 Şartları golf oynadığı için Stephen'a teşekkürler.

Beyaz alanı işaret ettiği için 53 teşekkür Stephen kaldırıldı

Caird tarafından sağlanan bağlantı sayesinde 26 kaldırıldı

Bu konuda oldukça yeniyim. Bir ay içinde günler açıklanmadan bunun nasıl yapılacağını düşünemedim.

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

Çevrimiçi deneyin!


5
Siteye hoş geldiniz ve güzel ilk gönderi! Bazı beyaz alanları kaldırmak gibi bunu golf için adil birkaç yolu vardır, bu nedenle Python
caird coinheringaahing 13:08

@cairdcoinheringaahing Tavsiye için teşekkürler bağlantı çok faydalı oldu!
akozi

1
158 bayt - biraz golf oynadı, ama çoğunlukla üçüncü hattınızda büyük bir uzun alanınız vardı, bunların oraya nasıl geldiğini bilmiyorum
Stephen

@Stephen Teşekkürler :) Sizinkini iki düzenleme olarak ekledim. Biri beyaz boşluk ve diğeri golf için.
akozi

(28if Y%4else 29)kısaltılabilir [29,28][Y%4>0]. Ayrıca, uzun liste kısaltılabilir [a,...]+2*[a,b,a,b,a]. a,b,cbir satırı kaydetmek için parametre listesine eklenebilir. int(str(Y)[2:])kısaltılabilir Y%100. Son olarak, sayaç değişkenleri çoğunlukla lenliste kavrayışlarına kısaltılabilir , bu da na lambda. Bu 118 yapar .
Black Owl Kai

2

İleri (gforth) , 60 59 bayt

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

Çevrimiçi deneyin!

Bu sürüm, ayda 1'den fazla eşleşen günün bulunamamasından ve yılın eşleşmesi için ayın bölünebilmesi gerektiğinden yararlanmaktadır.

açıklama

Aylar içinde yinelenir, yılın aya göre bölünebilir olup olmadığını ve bölümün <31 (Şubat için 28) olup olmadığını kontrol eder Mart ayından sonraki aylar 25'ten büyük günler için eşleşemez, bu nedenle tüm ayları (Şubat dışında) varsayabiliriz bulmacanın amacı için 31 gününüz var.

Kod Açıklaması

: 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] - Dördüncü olarak, yığın üzerinde iki tek uzunluklu sayı (xy biçiminde, çiftin değeri = y * 2^(l) + x burada l, çalıştığınız dördüncü uygulama).

Bu durumda, bölümü ve kalanını 32 (veya 29) 0 ile karşılaştırdım. Kalan 0'dan büyükse (yıl aylara bölünemez), ilk çift otomatik olarak 32 (veya 29) 0'dan büyük olur ve sonuç yanlış olur. Kalan 0 ise, <= 32 (veya 29) değerinin düzenli bir şekilde kontrol edilmesini etkili bir şekilde çözer.

İleri (gforth) , 61 bayt

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

Çevrimiçi deneyin!

Ayın doğru sayıda gününün olması açısından yalnızca Şubat'ın önemli olduğunu fark ederek bazı baytlar kaydetti

açıklama

İleri (en azından gforth) karşılaştırmaları true için -1 ve false için 0 döndürür

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 bayt

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

Çevrimiçi deneyin!


@Shaggy Teşekkürler! (önceki d
aydan kalan

Eğer değiştirirseniz &&için &kendisine o 19 dakika önce cevap olmasına rağmen, OlivierGrégoire Java cevap olarak aynı cevap.
Kevin Cruijssen

@KevinCruijssen Rastgele tesadüf. Benim sürümüm biraz daha kötü olsa da (üçlü gereksiz kullanım).
user202729

1

JavaScript (Node.js) , 108 bayt

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>


Kaba kuvvet arayışı, güzel!
BradC

PPCG'ye Hoşgeldiniz!
Shaggy


1

Python 3, 132 bayt

Bu gerçekten çok uzun bir program ama ilginizi çekebileceğini düşündüm.

Tüm değerler 0-7 arasındadır, bu yüzden her sayıyı uzun bir ikili dizede 3 bit ile kodlarım. Python programım ham bir ikili dize yapıştırma denedim ama işe yaramadı, bu yüzden dosya base64 yerleşti.

Bir arama tablosu olarak aşağıdaki dizeyi kullandım (dolgu için kullanılan son 7): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

Program bu dizeyi alır ve bir sayı olarak çözer, ardından sonucu çıkarmak için bit kaydırma özelliğini kullanır.

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

66 bayt + 37 bayt dosya = 103 bayt

Bu, adlandırılan bir ikili dosyayı okur eve base64 kullanmaktan kaçınır.

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

İşte okuma dosyasının bir hexdump (dolgu olmadan):

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 bayt

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

100/4 <28'den bu yana, Nisan ayında (ve daha sonraki aylarda) kaç gün önemli olmadığını fark edebiliriz. Ayrıca, yılın sıçrama olup olmadığını kontrol etmek de gerekli değildir. Sadece Şubat ayında 28 gün olduğunu belirtmek zorundayız (29 değil, çünkü doğrulama sadece 2058 için gerçekleştirilecek), aksi takdirde herhangi bir ay için sadece 31 olabilir.

Diğer yaklaşımlar

Oracle SQL (12c Sürüm 2 ve üstü), 151 bayt

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 Sürüm 2 ve üstü), 137 bayt

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

Her iki çözüm de değiştirirsek 8 bayt daha kısa olabilir (select level l from dual connect by level<=12), xmltable('1to 12'columns l int path'.')ancak Oracle hata nedeniyle bir istisna atar (12.2.0.1.0, 18.3.0.0.0 sürümlerinde test edilmiştir).

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

Her iki çözümde de yıl önemli olduğunda tek durum 2058'dir, bu artık sıçrama değildir, bu nedenle artık olmayan yılı belirtmek için '-1' değişmez değeri kullanılmıştır.

Oracle SQL, 128 bayt

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 bayt

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

Güncelleme

Oracle SQL, 110 bayt

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 bayt

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 bayt

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 bayt

( replaceişlev kullanılabilir hale gelir)

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 bayt

Boru girişi ve kullanımı php -nR:

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

Çevrimiçi deneyin!

PHP , 76 bayt

Komut satırı arg girdisini kullanma 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;

Çevrimiçi deneyin!

Iteratif yaklaşım. Bakılacak tek artık yıl 2 * 29 = 58 olduğundan ve 2058 artık bir yıl olmadığından, Şubat günlerinde artık yılı düşünmeye gerek yoktur. Ve sarmalama bir endişe olmadığından - Nisan ayından itibaren, 25'ten büyük herhangi bir gün 100'ü aşacaktır, sadece ayların geri kalanının sadece 25 günü olduğunu söylüyoruz.

Giriş, komut satırı üzerinden 2 basamaklı bir yıl (program olarak -10 bayt, @Titus'tan öneriye thx).

VEYA:

PHP , 101 bayt

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

Çevrimiçi deneyin!

Yine de yinelemeli ama PHP'nin zaman damgası işlevlerini kullanıyor. Yılı dört basamaklı sayı olarak kabul eder. strtotime()Bunun yerine kullanılması önerisi için Thx to @Titus mktime().


İlk sürüm 4 haneli, ikincisi iki haneli başarısız. Ama güzel bir düşünce. $m<5?$m-2?31:28:25Birinci ve $d=strtotime("$y-1")ikinci için deneyin
Titus

Uhm ... Neden değerlendirmeyi ytırnak içine aldın ?
Titus

@Titus çünkü PHP7, 0 ile işaretlenmiş rakamları sekizlik olarak ele aldığından 08 ve 09 aslında geçerli değildir. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA date () işlevini kullanarak yalnızca 2 basamaklı, sıfır dolgulu bir yıl alabilirsiniz.
640KB

Aylak! elbette.
Titus

1
@Titus, program strtotime()yerine ikinci versiyon kullanılarak güncellenmiş mktime()ve program olarak yeniden uygulanmıştır, -7 bayt. Ayrıca, en çok oylananlar da dahil olmak üzere gönderilerin çoğuna baktım, yılı sadece 2 veya 4 basamak olarak kabul edecekler, bu yüzden bunu gönderene kadar olduğu anlamına geleceğim. Öneriler için tekrar teşekkürler!
640KB

0

PHP, 74 70 bayt

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

yalnızca iki basamaklı yılları kabul eder.

Gwaugh'un düşüncelerini benimsedim ve golf oynadım; benim ilk yaklaşım onun (92 bayt) daha uzundu:

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 4 basamaklı yılların kullanılmasına izin verir.


Pipo ile çalıştırın -nRveya çevrimiçi deneyin .


: Sen% 100 kaldırma ve sadece Tamam 2 basamaklı girişi, alarak 4 bayt kaydedebilir codegolf.stackexchange.com/questions/162137/...
640KB
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.