Quelle est l'année commune spéciale la plus proche?

11

Une année commune est une année qui n'est pas une année bissextile et où le premier et le dernier jour de l'année sont le même jour. Une année commune spéciale est une année qui commence un lundi et se termine donc un lundi également.

Votre défi est de créer un programme / une fonction qui, une fois donnée une année, trouvera l'année commune spéciale la plus proche, se produisant elle-même s'il s'agit d'une année commune. Si l'année est aussi proche de celle qui la précède que celle qui la suit, sortez la plus grande.

Contribution

Un entier représentant l'année de test dans la plage 1600 <= x <= 2100.

Production

Un entier représentant l'année commune spéciale la plus proche.

Cas de test

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

Remarques

Les 54 années dans la fourchette donnée sont déjà présentées dans l'article Wikipedia lié. Je vais également les fournir ici pour référence:

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
la source
1
juste pour référence pour aider les gens, la séquence semble aller 6, 11, 11. IE 6 ans après le premier est un autre, 11 ans après c'est un autre, 11 ans après c'est un autre, 6 ans après c'est un autre, etc.
Skidsdev
6
@Mayube Pas tout à fait. La séquence réelle est "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 "(notez les 12 et les 6, 11, 6, 6, 11, 6)
Martin Ender
1
Étant donné que le calendrier se répète tous les 400 ans, la partie pertinente (périodique) de la séquence est "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 ". Je serai impressionné si quelqu'un peut économiser des octets avec cela, en raison des trois irrégularités.
Martin Ender
5
Félicitations pour 2k pour moi! : 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 dayLa deuxième partie de cette définition est redondante. Toutes les années non bissextiles commencent et se terminent le même jour, soit exactement 52 semaines et un jour (365 jours).
John Gordon

Réponses:

1

Gelée , 30 octets

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

Un lien monadique prenant et retournant une année entière.

Essayez-le en ligne! ou consultez une suite de tests .

Comment?

Tout comme les autres réponses, cela construit la liste des années requises pour le domaine d'entrée à partir des incréments et trouve l'année maximale de la différence absolue minimale par rapport à l'entrée.

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

PHP, 67 octets

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

Essayez-le en ligne!

ou

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

Essayez-le en ligne!

Étendu

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

Date

Jörg Hülsermann
la source
1
Enregistrer un octet:$i=($i<1)-$i;
Christoph
8

Python 2 , 129 124 118 118 octets

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)

Essayez-le en ligne! ou Essayer tous les cas de test
D'abord, la séquence est générée (inversée) a, puis 2401 - input_yearest utilisée comme valeur de départ à soustraire sur la séquence.
De cette façon, la liste ocontiendra les différences entre toutes les années communes et l'entrée, l'année la plus proche sera le nombre le plus proche de zéro (positif ou négatif), puis sera extraite avec (min, key=abs)et ajoutée à l'entrée.

Avec datetime, 119 octets

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*

Essayez-le en ligne!

Barre
la source
Cela génère-t-il la liste des années en fonction de la séquence?
TheLethalCoder
@TheLethalCoder, a ajouté une petite explication
Rod
7

05AB1E , 41 octets

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

Essayez-le en ligne!

Explication

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
la source
5

JavaScript (ES6), 77 octets

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
la source
4

Mathematica, 70 octets

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

Génère une liste de toutes les années communes spéciales jusqu'à l'année 5040 (= 7!) Puis trouve la plus proche de l'entrée, en prenant le maximum en cas d'égalité.

Martin Ender
la source
C'était le genre de réponse que j'attendais, générer la liste et comparer à cela. Il serait intéressant de voir si quelqu'un peut utiliser la "séquence" pour trouver une réponse.
TheLethalCoder
4
Whaaaa ... PHP bat Mathematica?
évêque
Je jouais avec votre code et j'ai trouvé ceci: (n = 1; t = #; While [! DayName @ {t} == Monday || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Floor [n / 2]]; t) & pouvez-vous jouer au golf en le remplaçant par //.t/; etc? J'ai essayé mais je ne peux pas ...
J42161217
3

Java 7, 217 octets

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

Explication:

Essayez-le ici.

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
la source
si x va toujours être 1, pourquoi ne pas simplement supprimer int c () {} et passer int d(int y, int x){}àd(int y){int x = 1;...}
Brian H.
@BrianH. Parce que je fais un appel récursif qui utilise x, donc si je le réinitialise à 1chaque fois en haut de la méthode, il xest incorrect et l'appel récursif échouera.
Kevin Cruijssen
1

C #, 183 octets

Pour lancer un peu la balle, voici une implémentation que j'ai faite moi-même. Je suis à peu près sûr qu'il peut encore être analysé, donc si quelqu'un veut se sentir libre de publier une nouvelle réponse.

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

Essayez-le en ligne!

Version complète / formatée, cela montre également toutes les sorties pour la plage donnée lors de l'exécution.

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
la source
1

Rubis, 145 octets

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

Définit un lambda en prenant l'année de début en entrée - f[2017] => 2018

Je dois aimer la bibliothèque standard Ruby! wday==1est de la même longueur monday?et infiniment moins cool :). La vérification spéciale de l'année commune se fait par le fait que dans une année commune commençant le lundi, le 1er juin est un vendredi ("vendredi" étant le nom du jour le plus court!)

Malheureusement, ce n'est pas si bon de chercher dans les deux sens.

Chowlett
la source