Заранее с Новым годом, 2016!


40

Ваш вклад будет целым числом от 1970 до 2090 (включительно), представляющим год. Ваша программа должна выводить следующий год, в который день нового года приходится на тот же день недели, что и год ввода.

Тестовые случаи:

Ниже приведены примеры входов и выходов

2001 => 2007
2047 => 2058
2014 => 2020
1970 => 1976
1971 => 1982
1977 => 1983
2006 => 2012

Бонус 20%: Выведите день недели Нового года

2001 => 2007 (Mon)
2047 => 2058 (Tue)
2014 => 2020 (Wed)
1970 => 1976 (Thu)
1971 => 1982 (Fri)
1977 => 1983 (Sat)
2006 => 2012 (Sun)

30% Бонус: ВыходAdvance Happy New Year, <year>

2010 => Advance Happy New Year, 2016

Бонус 50%: делайте оба вышеуказанных бонуса

2010 => Advance Happy New Year, 2016 (Fri)

Напишите программу, которая читает входные данные из STDIN или принимает аргументы командной строки, или функцию, которая принимает аргумент.

Примечание: пожалуйста, добавьте ссылку, чтобы проверить ваш код, если это возможно.

Leaderboard:


6
Я чувствую, что каждая проблема с датами требует подсчета високосных лет в качестве подзадачи, и она становится устаревшей.
xnor


@xnor Если бы это было не так, это было бы просто +7. Т.е. "слишком широк"
Эрик Аутгольфер,

@EriktheGolfer Нет. Когда я написал этот комментарий, мой ответ был принят.
Деннис

Ответы:


1

Желе, 9 байт

%4*3%7+5+

Это монадическая цепочка, которая принимает целочисленный аргумент командной строки в качестве входных данных. Он использует мой(x+5+(x%4)**3%7) алгоритм.

Попробуй это здесь . Хотя это текущая версия Jelly, она также работает в этой версии , которая предшествует вызову. (Спасибо @Dennis!)


Это потрясающе! Я могу подтвердить, что это работает с этой версией интерпретатора Jelly, который предшествовал вызову.
Деннис

31

Mathematica, 45 37 27 24 байта

#+5[6,6,11][[#~Mod~4]]&

Улучшения благодаря @ MartinBüttner (10 байтов) и @ChipHurst (еще 3 байта).


7
Ух ты. Никто, кажется, не заметил эту модель, но она работает.
Линн

4
Вот немного более короткая версия:#+5[6,6,11][[#~Mod~4]]&
Чип Херст

@ChipHurst очень умный с 5[6, 6, 11][[0]]:)
Мартин

18

CJam, 21 12 11 байт

{_9587Cb=+}

@martin нашел очень простой метод!

Попробуй это здесь .

РЕДАКТИРОВАТЬ: Спасибо, Деннис!


1
@Mauris Не могли бы вы добавить объяснение?
Васу Адари

@Vasu: Этот код является анонимной функцией, которая реализует тот же 5 6 6 11трюк, который использовался в других ответах, но список закодирован как «цифры 9587 в базе 12» .
Линн

Понял, спасибо. Я хотел, чтобы вы добавили объяснение, чтобы люди, которые проверяют ваш ответ, могли понять, как он работает с языком.
Васу Адари

10

gs2, 12 байт

V@¶4☻s%☺♀i50

Перевод моего ответа CJam. Кодируется в CP437 как обычно. Попробуйте онлайн !


Ссылка идет на код, который создает 2spooky4me, и если я вырезал и вставил код выше, я получу неправильный год: imgur.com/VAkXT0k (под "неправильным годом" я имею в виду, что я получаю на год раньше, чем намеченный год)
question_asker

Я забыл байт. Попробуй сейчас.
Линн

Я тоже редактировал ссылку.
Линн

Круто, теперь это работает
question_asker

8

JavaScript (ES6), 50 49 20 байт (без бонусов)

