Data zwielokrotnienia wyzwania

19

(Zainspirowany przez Riddlera z zeszłego tygodnia na FiveThirtyEight.com. Wpis w piaskownicy .)

Biorąc pod uwagę rok między 2001 a 2099, oblicz i zwróć liczbę dni w tym roku kalendarzowym, gdzie mm * dd = yy(gdzie yyjest 2-cyfrowa rok).

Na przykład 2018 ma 5:

  • 18 stycznia (1 * 18 = 18)
  • 9 lutego (2 * 9 = 18)
  • 6 marca (3 * 6 = 18)
  • 3 czerwca (6 * 3 = 18)
  • 2 września (9 * 2 = 18)

Dane wejściowe mogą być dwu- lub czterocyfrowe rokiem numerycznym.

Wyjście powinno być liczbą całkowitą. Opcjonalne końcowe miejsce lub zwrot jest w porządku.

Pełna lista wejść / wyjść:

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

To jest wyzwanie polegające na , wygrywa najniższa liczba bajtów w każdym języku.

Wstępne obliczanie i po prostu wyszukiwanie odpowiedzi jest zwykle wykluczone zgodnie z naszymi zasadami dotyczącymi luk , ale wyraźnie zezwalam na to wyzwanie. Pozwala na kilka interesujących alternatywnych strategii, chociaż prawdopodobnie nie będzie ona najkrótsza na liście 98 99 elementów.

BradC
źródło
Jeśli w twoim języku będzie to łatwiejsze, odpowiedź będzie taka sama bez względu na wiek; 1924 i 2124 mają taką samą liczbę dni jak 2024.
BradC
jeśli wynik mm * dd jest większy niż 100, jest on automatycznie filtrowany?
DanielIndie
@DanielIndie Prawidłowo, nie należy liczyć dat „zawinięcia”. Innymi słowy, 12 grudnia 2044 r.
Się
Ponieważ potrzebujemy tylko ograniczonej liczby danych wejściowych, edytowałem je wszystkie. Zapraszam do przywracania lub formatowania.
Kudłaty
1
@gwaugh Wystarczy, że zdecydujesz, które z nich przyjąć jako prawidłowe dane wejściowe (nie musisz więc wydawać dodatkowych znaków na konwersję między nimi).
BradC

Odpowiedzi:

14

Excel, 48 bajtów

Brawo! Wreszcie coś, w czym Excel jest naprawdę dobry.

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

Pobiera dane z A1 w postaci liczb całkowitych 1-99 reprezentujących rok i wypisuje je tam, gdzie wprowadzasz tę formułę. Jest to formuła tablicowa, więc użyj Ctrl-Shift-Enter zamiast Enter, aby ją wprowadzić.

