Когда ближайший особый общий год?

11

Общий год является годом , что не високосный год , и где первый и последний день года в тот же день. Особый общий год является один , который начинается в понедельник и так заканчивается на понедельник , а также.

Ваша задача состоит в том, чтобы создать программу / функцию, которая при задании года в качестве входных данных находит ближайший специальный общий год и выводит себя, если это общий год. Если год настолько близок к предыдущему, как год к нему, выведите больший.

вход

Целое число, представляющее год для проверки в диапазоне 1600 <= x <= 2100.

Выход

Целое число, представляющее ближайший специальный общий год.

Контрольные примеры

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

Заметки

Все 54 года в данном диапазоне уже показаны в связанной статье Википедии. Я также предоставлю их здесь для справки:

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
источник
1
просто для справки, чтобы помочь людям, последовательность, кажется, идет 6, 11, 11. То есть через 6 лет после первого - еще один, через 11 лет - еще один, через 11 лет - еще один, через 6 лет - еще один и т. Д.
Skidsdev
6
@ Mayube Не совсем. Фактическая последовательность: «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 и 6, 11, 6, 6, 11, 6)
Мартин Эндер
1
Поскольку календарь повторяется каждые 400 лет, соответствующая (периодическая) часть последовательности равна «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 ". Я буду впечатлен, если кто-нибудь может сохранить байты с этим, из-за трех нарушений.
Мартин Эндер
5
Поздравляю на 2к для меня! : 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 dayВторая часть этого определения является избыточной. Все не високосные годы начинаются и заканчиваются в один и тот же день и составляют ровно 52 недели и один день (365 дней).
Джон Гордон

Ответы:

1

Желе , 30 байт

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

Монадическая ссылка, берущая и возвращающая целочисленный год.

Попробуйте онлайн! или посмотрите набор тестов .

Как?

Подобно другим ответам, он строит список лет, требуемых для входной области из приращений, и находит максимальный год минимальной абсолютной разницы от входных данных.

“Þıİ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)
Джонатан Аллан
источник
9

PHP, 67 байт

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

Попробуйте онлайн!

или же

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

Попробуйте онлайн!

расширенный

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

Дата

Йорг Хюльсерманн
источник
1
Сохранить байт:$i=($i<1)-$i;
Кристоф
8

Python 2 , 129 124 118 байт

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)

Попробуйте онлайн! или Попробуйте все тестовые случаи.
Сначала генерируется (реверсируется) последовательность a, затем 2401 - input_yearиспользуется в качестве начального значения, которое вычитается из последовательности.
Таким образом, список oбудет содержать различия между всеми общими годами и входными данными, ближайший год будет числом, ближайшим к нулю (положительному или отрицательному), затем будет извлечен (min, key=abs)и добавлен обратно к входным данным.

С datetime, 119 байтов

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*

Попробуйте онлайн!

прут
источник
Создает ли это список лет на основе последовательности?
TheLethalCoder
@TheLethalCoder вроде, добавил небольшое объяснение
Род
7

05AB1E , 41 байт

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

Попробуйте онлайн!

объяснение

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
источник
5

JavaScript (ES6), 77 байт

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

Нил
источник
4

Mathematica, 70 байт

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

Создает список всех специальных общих лет до 5040 года (= 7!), А затем находит ближайший к входу, беря максимум в случае связи.

Мартин Эндер
источник
Это был тот ответ, который я ожидал, составить список и сравнить с ним. Было бы интересно посмотреть, сможет ли кто-нибудь использовать «последовательность», чтобы найти ответ.
TheLethalCoder
4
Вааааа ... PHP превосходит Mathematica?
Епископ
Я поиграл с вашим кодом и придумал следующее: (n = 1; t = #; пока [! DayName @ {t} == понедельник || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Floor [n / 2]]; t) & вы можете сыграть в гольф, заменив while на //.t/; и т.д? Я пытался, но я не могу ...
J42161217
3

Java 7, 217 байт

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));}

Объяснение:

Попробуй это здесь.

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)
Кевин Круйссен
источник
если x всегда будет 1, почему бы просто не удалить int c () {} и изменить int d(int y, int x){}наd(int y){int x = 1;...}
Brian H.
@BrianH. Потому что я делаю рекурсивный вызов, который использует x, поэтому, если я сбрасываю его 1каждый раз в начале метода, xэто неверно, и рекурсивный вызов потерпит неудачу.
Кевин Круйссен
1

C #, 183 байта

Чтобы немного покататься, вот реализация, которую я сделал самостоятельно. Я почти уверен, что это все еще может быть в гольфе, так что если кто-то хочет, не стесняйтесь, отправляйте как новый ответ.

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();}

Попробуйте онлайн!

Полная / отформатированная версия, также показывает все выходные данные для заданного диапазона при запуске.

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
источник
1

Рубин, 145 байт

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})}

Определяет лямбду, принимая в качестве входного значения начальный год - f[2017] => 2018

Должен любить стандартную библиотеку Ruby! wday==1такой же длины, какmonday? и бесконечно менее крутой :). Специальная проверка общего года выполняется тем, что в обычном году, начинающемся с понедельника, 1 июня, это пятница («пятница» - наименее короткое название дня!)

К сожалению, поиск не очень хорош в обоих направлениях.

Chowlett
источник