Quando è l'anno comune più vicino?


11

Un anno comune è un anno che non è un anno bisestile e in cui il primo e l'ultimo giorno dell'anno sono nello stesso giorno. Un anno comune speciale è quello che inizia un lunedì e finisce anche un lunedì.

La tua sfida è quella di creare un programma / funzione che quando viene dato un anno come input trova l'anno comune speciale più vicino, producendo se stesso se è un anno comune. Se l'anno è vicino a quello precedente come quello accanto ad esso produce quello più grande.

Ingresso

Un numero intero che rappresenta l'anno da testare nell'intervallo 1600 <= x <= 2100.

Produzione

Un numero intero che rappresenta l'anno comune speciale più vicino.

Casi test

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

Appunti

Tutti i 54 anni in un determinato intervallo sono già mostrati nell'articolo Wikipedia collegato. Li fornirò anche qui come riferimento:

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
solo come riferimento per aiutare le persone, la sequenza sembra andare 6, 11, 11. IE 6 anni dopo il primo è un altro, 11 anni dopo quello è un altro, 11 anni dopo quello è un altro, 6 anni dopo quello è un altro, ecc.
Skidsdev

6
@Mayube Non proprio. La sequenza effettiva è "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 "(nota il 12 e il 6, 11, 6, 6, 11, 6)
Martin Ender,

1
Poiché il calendario si ripete ogni 400 anni, la parte (periodica) rilevante della sequenza è "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 ". Sarò impressionato se qualcuno può salvare byte con questo, a causa delle tre irregolarità.
Martin Ender,

5
Complimenti per 2k per me! : 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 seconda parte di tale definizione è ridondante. Tutti gli anni non bisestili iniziano e terminano lo stesso giorno, con una durata esatta di 52 settimane e un giorno (365 giorni).
John Gordon,

Risposte:


1

Gelatina , 30 byte

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

Un collegamento monadico che prende e restituisce un anno intero.

Provalo online!o vedere una suite di test .

Come?

Proprio come le altre risposte, questo crea l'elenco degli anni richiesti per il dominio di input dagli incrementi e trova l'anno massimo di minima differenza assoluta dall'input.

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

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

Provalo online!

o

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

Provalo online!

allargato

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

Data


1
Salva un byte:$i=($i<1)-$i;
Christoph

8

Python 2 , 129 124 118 byte

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)

Provalo online! oppure Prova tutti i casi di test
Innanzitutto, la sequenza viene generata (invertita) a, quindi 2401 - input_yearviene utilizzata come valore iniziale da sottrarre sulla sequenza.
In questo modo l'elenco oconterrà le differenze tra tutti gli anni comuni e l'input, l'anno più vicino sarà il numero più vicino a zero (positivo o negativo), quindi verrà estratto con(min, key=abs) e aggiunto nuovamente all'input.

Con datetime, 119 byte

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*

Provalo online!


Questo genera l'elenco di anni basato sulla sequenza?
TheLethalCoder

@TheLethalCoder kinda, ha aggiunto una piccola spiegazione
Rod,

7

05AB1E , 41 byte

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

Provalo online!

Spiegazione

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


4

Mathematica, 70 byte

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

Genera un elenco di tutti gli anni comuni speciali fino all'anno 5040 (= 7!) E quindi trova quello più vicino all'ingresso, prendendo il massimo in caso di pareggio.


Questo era il tipo di risposta che mi aspettavo, generare l'elenco e confrontarlo con quello. Sarebbe interessante vedere se qualcuno può usare la "sequenza" per trovare una risposta.
TheLethalCoder

4
Whaaaa ... PHP batte Mathematica?
vescovo,

Stavo giocando con il tuo codice e ho pensato a questo: (n = 1; t = #; While [! DayName @ {t} == Monday || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Floor [n / 2]]; t) & puoi giocare a golf sostituendolo con //.t/; eccetera? Ci ho provato ma non ci riesco ...
J42161217

3

Java 7, 217 byte

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

Spiegazione:

Provalo qui.

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)

se x sarà sempre 1, perché non semplicemente rimuovere int c () {} e passare int d(int y, int x){}ad(int y){int x = 1;...}
Brian H.

@BrianH. Perché eseguo una chiamata ricorsiva che utilizza x, quindi se la reimposta 1ogni volta all'inizio del metodo, xnon è corretto e la chiamata ricorsiva fallirebbe.
Kevin Cruijssen,


1

C #, 183 byte

Per far rotolare un po 'la palla, ecco un'implementazione che ho fatto da solo. Sono abbastanza sicuro che possa ancora essere golfato, quindi se qualcuno vuole sentirsi libero di pubblicare come nuova risposta.

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

Provalo online!

Versione completa / formattata, mostra anche tutti gli output per l'intervallo dato quando eseguito.

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

Rubino, 145 byte

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

Definisce un lambda che prende l'anno di inizio come input - f[2017] => 2018

Devi amare la libreria standard di Ruby! wday==1è della stessa lunghezza monday?e infinitamente meno cool :). La speciale verifica dell'anno comune è fatta dal fatto che in un anno comune a partire da lunedì 1 giugno è un venerdì ("venerdì" è il nome del giorno più corto!)

Sfortunatamente, non è così bravo a cercare in entrambe le direzioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.