Коли найближчий спеціальний спільний рік?


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)

1
тільки для довідки, щоб допомогти людям, послідовність, здається, йде 6, 11, 11. IE 6 років після першого - це інше, 11 років після цього - іншого, 11 років після цього - іншого, 6 років після цього - іншого, і т. Д.
Скідсдев,

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, 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 свого роду, додав невелике пояснення
Rod

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

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

Математика, 70 байт

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

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


Це була така відповідь, яку я очікував, створити список і порівняти з цим. Було б цікаво подивитися, чи може хтось скористатися «послідовністю», щоб знайти відповідь.
TheLethalCoder

4
Whaaaa ... PHP б'є Mathematica?
єпископ

Я розігрувався з вашим кодом і придумав це: (n = 1; t = #; Хоча [! DayName @ {t} == понеділок || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Підлога [n / 2]]; t) і чи можете ви переграти це, замінивши на //.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;...}
Брайан Х.

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

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

Треба любити стандартну бібліотеку Рубі! wday==1така ж довжина, як іmonday? і нескінченно менш крутий :). Спеціальна загальна перевірка року проводиться тим, що у спільному році, що починається з понеділка, 1 червня, - це п'ятниця ("п'ятниця" - найменше найменший день!)

На жаль, не так добре шукати в обох напрямках.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.