Wykorzystuje to fakt, że COUNTignoruje błędy, więc wszelkie błędy spowodowane przez miesiąc niepodzielący roku (prowadzące Excel do analizowania czegoś podobnego 2/12.5/25lub przez niepoprawną datę 2/29/58, są po prostu dyskretnie ignorowane.

Sophia Lechner
źródło
1
Bardzo dobrze. Prawdopodobnie warto wspomnieć, że wymaga 2-cyfrowego roku A1. Wprowadzenie 4-cyfrowego roku po prostu powraca 0.
BradC
Prawdziwe! Zmienię to w opisie.
Sophia Lechner,
Powinienem również wspomnieć, że jest to specyficzne dla ustawień regionalnych; zależy to od ustawień regionalnych korzystających z uporządkowania w mm / dd / rr. W przypadku ustawień regionalnych z uporządkowaniem dd / mm / rr odpowiedź będzie oczywiście taka sama jak w bajtach.
Sophia Lechner,
1
Super sprytny; Podoba mi się to, że testujesz tylko 12 kandydatów na randki (jednego na miesiąc), zamiast przeprowadzać je każdego dnia w roku.
BradC
Naprawić rok na jeden skokowy bajt bez skoku?
l4m2
6

Python 2 , 44 bajty

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

Wypróbuj online!

Anonimowa funkcja podana jako obiekt metody. Wytwarza wszystkie produkty (month, day)par (m, d)jak zakodowany k=32*m+dw 0≤m≤12, 0≤d≤31, owijając się. Eliminuje 29-31 lutego, wykluczając je z zasięgu.

xnor
źródło
5

Java (JDK 10) , 65 bajtów

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

Wypróbuj online!

Kredyty

Olivier Grégoire
źródło
Nie pasuje rok przestępny 29*n, więc nie trzeba sprawdzać
14m2
Dzięki za wkład. Mogłem usunąć łącznie 27 bajtów z kilkoma innymi zmianami.
Olivier Grégoire,
1
Zmiana (m==2?29:32)na 29+m%2*3nadal wydaje się dawać wszystkie OKwyniki. Kredyt dla @AsoneTuhid „s Ruby odpowiedź .
Kevin Cruijssen
4

PowerShell , 94 bajty

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

Wypróbuj online!

Pobiera dane wejściowe jako dwucyfrowy rok, a następnie konstruuje forpętlę od 1/1/yeardo 12/9/year(ponieważ 12/10 i kolejne nigdy się nie liczą, a to oszczędza bajt). Każdą iterację zwiększamy o $zile .Monthrazy .Dayjest równa naszemu rokowi wejściowemu. Poza pętlą $zpozostaje w potoku, a dane wyjściowe są niejawne.

Edytuj - to zależy od kultury. Powyższy kod działa dla en-us. Format daty może wymagać zmiany w przypadku innych kultur.

AdmBorkBork
źródło
2
"kultura"? Miałeś na myśli „locale”? ...
user202729
1
@ user202729 Potocznie tak, ale dokumentacja PowerShell nazywa to „kulturą”.
AdmBorkBork
„Kultura” to słowo, którego MS zwykle używa do mówienia o lokalizacji, np. System.Globalization.CultureInfo w .NET.
Sundar - Przywróć Monikę
3

JavaScript (ES6), 91 bajtów

Byłem ciekawy, jak kodowanie twarde porównałoby się do obliczeń iteracyjnych. Jest zdecydowanie dłuższy (patrz odpowiedź @ Shaggy ), ale nie strasznie dłużej.

Edycja : Jest to jednak znacznie dłużej niż bardziej bezpośrednia formuła (patrz odpowiedź @ l4m2 ).

Pobiera dane wejściowe jako liczbę całkowitą w [1..99] .

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

Wypróbuj online!

W jaki sposób?

Lata nieparzyste mają znacznie mniejsze szanse, że mm * dd = rr niż lata. Konkretniej, nieparzyste lata mają od 0 do 3 meczów, podczas gdy parzyste lata mają od 0 do 7 meczów. To pozwala nam kodować każdą parę lat za pomocą zaledwie 5 bitów, które można wygodnie przedstawić jako pojedynczy znak w bazie 36.

Arnauld
źródło
3

Python 2 i 3 , 55 52 bajtów

lambda y:sum(y%i<(y/i<29+i%2*3)for i in range(1,13))

Wypróbuj online!

Asone Tuhid
źródło
3

Narzędzia Bash + GNU , 57

  • 1 bajt zapisany dzięki @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Zauważ, że seqpolecenie zawsze tworzy listę 366 dat - dla lat bez przestępstwa zostanie włączony 1 stycznia następnego roku. Jednak w zakresie dat 2001..2099, MM * DD nigdy nie będzie YY dla 1 stycznia następnego roku dla żadnego z tych lat, więc ten dodatkowy dzień nie wpłynie na wynik.

Wypróbuj online!

Cyfrowa trauma
źródło
Bardzo fajnie - nawet nie wiedziałem date, że podczas matematyki zrobię taką randkę. seqnie potrzebuje spacji po -f, więc możesz zapisać tam bajt.
Sophia Lechner,
3

T-SQL, 123 121 bajtów

Zgodnie z naszymi regułami IO dane wejściowe są pobierane za pomocą istniejącej tabeli t z polem całkowitym y , które zawiera 2-cyfrowy rok.

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

Podział linii służy wyłącznie do odczytu. Zainspirowany głównie rozwiązaniem Excela Sophii .

  • Górny wiersz generuje tablicę liczb 12-elementowych c, która jest połączona z tabelą wprowadzania t .
  • Jeśli to minie, łączę ze sobą kandydata na datę CONCAT(), który dokonuje niejawnej varcharkonwersji typu danych. W przeciwnym razie musiałbym zrobić kilka instrukcji CASTlub CONVERToświadczeń.
  • Znaleziono idealną funkcję oceny ISDATE(), która zwraca 1 dla prawidłowych dat i 0 dla nieprawidłowych dat.
  • Zawiń to w SUMIE i gotowe.
  • EDYCJA : Przeniesiono sprawdzanie podziału liczb całkowitych ( y%m=0) do WHEREklauzuli, aby zaoszczędzić 2 bajty, dzięki @RazvanSocol.

Niestety, nie jest on dużo krótszy niż wersja tabeli odnośników (używając ciągu z wersji osdavison ):

Wyszukiwanie T-SQL, 129 bajtów

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

EDYTOWAĆ : Pozostawiając mój oryginał powyżej, ale możemy zaoszczędzić kilka bajtów, używając kilku nowych funkcji:

  • STRING_SPLIT jest dostępny w MS SQL 2016 i nowszych wersjach.
  • CONCAT_WS jest dostępny w MS SQL 2017 i nowszych wersjach.
  • Jak wyżej, zastąpiony IIFprzezWHERE

MS-SQL 2017, 121 118 bajtów

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, dodatkowa oszustwa edycja: 109 bajtów

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

Wymaga bycia w masterbazie danych, która zawiera tabelę systemową, spt_valuesktóra (po przefiltrowaniu TYPE='P') daje zliczanie liczb od 0 do 2048.

BradC
źródło
Podobnie do innych odpowiedzi, kolejność, w której składam date ( m/d/y), zależy od ustawień lokalizacji instancji SQL. Inne lokalizacje mogą wymagać innej kolejności lub innego separatora, ale nie sądzę, żeby wpłynęło to na długość kodu.
BradC
Wydaje mi się, że zdałeś sobie sprawę, że konwersja „2/29/64” na datę daje 1964-02-29 (nie 2064-02-29), ale biorąc pod uwagę, że lata 2000 i 2100 są wykluczone, to dobry sposób na skrócenie czasu kod.
Razvan Socol
Użycie SPLIT_STRINGzamiast CTE sprowadza go do 120 bajtów. Użycie CONCAT_WSzamiast CONCATzapisuje inny znak, doprowadzając go do 119 bajtów.
Razvan Socol
@RazvanSocol Tak, nie jestem pewien, gdzie jest przerwa między 2-cyfrowymi datami odwzorowanymi na 19xx a 20xx, ale obie dają tę samą odpowiedź. Spróbuję pozostałych dwóch sugestii, dzięki!
BradC
1
Wymień IIFsię WHERE.
Razvan Socol
3

Julia 0,6 , 49 44 42 bajtów

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

Wypróbuj online!

-5 bajtów inspirowanych Rubinową odpowiedzią Asone Tuhid.
-2 bajty zastępujące licznik sumą

Wyjaśnienie:

Dla każdego miesiąca iod 1 do 12 oblicz y/ii sprawdź, czy jest to jeden z dni tego miesiąca. Miesięcy z 31 dni to 1, 3, 5, 7, 8, 10, 12 - tak oni dziwne poniżej 8, a nawet i powyżej 8. Więc albo i%2albo i÷8(co jest 0 dla i <8 i 1 dla I> = 8 tutaj) powinno wynosić 1, ale nie oba - więc XOR je. Jeśli wynik xor jest prawdą, możemy sprawdzić terminy 1:28+3tj 1:31, w przeciwnym razie możemy sprawdzić tylko dat 1:28.

1:28wystarcza na resztę miesięcy (ta poprawka zainspirowana Rubinową odpowiedzią Asone Tuhid ), ponieważ:

  • w lutym jedyną możliwością byłoby 2*29 = 58, ale 2058nie jest to rok przestępny, więc możemy założyć, że luty zawsze ma 28 dni.

  • pozostałe miesiące z 30 dniami to miesiąc 4 i więcej - dla których i*29(i i*30) byłoby powyżej 100, co można zignorować.

Na koniec odliczamy, ile razy y/inależy do tej listy dni (używając sumtutaj boolean ), i zwracamy to.

sundar - Przywróć Monikę
źródło
3

JavaScript, 91 85 82 81 77 bajtów

Pobiera dane wejściowe jako 2-cyfrowy ciąg (lub 1 lub 2 cyfrową liczbę całkowitą).

Wykorzystuje fakt, że new Dateprzejdzie do następnego miesiąca i będzie to kontynuował, jeśli przekażesz mu wartość dzienną przekraczającą liczbę dni w miesiącu, w którym ją przekazałeś, więc przy pierwszej iteracji próbuje zbudować data, yyyy-01-345która staje się yyyy-12-11lub yyyy-12-10w latach przestępnych. Po tym terminie nie musimy sprawdzać dat, ponieważ 12*11+otrzymujemy trzycyfrową liczbę.

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

3 bajty zapisane dzięki Arnauldowi .


Sprawdź to

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>

Kudłaty
źródło
2

Excel, 83 bajty

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

Dane wejściowe są w komórce A1w formacie yyyy. Jest to formuła tablicowa i jest wprowadzana za pomocą Ctrl+ Shift+, Enteraby uzyskać nawiasy klamrowe {}. Jest to dość proste i bez sprytu.

W formule tablicowej DATE(A1,1,0)+ROW(1:366)daje nam tablicę 366 wartości dat. W latach bez przestępstwa będzie to obejmowało 1 stycznia następnego roku, ale nie stanowi to problemu, ponieważ 1*1=1i byłoby liczone jako fałszywie dodatnie, jeśli następny rok będzie, 2001ale ponieważ wymagany zakres roczny jest 2001 - 2099, nigdy nie powstanie jako kwestia.

Jeśli zwędziłeś ten kawałek na prosty ~, formuła jest o wiele łatwiejsza do naśladowania:

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

Próbowałem użyć COUNTIF()zamiast, SUM(IF())ale Excel nawet nie pozwolił mi wprowadzić go jako formuły tablicowej, a tym bardziej dać mi wynik. I tak znaleźć Arkusze Google rozwiązanie używając CountIf()ale ten sam sposób poza tym, że okazał się być 91 bajtów, głównie dlatego, że używa ArrayFormula()zamiast po prostu { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)
Inżynier Toast
źródło
Nie widziałem konsensusu, ale generalnie nie uwzględniłem zewnętrznych nawiasów klamrowych w mojej liczbie bajtów dla programu Excel. Czują się bardziej jak sposób, w jaki Excel formatuje wyświetlanie, niż część formuły. Opinie?
Sophia Lechner,
@SophiaLechner Uwzględniłem je zamiast decydować, jak uwzględnić dodatkowe naciśnięcia klawiszy wymagane do wprowadzenia go jako formuły tablicowej. Jest meta pytanie o to i tylko odpowiedź mówi, że CTRL + ALT + ENTER, komenda będzie liczyć jako 1 naciśnięciem klawisza. Jeśli użyjesz tego samego co vim ( na meta ), to naciśnięcie klawisza będzie liczone jako 1 bajt. Jednak zwykle nie liczę ENTER na końcu wprowadzania formuły jako 1 bajt w innych odpowiedziach.
Inżynier Toast
2

Retina 0.8.2 , 55 bajtów

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

Wypróbuj online! Trwa dwucyfrowy rok; dodaj 1 bajt, aby obsługiwać 4-cyfrowe lata. Objaśnienie: Pierwszy etap po prostu przekształca się w jednoosobowy. Drugi etap rozpoczyna się od dopasowania od 1 do 12 znaków przed pozycją dopasowania, reprezentującą miesiąc, a następnie próbuje się spodziewać całej liczby powtórzeń tego miesiąca. Jednak lookahead zawiera warunek, który wybiera od 27 do 30 kolejnych powtórzeń w zależności od miesiąca. Liczba pasujących pozycji jest wówczas pożądanym wynikiem.

Neil
źródło
2

R , 22 122 bajty

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

Wypróbuj online!

Zdecydowałem się na podejście oparte na tabeli odnośników. Rok wprowadzenia musi składać się z 2 cyfr.

Robert S.
źródło
1
Również w TIO możesz nacisnąć przycisk „link”, a to automatycznie sformatuje odpowiedź za ciebie. Podziękowania dla Dennisa za konfigurację!
Giuseppe,
Można usunąć początkowe if, ponieważ wejście może być albo 2-cyfrowy lub 4-cyfrowy do wyboru (dzięki czemu można wybrać, aby zaakceptować tylko 2-cyfrowe wejście). Ale wygląda na to, że kod uważa, że ​​każdy miesiąc zawiera 31 dni, więc np. 62 (dla 2062) zwraca 1, gdzie powinien zwrócić 0.
Sundar - Przywróć Monikę
2
Źle zrozumiałem. Biorąc to pod uwagę, jestem prawie pewien, że tabela odnośników musiałaby zostać uwzględniona w liczbie bajtów.
ngm
@ngm Nie byłem również pewien, czy należy uwzględnić tabelę odnośników, ale dodam ją do liczby bajtów, aby zachować bezpieczeństwo.
Robert S.
Nadal nie jestem pewien, jakie są wszystkie zasady!
ngm
2

C (gcc), 65 60 59 bajtów

d(a,t,e){for(t=0,e=13;e-->1;)t+=a%e<1&a/e<(e-2?32:29);a=t;}

Port odpowiedzi Java użytkownika user202729 . Wypróbuj online tutaj . Podziękowania dla Jonathana Frecha za grę w golfa 1 bajt.

OOBalance
źródło
a=0,m=13;for(;~> for(a=0,m=13;.
Jonathan Frech
@JathanathanFrech Dzięki za zwrócenie na to uwagi, edytowałem.
OOBalance
2

J , 29 bajtów

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

Wypróbuj online!

Jak to działa

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

Próbowałem ciężko dostać 2 razy rozwiązanie Jelly :)

Dygresja

Jeśli ktoś naprawdę chce zakodować 99-cyfrowe dane, oto trochę informacji:

Podziel 99-cyfrową część na 2 cyfry. Następnie pierwsza cyfra to <4druga <8, co oznacza, że ​​pięć bitów może zakodować dwie liczby. Następnie całe dane mogą być kodowane w 250 bitach lub 32 bajtach.

Bubbler
źródło
2

Python 3 , 158 162 215 241 bajtów

Usunięto 4 Dzięki Stephen za grę w golfa w warunkach warunkowych.

Usunięto 53 podziękowania dla Stephena za wskazanie białej przestrzeni

Usunięto 26 dzięki linkowi udostępnionemu przez Caira

Jestem w tym całkiem nowy. Nie mogłem wymyślić, jak to zrobić bez opisania dni w miesiącu.

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

Wypróbuj online!

akozi
źródło
5
Witamy na stronie i miły pierwszy post! Istnieje kilka sposobów na
grę w
@cairdcoinheringaahing Dzięki za poradę link był bardzo przydatny!
akozi
1
158 bajtów - trochę grałeś w golfa, ale przeważnie miałeś dużą długą linię spacji na trzeciej linii, nie wiem, jak się tam dostało
Stephen
@Stephen Dzięki :) Dodałem twój jako dwie zmiany. Jeden do białych pól, a drugi do gry w golfa.
akozi
(28if Y%4else 29)można skrócić do [29,28][Y%4>0]. Można także skrócić długą listę [a,...]+2*[a,b,a,b,a]. a,b,cmożna dodać do listy parametrów, aby zapisać linię. int(str(Y)[2:])można skrócić do Y%100. Wreszcie, zmienne przeciwne można przeważnie skrócić do lens wyrażeń listowych, co pozwala również nna wykonanie lambda. To daje 118 .
Czarna sowa Kai
2

Naprzód (gforth) , 60 59 bajtów

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

Wypróbuj online!

Ta wersja korzysta z faktu, że nie może być więcej niż 1 pasujący dzień na miesiąc, a rok musi być podzielny przez miesiąc, aby się zgadzał.

Wyjaśnienie

Iteruje po miesiącach, sprawdza, czy rok jest podzielny przez miesiąc i czy iloraz wynosi <31 (28 lutego) Miesiące po marcu nie mogą się zgadzać dla dni większych niż 25, więc możemy po prostu założyć wszystkie miesiące (inne niż luty) mają 31 dni na przeznaczenie układanki.

Objaśnienie kodu

: 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] - Forth ma pojęcie liczb o podwójnej długości, które są przechowywane na stosie jako dwie liczby o pojedynczej długości (w postaci xy, gdzie wartość podwójnej = y * 2^(l) + x gdzie l jest rozmiarem w bitach pojedynczego w czwarta implementacja, nad którą pracujesz).

