最も近い特別共通年はいつですか?


11

一般的な年はうるう年とどこ年の最初と最後の日が同じ日にあるではない年です。特別な共通今年はうまくとして月曜日に終了し、月曜日にとして始まるものです。

あなたの課題は、入力として年を指定すると、最も近い特別な共通の年を見つけ、それが共通の年である場合にそれ自体を出力するプログラム/関数を作成することです。年がその前の年に近い場合、その次の年が大きい年を出力します。

入力

範囲内でテストする年を表す整数1600 <= x <= 2100

出力

最も近い特別な一般年を表す整数。

テストケース

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

ノート

指定された範囲内の54年はすべて、リンクされたWikipediaの記事にすでに表示されています。また、参照用にここで提供します。

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に注意)
マーティン・エンダー

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 "。3つの不規則性のために、これで誰でもバイトを節約できるなら感心します。
マーティンエンダー

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その定義の2番目の部分は冗長です。うるう年以外のすべての年は、ちょうど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;
クリストフ

8

パイソン2129の 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

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
Whaaaa ... PHPはMathematicaに勝っていますか?
ビショップ

私はあなたのコードで遊んでいて、これを思いつきました:(n = 1; t =#; While [!DayName @ {t} == Monday || 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;...}
ブライアンH.

@BrianH。を使用する再帰呼び出しを行うため、メソッドの先頭で毎回xリセットすると、正しくなくなり、再帰呼び出しは失敗します。1x
ケビン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.