Kiedy jest najbliższy specjalny wspólny rok?

11

Wspólny rok to rok, który nie jest rokiem przestępnym i gdzie pierwszy i ostatni dzień w roku są tego samego dnia. Specjalny wspólny rok to taki, który rozpoczyna się w poniedziałek i tak kończy się w poniedziałek, jak również.

Wyzwanie polega na utworzeniu programu / funkcji, która po podaniu roku jako najbliższego specjalnego specjalnego roku, generuje wynik, jeśli jest to wspólny rok. Jeśli rok jest zbliżony do roku przed nim, jak rok obok, należy wydać większy.

Wejście

Liczba całkowita reprezentująca rok, w którym ma być testowany zakres 1600 <= x <= 2100.

Wynik

Liczba całkowita reprezentująca najbliższy specjalny wspólny rok.

Przypadki testowe

2017 -> 2018
2018 -> 2018
1992 -> 1990
1600 -> 1601
2100 -> 2103
1728 -> 1731 (lies between 1725 and 1731)

Notatki

Wszystkie 54 lata w podanym zakresie są już pokazane w powiązanym artykule w Wikipedii. Podam je również tutaj w celach informacyjnych:

1601, 1607, 1618, 1629, 1635, 1646, 1657, 1663, 1674, 1685, 1691
1703, 1714, 1725, 1731, 1742, 1753, 1759, 1770, 1781, 1787, 1798
1810, 1821, 1827, 1838, 1849, 1855, 1866, 1877, 1883, 1894, 1900
1906, 1917, 1923, 1934, 1945, 1951, 1962, 1973, 1979, 1990
2001, 2007, 2018, 2029, 2035, 2046, 2057, 2063, 2074, 2085, 2091
2103 (Needed for 2097 to 2100)
TheLethalCoder
źródło
1
tylko w celach informacyjnych, aby pomóc ludziom wyjść, sekwencja wydaje się iść 6, 11, 11. IE 6 lat po pierwszej jest kolejna, 11 lat po niej jest kolejna, 11 lat po niej jest kolejna, 6 lat po niej jest kolejna itd.
Skidsdev
6
@Mayube Niezupełnie. Rzeczywista sekwencja to „6, 11, 11, 6, 11, 11, 6, 11, 11, 6, 12, 11, 11, 6, 11, 11, 6, 11, 11, 6, 11, 12, 11 , 6, 11, 11, 6, 11, 11, 6, 11, 6, 6, 11, 6, 11, 11, 6, 11, 11, 6, 11, 11, 6, 11, 11, 6, 11 , 11, 6, 11, 11, 6 "(zwróć uwagę na 12 i 6, 11, 6, 6, 11, 6)
Martin Ender
1
Ponieważ kalendarz powtarza się co 400 lat, odpowiednią (okresową) częścią sekwencji jest „6, 11, 11, 6, 11, 11, 6, 11, 11, 6, 12, 11, 11, 6, 11, 11 , 6, 11, 11, 6, 11, 12, 11, 6, 11, 11, 6, 11, 11, 6, 11, 6, 6, 11, 6, 11, 11, 6, 11, 11, 6 , 11, 11 ”. Będę pod wrażeniem, jeśli ktoś może dzięki temu zaoszczędzić bajty z powodu trzech nieprawidłowości.
Martin Ender
5
Gratulacje dla mnie 2k! : P
TheLethalCoder
1
a year that is not a leap year and where the first and last day of the year are on the same dayDruga część tej definicji jest zbędna. Wszystkie lata bez przestępowania rozpoczynają się i kończą tego samego dnia, trwając dokładnie 52 tygodnie i jeden dzień (365 dni).
John Gordon

Odpowiedzi:

1

Galaretka , 30 bajtów