W tym przypadku porównałem iloraz i resztę do 32 (lub 29) 0. Jeśli reszta była większa niż 0 (rok niepodzielny przez miesiąc), pierwsze podwójne byłoby automatycznie większe niż 32 (lub 29) 0, a wynik byłoby fałszywe. Jeśli reszta to 0, oznacza to skuteczne regularne sprawdzanie ilorazu <= 32 (lub 29)

Dalej (gforth) , 61 bajtów

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

Wypróbuj online!

Zaoszczędzono kilka bajtów, zdając sobie sprawę, że tylko luty ma znaczenie pod względem posiadania prawidłowej liczby dni w miesiącu

Wyjaśnienie

Czwarte (przynajmniej gforth) porównania zwracają -1 dla true i 0 dla 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
reffu
źródło
1

Java (JDK 10) , 79 72 70 bajtów

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

Wypróbuj online!

użytkownik202729
źródło
@Shaggy Thanks! (pozostałość po poprzedniej wersji, w której przeglądam wszystkie d
pliki
Jeśli zmienisz &&na &to ta sama odpowiedź, co odpowiedź Javy Oliviera Grégoire'a, chociaż odpowiedział 19 minut wcześniej.
Kevin Cruijssen
@KevinCruijssen Przypadkowy zbieg okoliczności. Chociaż moja wersja jest nieco gorsza (niepotrzebne użycie potrójnego).
user202729,
1

JavaScript (Node.js) , 108 bajtów

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>


źródło
Wyszukiwanie z użyciem siły brutalnej, miło!
BradC
Witamy w PPCG!
Kudłaty
1

Python 3, 132 bajty

To naprawdę dość długi program, ale pomyślałem, że może być interesujący.

Wszystkie wartości mieszczą się w zakresie od 0 do 7, więc koduję każdą liczbę 3 bitami w długim ciągu binarnym. Próbowałem wkleić nieprzetworzony ciąg binarny do mojego programu python, ale nie mogłem go uruchomić, więc zdecydowałem się na base64 w pliku.

Użyłem następującego ciągu jako tabeli odnośników (końcówka 7 została użyta do wypełnienia): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

Program pobiera ten ciąg i dekoduje go jako liczbę, a następnie używa przesunięcia bitowego w celu wyodrębnienia wyniku.

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

66 bajtów + plik 37 bajtów = 103 bajty

Czyta to plik binarny o nazwie ei unika korzystania z base64.

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

Oto zrzut heksowy odczytanego pliku (bez wypełniania):

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.|
qwr
źródło
1

Oracle SQL, 115 bajtów

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

Możemy zauważyć, że tak naprawdę nie ma znaczenia, ile dni w kwietniu (i późniejszych miesiącach), ponieważ 100/4 <28. Również nie trzeba sprawdzać, czy rok jest przestępny, czy nie. Musimy tylko określić, że w lutym jest 28 dni (nie 29, ponieważ ta walidacja zostanie wykonana tylko dla 2058, co nie jest skokiem), w przeciwnym razie może to być tylko 31 na dowolny miesiąc.

Inne podejścia

Oracle SQL (12c wydanie 2 i nowsze), 151 bajtów

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 wydanie 2 i nowsze), 137 bajtów

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

