Wann ist das nächste gemeinsame Jahr?

11

Ein gemeinsames Jahr ist ein Jahr, das kein Schaltjahr ist und in dem der erste und der letzte Tag des Jahres am selben Tag liegen. Ein besonderes gemeinsames Jahr beginnt an einem Montag und endet auch an einem Montag.

Ihre Herausforderung besteht darin, ein Programm / eine Funktion zu erstellen, die, wenn ein Jahr als Eingabe angegeben wird, das nächste spezielle gemeinsame Jahr findet und sich selbst ausgibt, wenn es ein gemeinsames Jahr ist. Wenn das Jahr dem vorhergehenden so nahe kommt wie das daneben, wird das größere ausgegeben.

Eingang

Eine Ganzzahl, die das Jahr darstellt, gegen das im Bereich getestet werden soll 1600 <= x <= 2100.

Ausgabe

Eine Ganzzahl, die das nächste gemeinsame Sonderjahr darstellt.

Testfälle

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

Anmerkungen

Alle 54 Jahre im angegebenen Bereich sind bereits im verlinkten Wikipedia-Artikel aufgeführt. Ich werde sie auch hier als Referenz bereitstellen:

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
quelle
1
Nur als Referenz, um den Menschen zu helfen, scheint die Sequenz zu gehen 6, 11, 11. IE 6 Jahre nach dem ersten ist ein anderer, 11 Jahre danach ist ein anderer, 11 Jahre danach ist ein anderer, 6 Jahre danach ist ein anderer usw.
Skidsdev
6
@ Mayube Nicht ganz. Die tatsächliche Sequenz ist "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 "(beachten Sie die 12er und die 6, 11, 6, 6, 11, 6)
Martin Ender
1
Da sich der Kalender alle 400 Jahre wiederholt, ist der relevante (periodische) Teil der Sequenz "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 ". Ich bin beeindruckt, wenn jemand aufgrund der drei Unregelmäßigkeiten damit Bytes sparen kann.
Martin Ender
5
Herzlichen Glückwunsch zu 2k für mich! : 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 dayDer zweite Teil dieser Definition ist redundant. Alle Nicht-Schaltjahre beginnen und enden am selben Tag und sind genau 52 Wochen und ein Tag (365 Tage) lang.
John Gordon

Antworten:

1

Gelee , 30 Bytes

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

Eine monadische Verbindung, die ein ganzzahliges Jahr nimmt und zurückgibt.

Probieren Sie es online aus! oder sehen Sie sich eine Testsuite an .

Wie?

Ähnlich wie bei anderen Antworten wird aus den Inkrementen die Liste der für die Eingabedomäne erforderlichen Jahre erstellt und das maximale Jahr mit minimaler absoluter Differenz zur Eingabe ermittelt.

“Þıİ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
quelle
9

PHP, 67 Bytes

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

Probieren Sie es online aus!

oder

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

Probieren Sie es online aus!

Erweitert

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

Datum

Jörg Hülsermann
quelle
1
Speichern Sie ein Byte:$i=($i<1)-$i;
Christoph
8

Python 2 , 129 124 118 Bytes

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)

Probieren Sie es online aus! oder Alle Testfälle ausprobieren
Zuerst wird die Sequenz generiert (umgekehrt) aund dann 2401 - input_yearals Startwert verwendet, der über die Sequenz subtrahiert wird.
Auf diese Weise enthält die Liste odie Unterschiede zwischen allen gemeinsamen Jahren und der Eingabe. Das nächste Jahr ist die Zahl, die der Null am nächsten liegt (positiv oder negativ). Anschließend wird sie extrahiert (min, key=abs)und zur Eingabe hinzugefügt.

Mit datetime119 Bytes

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*

Probieren Sie es online aus!

Stange
quelle
Erzeugt dies die Liste der Jahre basierend auf der Sequenz?
TheLethalCoder
@ TheLethalCoder irgendwie, fügte eine kleine Erklärung hinzu
Rod
7

05AB1E , 41 Bytes

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

Probieren Sie es online aus!

Erläuterung

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
quelle
5

JavaScript (ES6), 77 Byte

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
quelle
4

Mathematica, 70 Bytes

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

Erzeugt eine Liste aller gemeinsamen Sonderjahre bis zum Jahr 5040 (= 7!) Und findet dann das der Eingabe am nächsten liegende Jahr, wobei bei einem Gleichstand das Maximum verwendet wird.

Martin Ender
quelle
Dies war die Art von Antwort, die ich erwartet hatte, die Liste zu generieren und damit zu vergleichen. Es wäre interessant zu sehen, ob jemand die "Sequenz" verwenden kann, um eine Antwort zu finden.
TheLethalCoder
4
Whaaaa ... PHP schlägt Mathematica?
Bischof
Ich habe mit Ihrem Code herumgespielt und mir Folgendes ausgedacht: (n = 1; t = #; While [! DayName @ {t} == Montag || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Floor [n / 2]]; t) & können Sie dies Golf spielen, indem Sie es durch //.t/ ersetzen; etc? Ich habe es versucht, aber ich kann nicht ...
J42161217
3

Java 7, 217 Bytes

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

Erläuterung:

Probieren Sie es hier aus.

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
quelle
Wenn x immer 1 sein wird, warum nicht einfach int c () {} entfernen und int d(int y, int x){}zud(int y){int x = 1;...}
Brian H.
@ BrianH. Da ich einen rekursiven Aufruf durchführe, der verwendet xwird 1, xist es falsch , wenn ich ihn jedes Mal oben in der Methode zurücksetze , und der rekursive Aufruf würde fehlschlagen.
Kevin Cruijssen
1

C #, 183 Bytes

Um den Ball ein wenig ins Rollen zu bringen, habe ich hier eine eigene Implementierung durchgeführt. Ich bin mir ziemlich sicher, dass es immer noch gespielt werden kann, wenn jemand sich frei fühlen möchte, als neue Antwort zu posten.

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

Probieren Sie es online aus!

Vollversion / Formatierte Version, hier werden auch alle Ausgaben für den angegebenen Bereich angezeigt, wenn sie ausgeführt werden.

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
quelle
1

Ruby, 145 Bytes

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

Definiert ein Lambda, das das Startjahr als Eingabe verwendet - f[2017] => 2018

Ich muss die Ruby-Standardbibliothek lieben! wday==1ist genauso lang monday?und unendlich weniger cool :). Die spezielle Prüfung des gemeinsamen Jahres erfolgt durch die Tatsache, dass in einem gemeinsamen Jahr, das am Montag beginnt, der 1. Juni ein Freitag ist ("Freitag" ist der gleich kürzeste Tagesname!).

Leider ist es nicht so gut, in beide Richtungen zu suchen.

Chowlett
quelle