“Þıİs|9ṗ[¿¶F’ṃ“©€¿‘⁽£d;+\ạÐṂ⁸Ṁ

Monadyczny link przyjmujący i zwracający liczbę całkowitą.

Wypróbuj online! lub zobacz pakiet testowy .

W jaki sposób?

Podobnie jak inne odpowiedzi, ta buduje listę lat wymaganą dla domeny wejściowej z przyrostów i znajduje maksymalny rok minimalnej absolutnej różnicy od danych wejściowych.

“Þıİs|9ṗ[¿¶F’ṃ“©€¿‘⁽£d;+\ạÐṂ⁸Ṁ - Main link: number y
                   ⁽£d         - augmented base 250 literal = 1601
“Þıİs|9ṗ[¿¶F’                  - base 250 literal = 20129386383114231907032071
              “©€¿‘            - code page index list = [6,12,11]
             ṃ                 - base decompression = [6,11,11,6,11,11,6,11,11,6,12,11,11,6,11,11,6,11,11,6,11,12,11,6,11,11,6,11,11,6,11,6,6,11,6,11,11,6,11,11,6,11,11,6,11,11,6,11,11,6,11,11,6,12]
                      ;        - concatenate = [1601,6,11,11,6,11,11,6,11,11,6,12,11,11,6,11,11,6,11,11,6,11,12,11,6,11,11,6,11,11,6,11,6,6,11,6,11,11,6,11,11,6,11,11,6,11,11,6,11,11,6,11,11,6,12]
                       +\      - reduce with addition = [1601,1607,1618,1629,1635,1646,1657,1663,1674,1685,1691,1703,1714,1725,1731,1742,1753,1759,1770,1781,1787,1798,1810,1821,1827,1838,1849,1855,1866,1877,1883,1894,1900,1906,1917,1923,1934,1945,1951,1962,1973,1979,1990,2001,2007,2018,2029,2035,2046,2057,2063,2074,2085,2091,2103]
                            ⁸  - link's left argument, y
                          ÐṂ   - filter keep if maximal:
                         ạ     -   absolute difference
                             Ṁ - maximum (alternatively tail, Ṫ, since increasing)
Jonathan Allan
źródło
9

PHP, 67 bajtów

for(;date(LN,mktime(0,0,0,1,1,$y=$argn+$i))>1;)$i=($i<1)-$i;echo$y;

Wypróbuj online!

lub

for(;date(LN,strtotime("1/1/".$y=$argn+$i))>1;)$i=($i<1)-$i;echo$y;

Wypróbuj online!

Rozszerzony

for(;
date(LN,mktime(0,0,0,1,1,$y=$argn+$i)) # N is 1 for Monday and L is 0 for Non leap year
>1;) # loop so long as expression is not 1
  $i=($i<1)-$i; # set $i 0,1,-1,2,-2 ...
echo$y; # Output Year

data

Jörg Hülsermann
źródło
1
Zapisz bajt:$i=($i<1)-$i;
Christoph
8

Python 2 , 129 124 118 bajtów

a=[11,11,6]*13
a[29:29]=a[19:19]=12,
a[10:10]=6,6
n=input()
o=[2401-n]
for i in a*2:o+=o[-1]-i,
print n+min(o,key=abs)

Wypróbuj online! lub Wypróbuj wszystkie przypadki testowe
Najpierw sekwencja jest generowana (odwrócona) a, a następnie 2401 - input_yearużywana jako wartość początkowa do odjęcia od sekwencji.
W ten sposób lista obędzie zawierać różnice między wszystkimi wspólnymi latami a danymi wejściowymi, najbliższy rok będzie liczbą najbliższą zeru (dodatnią lub ujemną), a następnie zostanie wyodrębniony za pomocą (min, key=abs)i ponownie dodany do danych wejściowych.

Z datetime119 bajtów

lambda i:i+min([y-i for y in range(2200,1500,-1)if datetime(y,1,1).weekday()<1and y%400],key=abs)
from datetime import*

Wypróbuj online!

Pręt
źródło
Czy generuje to listę lat na podstawie sekwencji?
TheLethalCoder
@ TheLethalCoder niejako dodałem małe wyjaśnienie
Rod
7

05AB1E , 41 bajtów

6xD<Š)•HΘ%A°,SΔA)u•3вè.pO0¸ì1601+DI-ÄWQϤ

Wypróbuj online!

Wyjaśnienie

6xD<Š)                                     # push the list [11,6,12]
      •HΘ%A°,SΔA)u•                        # push the number 20129386383114231907032071
                   3в                      # convert to a base-3 digit list
                     è                     # use this to index into the first list
                      .p                   # get list of prefixes
                        O                  # sum each sublist
                         0¸ì               # prepend 0
                            1601+          # add 1601 to each
                                 D         # duplicate
                                  I-       # subtract input from each
                                    Ä      # calculate absolute value
                                     WQÏ   # keep only the years that have the 
                                           # smallest absolute difference from input
                                        ¤  # get the last one
Emigna
źródło
5

JavaScript (ES6), 77 bajtów

f=(y,z=y,d=m=>new Date(y,m,!m||31).getDay()-1)=>d(0)|d(11)?f(z<y?z-1:z+1,y):y
<input type=number value=2001 oninput=o.textContent=f(+this.value)><pre id=o>2001

Neil
źródło
4

Mathematica, 70 bajtów

