Kapan tahun umum khusus terdekat?

11

Sebuah tahun yang umum adalah tahun yang tidak tahun kabisat dan di mana hari pertama dan terakhir tahun ini adalah pada hari yang sama. Sebuah tahun khusus umum adalah salah satu yang dimulai pada hari Senin dan berakhir pada hari Senin juga.

Tantangan Anda adalah membuat program / fungsi yang ketika diberi tahun sebagai input menemukan tahun umum khusus terdekat, menghasilkan sendiri jika itu adalah tahun yang umum. Jika tahun sedekat mungkin dengan tahun sebelumnya seperti tahun berikutnya menghasilkan yang lebih besar.

Memasukkan

Integer yang mewakili tahun untuk diuji dalam kisaran 1600 <= x <= 2100.

Keluaran

Integer yang mewakili tahun umum khusus terdekat.

Uji kasus

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

Catatan

Semua 54 tahun dalam kisaran yang diberikan sudah ditampilkan di artikel Wikipedia yang ditautkan. Saya juga akan memberikannya di sini untuk referensi:

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
sumber
1
hanya untuk referensi untuk membantu orang keluar, urutannya muncul 6, 11, 11. IE 6 tahun setelah yang pertama adalah yang lain, 11 tahun setelah yang lain, 11 tahun setelah yang lain, 6 tahun setelah yang lain, dll.
Skidsdev
6
@ Mayube Tidak cukup. Urutan aktual adalah "6, 11, 11, 6, 11, 11, 6, 11, 11, 6, 12, 11, 11, 6, 11, 11, 6, 11, 11, 6, 11, 11, 12, 11 , 6, 11, 11, 6, 11, 11, 6, 11, 6, 6, 11, 6, 11, 11, 6, 11, 11, 6, 11, 11, 11, 6, 11, 11, 11, 6, 11 , 11, 6, 11, 11, 6 "(perhatikan tanggal 12 dan 6, 11, 6, 6, 11, 6)
Martin Ender
1
Karena kalender berulang setiap 400 tahun, bagian (periodik) yang relevan dari urutannya adalah "6, 11, 11, 6, 11, 11, 11, 11, 11, 11, 11, 11, 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, 11, 6 , 11, 11 ". Saya akan terkesan jika ada yang bisa menyimpan byte dengan ini, karena tiga penyimpangan.
Martin Ender
5
Selamat atas 2k untuk saya! : 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 dayBagian kedua dari definisi itu berlebihan. Semua tahun non-kabisat dimulai dan berakhir pada hari yang sama, tepatnya 52 minggu dan satu hari (365 hari).
John Gordon

Jawaban:

1

Jelly , 30 byte

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

Tautan monadik yang mengambil dan mengembalikan tahun bilangan bulat.

Cobalah online! atau lihat test suite .

Bagaimana?

Sama seperti jawaban lain, ini membangun daftar tahun yang diperlukan untuk domain input dari kenaikan, dan menemukan tahun maksimal perbedaan absolut minimal dari 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)
Jonathan Allan
sumber
9

PHP, 67 Bytes

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

Cobalah online!

atau

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

Cobalah online!

Diperluas

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

tanggal

Jörg Hülsermann
sumber
1
Simpan satu 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)

Cobalah online! atau Coba semua uji kasus
Pertama, urutan dihasilkan (dibalik) aktif a, kemudian 2401 - input_yeardigunakan sebagai nilai awal untuk dikurangi atas urutan.
Dengan cara ini daftar oakan berisi perbedaan antara semua tahun umum dan input, tahun terdekat akan menjadi angka yang terdekat dengan nol (positif atau negatif), kemudian akan diekstraksi dengan (min, key=abs)dan ditambahkan kembali ke input.

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

Cobalah online!

tongkat
sumber
Apakah ini menghasilkan daftar tahun berdasarkan urutan?
TheLethalCoder
@TheLethalCoder agak, menambahkan sedikit penjelasan
Rod
7

05AB1E , 41 byte

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

Cobalah online!

Penjelasan

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

Mathematica, 70 byte

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

Buat daftar semua tahun umum umum hingga tahun 5040 (= 7!) Dan kemudian temukan yang terdekat dengan input, ambil nilai maksimum jika terjadi seri.

Martin Ender
sumber
Ini adalah jenis jawaban yang saya harapkan, menghasilkan daftar dan membandingkannya. Akan menarik untuk melihat apakah ada yang bisa menggunakan "urutan" untuk menemukan jawaban.
TheLethalCoder
4
Whaaaa ... PHP mengalahkan Mathematica?
Uskup
Saya bermain-main dengan kode Anda dan menghasilkan ini: (n = 1; t = #; Sementara [! DayName @ {t} == Senin || LeapYearQ @ {t}, n ++; t = # - (- 1 ) ^ n * Lantai [n / 2]]; t) & dapatkah Anda golf ini dengan mengganti ketika dengan //.t/; dll? Saya mencoba tetapi saya tidak bisa ...
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));}

Penjelasan:

Coba di sini.

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
sumber
jika x selalu menjadi 1, mengapa tidak hanya menghapus int c () {} dan ubah int d(int y, int x){}ked(int y){int x = 1;...}
Brian H.
@BrianH. Karena saya melakukan panggilan rekursif yang menggunakan x, jadi jika saya mengatur ulang 1setiap kali di bagian atas metode, xsalah dan panggilan rekursif akan gagal.
Kevin Cruijssen
1

C #, 183 byte

Untuk menggulirkan bola sedikit, inilah implementasi yang saya lakukan sendiri. Saya cukup yakin itu masih bisa diturunkan jadi jika ada yang ingin bebas memposting sebagai jawaban baru.

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

Cobalah online!

Versi Lengkap / Terformat, ini juga menampilkan semua output untuk rentang yang diberikan saat dijalankan.

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

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

Menentukan lambda yang mengambil tahun awal sebagai input - f[2017] => 2018

Harus menyukai perpustakaan standar Ruby! wday==1panjangnya sama monday?dan jauh lebih tidak keren :). Pemeriksaan tahun umum khusus dilakukan oleh fakta bahwa pada tahun yang sama mulai Senin, 1 Juni adalah Jumat ("Jumat" adalah nama hari yang sama-pendeknya!)

Sayangnya, pencarian di kedua arah tidak begitu baik.

Chowlett
sumber