Zarówno rozwiązanie mogło 8 bajtów krótszy, jeśli wymienimy (select level l from dual connect by level<=12)się xmltable('1to 12'columns l int path'.')jednak Oracle zgłasza wyjątek z powodu błędu (testowane na wersji 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

Jedynym przypadkiem w obu rozwiązaniach, gdy rok ma znaczenie, jest rok 2058, który nie jest skokowy, dlatego dosłowne „-1” zostało użyte do określenia roku nieskokowego.

Oracle SQL, 128 bajtów

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 bajtów

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

Aktualizacja

Oracle SQL, 110 bajtów

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 bajtów

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 bajtów

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 bajtów

( replacefunkcja staje się dostępna)

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
Dr Y Wit
źródło
1

PHP , 73 bajty

Korzystanie z wprowadzania potoku i php -nR:

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

Wypróbuj online!

PHP , 76 bajtów

Za pomocą wprowadzania arg wiersza poleceń 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;

Wypróbuj online!

Podejście iteracyjne. Ponieważ jedynym rokiem przestępnym jest 2 * 29 = 58, a rok 2058 nie jest rokiem przestępnym, nie trzeba brać pod uwagę roku przestępnego w dniach lutowych. A ponieważ owijanie nie stanowi problemu - od kwietnia każdy dzień większy niż 25 przekroczy 100, po prostu mówimy, że reszta miesięcy ma tylko 25 dni.

Dane wejściowe to 2-cyfrowy rok za pomocą wiersza poleceń (-10 bajtów jako program, dzięki za sugestię z @Titus).

LUB:

PHP , 101 bajtów

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

Wypróbuj online!

Wciąż iteracyjny, ale przy użyciu funkcji znaczników czasu PHP. Akceptuje rok jako czterocyfrowy numer. Dziękujemy za @Titus za sugestię użycia strtotime()zamiast mktime().

640 KB
źródło
Pierwsza wersja zawiedzie przez 4-cyfrowe lata, druga zawiedzie przez dwie cyfry. Ale miłe myślenie. Spróbuj $m<5?$m-2?31:28:25pierwszego i $d=strtotime("$y-1")drugiego
Tytusa
Uhm ... Dlaczego wprowadziłeś yewaluację w cudzysłów?
Tytus
@Titus, ponieważ PHP7 traktuje teraz cyfry poprzedzone 0 jako ósemkowe, więc 08 i 09 w rzeczywistości nie są poprawne. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Za pomocą funkcji date () można uzyskać tylko 2-cyfrowy, zerowany rok.
640 KB
Porażka! oczywiście.
Tytus
1
@Titus, zaktualizowano drugą wersję, używając strtotime()zamiast mktime()i ponownie zaimplementowano jako program, -7 bajtów. Spojrzałem również na większość zgłoszeń, w tym te, które uzyskały najwyższy głos, będą przyjmować rok jako 2 lub 4 cyfry, więc przyjmę, że to zależy od autora. Jeszcze raz dziękuję za sugestie!
640 KB
0

PHP, 74 70 bajtów

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

akceptuje tylko dwucyfrowe lata.

I przyjął gwaugh's rozważania i grałem je; moje pierwsze podejście było dłuższe niż jego (92 bajty):

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 pozwala na użycie 4-cyfrowych lat.


Uruchom jako potok z -nRlub wypróbuj je online .

Tytus
źródło
Możesz zapisać 4 bajty, usuwając% 100 i przyjmując tylko 2 cyfry, co jest OK: codegolf.stackexchange.com/questions/162137/…
640KB