a=>a+[5,6,6,11][a%4]

Алгоритм @martin оказался намного меньше, поэтому я пошел с ним.

Я выбрал математический подход, потому что JavaScript имеет тенденцию быть многословным. Код достаточно короткий, чтобы бонусы только увеличивали его.

Вот мой предыдущий ответ (49 байт) и мой оригинальный ответ (50 байт):

F=(a,b=a)=>((a+--a/4|0)-(b++/4+b|0))%7?F(++a,b):b

F=(a,b=a)=>(f=c=>(c--+c/4|0)%7)(a)-f(++b)?F(a,b):b

Они работают, беря год и вычисляя число (0-6), чтобы представить «начальный день года». Поскольку диапазон дат для этого испытания находится в диапазоне лет, которые следуют простым правилам високосного года (без пропусков в 2000 году), рассчитать его довольно просто. Тогда это просто вопрос сравнения вперед, чтобы найти годы, которые начинаются с одинакового значения. Рекурсия оказалась самым лаконичным способом сделать это.


7

Pyth, 14 12 11 байтов

+QC@"♣♠♠♂"Q

Четыре байта в строке должны быть 05 06 06 0B.

РЕДАКТИРОВАТЬ: Спасибо, FryAmTheEggman!

РЕДАКТИРОВАТЬ: Спасибо, Деннис!


6

JavaScript (ES6), 104 байта - бонус 50% = 52

y=>eval('for(a=0;a!=(b=(new Date(""+y++)+"").slice(0,3));a=a||b)`Advance Happy New Year, ${y} (`')+b+")"

объяснение

y=>
  eval(`                  // eval enables for loop without {} or return
    for(
      a=0;                // a = first day of input year
      a!=                 // check if the day of the current year is equal to the first
        (b=(new Date(     // b = day of current year
          ""+y++)+"")     // cast everything as strings!
            .slice(0,3)); // the first 3 letters of the date string are the day name
      a=a||b              // set a to the day on the first iteration
    )

      // return the string
      \`Advance Happy New Year, \${y} (\`
  `)+b+")"

Тест


6

Машинный код Z80, 12 байт

Процедура Z80, которая будет сохранена 0000h, вызывается со входом in HL, и все остальные регистры очищаются:

.org 0000h
              ; Bytes   ; Explanation
  ;---------------------------------------------------------------
  DEC B       ; 05      ; 
  LD B, 6     ; 06 06   ;   
  DEC BC      ; 0B      ;
  LD A, 3     ; 3E 03   ;   A = 3
  AND L       ; A5      ;   A = input & 3
  LD E, A     ; 5F      ;   A = input & 3     DE = input & 3
  LD A, (DE)  ; 1A      ;   A = [input & 3]   DE = input & 3
  LD E, A     ; 5F      ;   A = [input & 3]   DE = [input & 3]
  ADD HL, DE  ; 19      ;   HL = input + offset
  RET         ; C9      ;

Первые три инструкции являются «NOP», но они проиндексированы как данные позже в коде. По возвращении, выход в HL.


Да, я добавил это к почте.
Линн

Не выглядит правильным для 2097 и 2098 годов, которые требуют дополнений 7 и 12, соответственно.
Тоби Спейт

1
ОП говорит, что год ввода гарантированно будет в диапазоне 1970-2090.
Линн

6
Мне действительно не нравятся вопросы, которые меняются после того, как я ответил!
Тоби Спейт

2
Вам разрешено указывать, что вход находится DEи, следовательно, вы можете использовать LD A, 3; AND E; LD L, A; LD L, (HL);?
Нил

5

Питон 3, 140 100 102 84,5 154 * 0,5 = 77 байт

Возможно, я мог бы написать лучшее решение с помощью алгоритма Сакамото, но сейчас это подойдет

Я был прав. Вот реализация с использованием алгоритма Сакамото.