Max@Nearest[Select[Range[7!],!LeapYearQ@{#}&&DayName@{#}==Monday&],#]&

Generuje listę wszystkich specjalnych wspólnych lat do roku 5040 (= 7!), A następnie znajduje najbliższy do danych wejściowych, biorąc maksimum w przypadku remisu.

Martin Ender
źródło
To była odpowiedź, jakiej się spodziewałem: wygeneruj listę i porównaj z nią. Byłoby interesujące sprawdzić, czy ktoś może użyć „sekwencji”, aby znaleźć odpowiedź.
TheLethalCoder
4
Whaaaa ... PHP bije Mathematica?
biskup
Bawiłem się z twoim kodem i wymyśliłem to: (n = 1; t = #; While [! DayName @ {t} == Monday || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Floor [n / 2]]; t) i czy możesz zagrać w golfa, zastępując // // t /; itp? Próbowałem, ale nie mogę ...
J42161217
3

Java 7, 217 bajtów

import java.util.*;int c(int y){return d(y,1);}int d(int y,int x){Calendar c=Calendar.getInstance(),d=Calendar.getInstance();c.set(y,0,1);d.set(y,11,31);return c.get(7)==d.get(7)&c.get(7)==2?y:d(y+x,x>0?-++x:-(--x));}

Wyjaśnienie:

Wypróbuj tutaj.

import java.util.*;                   // Required import for Calendar

int c(int y){                         // Method with integer parameter and integer return-type
  return d(y,1);                      //  Call second method with additional parameter
}                                     // End of method (1)

int d(int y,int x){                   // Method (2) with two integer parameters and integer return-type
  Calendar c=Calendar.getInstance(),  //  Create two Calendar instances
           d=Calendar.getInstance();
  c.set(y,0,1);                       //  Set one to 01 January yyyy
  d.set(y,11,31);                     //  and one to 31 December yyyy
  return c.get(7)==d.get(7)           //  If both are the same day of the week
         &c.get(7)==2?                //  and it is a Monday:
          y                           //   Return the input-year
         :                            //  Else:
          d(y+x,                      //   Recursive-call with year + `x`
                x>0?-++x:-(--x));     //   and change `x` to the next to check
                                      //   +1,-2,+3,-4,+5,-6,etc.
}                                     // End of method (2)
Kevin Cruijssen
źródło
jeśli x zawsze będzie wynosić 1, to po prostu usuń int c () {} i zmień int d(int y, int x){}nad(int y){int x = 1;...}
Brian H.
@BrianH. Ponieważ wykonuję wywołanie rekurencyjne, które wykorzystuje x, więc jeśli zresetuję go za 1każdym razem na początku metody, xjest niepoprawne, a wywołanie rekurencyjne zakończy się niepowodzeniem.
Kevin Cruijssen
1

C #, 183 bajtów

Aby trochę rzucić piłkę, oto moja własna implementacja. Jestem prawie pewien, że nadal można go odłożyć w golfa, więc jeśli ktoś chce napisać jako nową odpowiedź.

namespace System.Linq{n=>Enumerable.Range(1,9999).Where(y=>!DateTime.IsLeapYear(y)&(int)new DateTime(y,1,1).DayOfWeek==1).GroupBy(y=>Math.Abs(n-y)).OrderBy(g=>g.Key).First().Last();}

Wypróbuj online!

Wersja pełna / sformatowana, pokazuje również wszystkie wyjścia dla danego zakresu po uruchomieniu.

namespace System.Linq
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int, int> f = n =>
                Enumerable.Range(1, 9999)
                          .Where(y => !DateTime.IsLeapYear(y)
                                    & (int)new DateTime(y, 1, 1).DayOfWeek == 1)
                          .GroupBy(y => Math.Abs(n - y))
                          .OrderBy(g => g.Key)
                          .First()
                          .Last();

            for (int y = 1600; y <= 2100; ++y)
            {
                Console.WriteLine($"{y} -> {f(y)}");
            }

            Console.ReadLine();
        }
    }
}
TheLethalCoder
źródło
1

Rubin, 145 bajtów

f=->i{i+(1.upto(i).map{|m|Time.new(y=i+m).monday?&&Time.new(y,6).friday?? m:Time.new(y=i-m).monday?&&Time.new(y,6).friday?? -m :nil}.find{|a|a})}

Definiuje lambda przyjmującą rok początkowy jako dane wejściowe - f[2017] => 2018

Uwielbiam standardową bibliotekę Ruby! wday==1ma taką samą długość monday?i jest nieskończenie mniej fajny :). Specjalna wspólna kontrola roku polega na tym, że we wspólnym roku rozpoczynającym się w poniedziałek, 1 czerwca jest piątek („piątek” to nazwa najkrótszego dnia!)

Niestety wyszukiwanie w obu kierunkach nie jest tak dobre.

Chowlett
źródło