가장 가까운 특별 연도는 언제입니까?


11

일반 년은 윤년 어디 올해의 첫 번째와 마지막 날이 같은 날에있는없는 년입니다. 특별 일반 년 일이 월요일에 끝나는 월요일에 그래서 시작은 물론이다.

당신의 과제는 입력으로 1 년을 주었을 때 가장 가까운 특수 공통 연도를 찾아서 공통 연도 인 경우 스스로 출력하는 프로그램 / 함수를 만드는 것입니다. 연도가 이전 연도에 가까운 경우 다음 연도가 큰 연도를 출력합니다.

입력

범위에서 테스트 할 연도를 나타내는 정수 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 년 후 또 다른 것입니다.
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 참고)
Martin Ender

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
나를 위해 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 day그 정의의 두 번째 부분은 중복입니다. 윤년이 아닌 모든 연도는 같은 날에 시작하고 끝나며 정확히 52 주와 1 일 (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;
Christoph

8

파이썬 (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에 모든 공통 연도와 입력 값의 차이가 포함되고 가장 가까운 연도는 0에 가장 가까운 숫자 (양수 또는 음수)가되며 추출 (min, key=abs)하여 입력에 다시 추가합니다.

datetime119 바이트,

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

자바 스크립트 (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&],#]&

최대 5050 년 (= 7!)까지의 모든 특수 공통 연도 목록을 생성 한 다음 타이의 경우 최대 값을 사용하여 입력에 가장 가까운 연도를 찾습니다.


이것은 내가 기대했던 일종의 대답이었습니다. 목록을 생성하고 비교하십시오. 누군가가 "시퀀스"를 사용하여 답을 찾을 수 있는지 보는 것이 흥미로울 것입니다.
TheLethalCoder

4
Wahaaa ... PHP가 Mathematica를 이겼습니까?
감독

나는 당신의 코드를 가지고 놀고 있었고 이것을 생각해 냈습니다 : (n = 1; t = #; While [! DayName @ {t} == Monday || LeapYearQ @ {t}, n ++; t = #-(-1 ) ^ n * Floor [n / 2]]; t) & //.t/; 기타? 시도했지만 할 수 없습니다 ...
J42161217

3

자바 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재설정하면 잘못되어 재귀 호출이 실패합니다. 1x
Kevin Cruijssen


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

Ruby 표준 라이브러리를 좋아해야합니다! wday==1같은 길이입니다monday? 무한히 시원합니다 :). 6 월 1 일 월요일부터 시작하는 공통 연도는 금요일 ( "금요일"이 가장 짧은 요일 이름 임)이라는 사실에 의해 특별 공통 연도 점검이 수행됩니다.

불행히도 양방향 검색이 그다지 좋지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.