def s(y):
 d=lambda j:(j+j//4)%7
 for i in range(y,y+15):
  if d(i)==d(y-1):return"Advance Happy New Year, %d (%s)"%(-~i,"SMTWTFSuouehranneduit"[d(i)::7])

Объяснение:

def day_of_the_week(year):
    return (year + year//4 - 1 + 0 + 1) % 7
    # The month code for January is 0, and you add 1 from January *1*.
    # The -1 is to correct for starting on Saturday 
    # and so that it cancels out the 1 from January 1.

def new_years(this_year):
# But in Sakamoto's algorithm, if the month is January or February, we must subtract 1.
    weekdays = "SunMonTueWedThuFriSat"
    for item in range(this_year, this_year + 15):
        if day_of_the_week(this_year - 1) == day_of_the_week(item):
            day = weekdays[day_of_the_week(item)*3 : day_of_the_week(item)*3+3]
            return "Advance Happy New Year, %d (%s)"%(item + 1, day)
        # So we subtract from every year we check, including this_year
        # And add 1 back in at the end
        # And print the greeting, the year, and the corresponding day of the week

Я обновил вопрос. Вам не нужно проверять век лет.
Васу Адари

1
Как насчет w="SMTWTFSuouehranneduit"печати w[d(i)::7]?
Линн

4

Серьезно, 35 17 байт

[5,6,6,11] трюк спасает день.

4,;)%[5,6,6,11]E+

Попробуйте онлайн

Объяснение:

4,;)%[5,6,6,11]E+
4,;)%              push input, input % 4
     [5,6,6,11]E   push (input % 4)th element of [5,6,6,11]
                +  add to the input

Старая версия:

,;;D`45/*≈7@%`;╝ƒ╗35*r+`╛ƒ╜=`M1@íu+

Попробуйте онлайн

Объяснение:

,;;D`45/*≈7@%`;╝ƒ╗35*r+`╛ƒ╜=`M1@íu+
,;;                                  push 3 copies of the input (n)
   D                                 decrement the top copy of n
    `45/*≈7@%`;╝                     push Sakamoto's algorithm as a function and save a copy in register 1
                ƒ╗                   call Sakamoto's algorithm function and save result in register 0
                  35*r+              push [n, n+1, ..., n+14]
                       `    `M       map the function:
                        ╛ƒ╜=           push Sakamoto's algorithm, call, push 1 if equal to value in register 0 else 0
                              1@í    get the index of the first 1
                                 u+  increment and add n

Алгоритм Сакамото:

45/*≈7@%
45/*      multiply by 5/4
    ≈     floor
     7@%  mod 7

4

C, 31 байт

После редактирования вопроса, который ограничивает диапазон ввода до 1970-2090, это становится довольно тривиальным:

f(x){return"\5\6\6\13"[x%4]+x;}

Без не високосных лет столетия есть простая последовательность 5,6,6,11 интервалов для первого повторения того же дня.

Полное решение исходной задачи (не ограничено 2090), 90 байт:

f(x){return(x-1)%100>89&&(x+9)/100%4?"\6\14\5\6\6\6\6\7\14\6"[x%10]+x:"\5\6\6\13"[x%4]+x;}

Тестовая программа:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    while (*++argv)
        printf("Advance Happy New Year, %d\n", f(atoi(*argv)));
    return !argc;
}

Тестовый забег:

$ ./66656 2001 2047 2014 1970 1971 1977 2006
Advance Happy New Year, 2007
Advance Happy New Year, 2058
Advance Happy New Year, 2020
Advance Happy New Year, 1976
Advance Happy New Year, 1982
Advance Happy New Year, 1983
Advance Happy New Year, 2012

4

R 143 136 * 0,5 = 68 байт

G=function(y)strftime(paste(y,1,1,sep='-'),'%a')
d=seq(y<-scan(),y+14);sprintf("Advance Happy New Year, %i (%s)",d[G(d)==(w=G(y))][2],w)

Используйте %Aдля полного имени дня вместо `% a, зависит от желаемого состояния.

R 120 * 0,7 = 84 байта

G=function(y)as.POSIXlt(paste(y,1),,"%Y %j")$wday
d=seq(y<-scan(),y+14);cat("Advance Happy New Year,",d[G(d)==G(y)][2])

R, 90 байт

G=function(y)as.POSIXlt(paste(y,1),,"%Y %j")$wday
d=seq(y<-scan(),y+14);d[G(d)==G(y)][2]

Все ответы выше являются производной работой, основанной на ответе @plannapus. Использование ;разделителя, чтобы избежать необходимости sourceфайла или запустить его как скрипт в командной строке.


1
+1 Я совсем забыла weekdays, милая.
plannapus

@plannapus Спасибо :) (Я посчитал переводы строк, фактически спросил файловую систему, так как у меня под windows это 2 байта, но у меня нет конца строки в конце, который должен иметь файл POSIX, поэтому справедливо сохранить его таким образом на самом деле)
Тенсибай

3

R 145 байт -50% -> 72,5

y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%a");x=y+1;while(F(x)!=F(y))x=x+1;sprintf("Advance Happy New Year, %i (%s)",x,F(x))

Примеры:

> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%a");x=y+1;while(F(x)!=F(y))x=x+1;sprintf("Advance Happy New Year, %i (%s)",x,F(x))
1: 2006
2: 
Read 1 item
[1] "Advance Happy New Year, 2012 (Sun)"
> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%a");x=y+1;while(F(x)!=F(y))x=x+1;sprintf("Advance Happy New Year, %i (%s)",x,F(x))
1: 1977
2: 
Read 1 item
[1] "Advance Happy New Year, 1983 (Sat)"
> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%a");x=y+1;while(F(x)!=F(y))x=x+1;sprintf("Advance Happy New Year, %i (%s)",x,F(x))
1: 2014
2: 
Read 1 item
[1] "Advance Happy New Year, 2020 (Wed)"

R, 97 байт (без бонуса)

y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%w");x=y+1;while(F(x)!=F(y))x=x+1;x

С отступом, с новыми строками:

y = scan() #Takes input from stdin
F = function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%w") #Year to Weekday
x = y+1
while(F(x) != F(y)) x = x+1
x

Тестовые случаи:

> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%w");x=y+1;while(F(x)!=F(y))x=x+1;x
1: 1977
2: 
Read 1 item
[1] 1983
> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%w");x=y+1;while(F(x)!=F(y))x=x+1;x
1: 2006
2: 
Read 1 item
[1] 2012
> y=scan();F=function(y)format(as.POSIXct(paste(y,1),,"%Y %j"),"%w");x=y+1;while(F(x)!=F(y))x=x+1;x
1: 2016
2: 
Read 1 item
[1] 2021

Я не понимаю этого желания встать на одну уродливую линию, возврат каретки не самый дорогой, чем ;...
Tensibai

Вы можете сохранить 1 символ, удалив первый y=scan;и используя, x=y<-scan()+1я думаю,
Tensibai

и вы можете сохранить еще семь, используя в as.POSIXlt(paste(y,1),,"%Y %j")$wdayкачестве своего тела функций
Tensibai

@Tensibai, если вы не поместите его в одну строку и вставите его непосредственно в консоль, scanво второй строке будет отображаться как ввод. x=y<-scan()+1с 2014 года в качестве стандартного ввода даст вам х = 2015 и у = 2015 (т.е. присвоение y <- scan()+1) , и если вы попытаетесь сделать x=1+y<-scan()это даст вам ошибку ( Error in 1 + y <- scan() : target of assignment expands to non-language object) , потому что он пытается назначить scan()на 1+y.
plannapus

@Tensibai Что касается вашего последнего совета, результатом ...$wdayбудет номер дня недели: но здесь мне нужно название дня недели, чтобы я мог напечататьAdvance Happy New Year, 2012 (Sun)
plannapus

3

VBA, 130 * 0,50 = 65 байт

Sub k(y)
i=1
Do While Weekday(y+i)<>Weekday(y)
i=i+1
Loop
MsgBox "Advance Happy New Year," &y+i &WeekdayName(Weekday(y+i))
End Sub

VBA делает поиск дней недели таким простым ... Если бы это было не так уж многословно.


3

PHP, 120 139 байт - 50% = 60 байт

Функциональный подход:

$s=strtotime;for($d=date(D,$s(($y=$argv[1]).$_="-1-1"));$d!=date(D,$s(++$y.$_)););echo"Advance Happy New Year, $y ($d)";

Принимает один ввод из командной строки, например:

$ php ahny.php 2001

Путь ООП, как всегда, длиннее (143 байта):

$s=strtotime;for($d=date(D,$s($x=($y=$argv[1])."-1-1"));$d!=date(D,$s(++$y."-1-1")););echo"Advance Happy New Year, $y ($d)";

Правки

  • Сохранено 18 байт . Вместо добавления одного года с использованием модификатора PHP +1year, я теперь просто увеличиваю данный год.
  • Сохранено 1 байт путем сохранения -1-1в переменной.

3

C, оценка 53 52 (104 байта)

f(x){x+="0116"[x%4];printf("Advance Happy New Year, %d (%.3s)",x-43,"MonTueWedThuFriSatSun"+x*5/4%7*3);}

Идея заимствована у Тоби Спейта ; добавлен бонусный дисплей дня недели.

Укоротил строку, сдвинув коды символов в более удобный диапазон. Нужно было выбрать правильную величину сдвига (например, 43), чтобы заставить x*5/4%7работать код вычисления короткого рабочего дня .


I take it your character code stuff restricts this to ASCII-compatible encodings?
Toby Speight

Yes. The codes should be greater than 31, so the minimal number to add to the codes would be 27, giving the string " !!&".
anatolyg

2

Mathematica, 145 * 50% = 74 73.5 72.5 bytes

d=DateValue;StringForm["Advance Happy New Year, `` (``)",NestWhile[#+1&,(a=#)+1,#!=#2&@@DateObject@{{a},{#}}~d~"DayName"&],{a}~d~"DayNameShort"]&

Uses standard date functions.


2

Pyth, 23 bytes

L%+/b4b7.VQIqyby-Q1+1bB

Doesn't qualify for any of the bonuses.

Try it here.

Similar to the pure python answer.

                        - Q = eval(input()) (autoassigned)
L                       - y = lambda b:
   /b4                  - b floordiv 4
  +   b                 - + b
 %     7                - mod 7


        .VQ             - for b in range(Q, infinate):
           Iqyby-Q1     - if y(b) == y(Q-1):
                   +1b  - print b+1
                      B - break

2

Java, (1-.2)*323 (1-.5)*350 348 339 = 258.4 175 174 169.5 bytes

import java.text.*;class D{public static void main(String[]a){long y=new Long(a[0]);int i=0;for(;!s(y).equals(s(y+(++i))););System.out.printf("Advance Happy New Year, %d (%s)",y+i,s(y+i));}static String s(long y){try{return new SimpleDateFormat("E").format(new SimpleDateFormat("d/M/yyyy").parse("1/1/"+y));}catch(Exception e){}return"";}}

Ugh.

Ungolfed:

import java.text.*;
class D{
    public static void main(String[]a){
        long y=new Long(a[0]);
        int i=0;
        for(;!s(y).equals(s(y+(++i))););
        System.out.printf("Advance Happy New Year, %i (%s)",y+i,s(y+i));
    }
    static String s(long y){
        try{
            return new SimpleDateFormat("E").format(new SimpleDateFormat("d/M/yyyy").parse("1/1/"+y));
        }catch(Exception e){}
        return"";
    }
}

Try it online!

Thanks to @Kenney for pointing out that I could shorten with new Long and printf! :D


long y=new Long(a[0]) saves 6 (12) bytes, and using printf saves another 3 (6).
Kenney

2

GNU coreutils, 52 51 49 bytes

(98 bytes program - 50% bonus)

seq -f$1-1-1\ %gyear 28|date -f- +'Advance Happy New Year, %Y (%a)'|sed /`date -d$1-1-1 +%a`/!d\;q

Input is from command-line argument, and output is to stdout.

Explanation

# generate 28 input years from $1 + 1 onwards (28 is always enough)
seq -f '$1-1-1 %g year' 28
|
# convert all of these as potential outputs
date -f- +'Advance Happy New Year, %Y (%a)'
|
 # Select the first one where the dayname matches that of input year
sed "/`date -d$1-1-1 +%a`/!d;q"

Test run:

All locale settings can be C or POSIX.

$ for i in 2001 2047 2014 1970 1971 1977 2006; do ./66656.sh $i; done
Advance Happy New Year, 2007 (Mon)
Advance Happy New Year, 2058 (Tue)
Advance Happy New Year, 2020 (Wed)
Advance Happy New Year, 1976 (Thu)
Advance Happy New Year, 1982 (Fri)
Advance Happy New Year, 1983 (Sat)
Advance Happy New Year, 2012 (Sun)

Limitation: this only works up to year 2147485519 (though the question is now changed to permit a lower limit).


2

MATL, 28 bytes

i0:14+t1tI$YO8H$XO!st1)=f2))

Example

>> matl i0:14+t1tI$YO8H$XO!st1)=f2))
> 1970
1976

Code explained

i           % input year
0:14+       % vector with that year and the next 14
t1tI$YO     % first day of each year
8H$XO       % transform into three letters specifying weekday
!s          % sum those three letters to reduce to unique numbers
t1)         % get first of those numbers (corresponding to input year)
=f2)        % find index of second matching
)           % index with that to obtain output year

2

Perl 6,  70  23 bytes

{($^a+1...{[==] ($a,$_).map: {Date.new(:year($_)).day-of-week}})[*-1]} # 70 bytes

{($_ X+5,6,6,11)[$_%4]} # 23 bytes

usage:

for «2001 2047 2014 1970 1971 1977 2006 2010» {
  printf "%d => %d\n", $_, {($_ X+5,6,6,11)[$_%4]}( $_ )
}
2001 => 2007
2047 => 2058
2014 => 2020
1970 => 1976
1971 => 1982
1977 => 1983
2006 => 2012
2010 => 2016


2

Japt, 12 bytes

U+"♣♠♠♂"cU%4

As with the Pyth answer, the four bytes in the string should be 05 06 06 0B. Try it online!

U+"♣♠♠♂"cU%4  // Implicit: U = input integer
  "♣♠♠♂"      // Take this string.
        cU%4  // Take the char code at U%4.
U+            // Add U.
              // Implicit: output last expression

2
Thanks for this Christmas gift of a bounty! But can someone tell me how I earned it?
ETHproductions

I looked through the history. Apparently the OP attempted to bounty an answer, but forgot to award the bounty, so Community chose to pass half the reputation onto this answer (I think it bases its choice on recent upvotes).

2

Jelly, 14 bytes

%4=0,3×-,5S++6

Try it online!

Until today, Jelly had no array indexing, so the above will have to do. Since the latest commit, array indexing has been implemented as , giving the following solution (10 bytes).

ị6,6,11,5+

Try it online!


1
I think Jelly can spare 7 characters for 10~16 constants.
lirtosiast


1

C# (6.0) .Net Framework 4.6 173 Bytes - 30% = 121.1 Bytes

void n(int y)=>Console.Write($"Advance Happy New Year, {Enumerable.Range(1,15).Select(i=>new DateTime(y+i,1,1)).First(x=>x.DayOfWeek==new DateTime(y,1,1).DayOfWeek).Year}");



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.