提前祝您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读取输入或接受命令行参数,或者编写一个带有参数的函数。

注意:如果可能,请添加链接以测试您的代码。

排行榜:


6
我觉得每个单日期挑战都需要将requires年计算作为一个子问题,而且它已经过时了。
xnor 2015年


@xnor如果不是这种情况,那只会是+7。即“太宽泛”
暴民埃里克(Erik the Outgolfer)

@EriktheGolfer否。当我写评论时,我的回答是被接受的。
丹尼斯

Answers:


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
哦,哇 似乎没有人注意到这种模式,但是可以解决。
林恩(Lynn)2015年

4
这是一个略短的版本:#+5[6,6,11][[#~Mod~4]]&
Chip Hurst 2015年

@ChipHurst非常聪明5[6, 6, 11][[0]]:)
马丁

18

CJam,21 12 11字节

{_9587Cb=+}

@martin发现了一个非常简单的方法!

在这里尝试。

编辑:谢谢,丹尼斯!


1
@Mauris您能添加一个说明吗?
Vasu Adari

@Vasu:此代码是一个匿名函数,实现与5 6 6 11其他答案中使用的相同的技巧,但是列表编码为“以12为基的9587的数字”
林恩

知道了谢谢。我希望您添加一个解释,以便检查您答案的人可以理解它在语言中的工作方式。
Vasu Adari 2015年


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)来表示“一年的开始日期”来工作。由于此挑战的日期范围在遵循简单leap年规则的年份范围内(不能跳过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,使用中的输入进行调用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


是的,我已将其添加到帖子中。
林恩(Lynn)2015年

在2097年和2098年看起来并不正确,这需要分别增加7和12。
Toby Speight 2015年

1
OP表示,输入年份保证在1970-2090之间。
林恩(Lynn)2015年

6
我真的不喜欢回答后变的问题!
Toby Speight 2015年

2
您是否可以指定输入在其中DE,因此可以使用LD A, 3; AND E; LD L, A; LD L, (HL);
尼尔

5

Python 3中,140 100 102 84.5 154 * 0.5 = 77个字节

我可能可以用Sakamoto的算法写一个更好的解决方案,但是现在就可以了

我是正确的。这是使用坂本算法的实现。

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

我已经更新了问题。您无需检查世纪。
Vasu Adari 2015年

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,143136 * 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全日名称,而不是'%一,取决于所需的状态。

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

@plannapus谢谢:)(我数了换行符,实际上是问文件系统的,因为我在Windows下是2字节,但是最后没有POSIX文件应该换行的地方,所以可以这样保存它是公平的实际上)
Tensibai 2015年

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

我不明白;
要走

您可以删除第一个字符y=scan;并使用x=y<-scan()+1我认为可以节省1个字符
Tensibai 2015年

而且您可以将其as.POSIXlt(paste(y,1),,"%Y %j")$wday用作功能主体来节省七个
Tensibai 2015年

@Tensibai如果您不将其放在一行上并将其直接粘贴到控制台,scan则会将第二行作为输入读取。x=y<-scan()+1将2014作为stdin会给您x = 2015和y = 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 2015年

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,120139字节-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

与往常一样,OOP方法似乎更长(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);}

想法借鉴了Toby Speight ; 添加了工作日的奖金显示。

通过将字符代码移至更舒适的范围来缩短字符串。必须选择正确的移动量(例如43)以使短的工作日计算代码x*5/4%7起作用。


我认为您的字符代码将其限制为ASCII兼容编码吗?
Toby Speight 2015年

是。密码应大于31,因此要添加到密码中的最小数字为27(给定字符串)" !!&"
anatolyg 2015年

2

Mathematica,145 * 50%= 74 73.5 72.5字节

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

使用标准日期功能。


2

Pyth,23个字节

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

没有资格获得任何奖金。

在这里尝试。

类似于纯python答案。

                        - 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-0.2)* 323(1-0.5)* 350 348 339 = 258.4 175 174 169.5字节

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

啊。

取消高尔夫:

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

在线尝试!

感谢@Kenney指出我可以用new Longand 来缩短printf!:D


long y=new Long(a[0])保存6(12)个字节,使用printf保存另外3(6)个字节。
肯尼2015年

2

GNU coreutils,52 51 49字节

(98字节程序-50%奖金)

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

输入来自命令行参数,输出至stdout。

说明

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

测试运行:

所有区域设置可以是CPOSIX

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

限制:这仅适用于2147485519年(尽管现在将问题更改为允许较低的限制)。


2

MATL,28字节

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

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

代码说明

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个字节

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

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

用法:

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个字节

U+"♣♠♠♂"cU%4

与Pyth答案一样,字符串中的四个字节应为05 06 06 0B在线尝试!

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
感谢您提供这笔赏金的圣诞节礼物!但是有人可以告诉我我如何赚钱吗?
ETHproductions 2015年

我翻阅了历史。显然,OP尝试奖励悬赏,但忘了授予悬赏,因此Community选择将一半声誉转移给该答案(我认为其选择基于最近的投票)。

2

果冻,14字节

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

在线尝试!

直到今天,Jelly还没有数组索引,因此上述操作必须要做。自从最近一次提交以来,数组索引已实现为,提供了以下解决方案(10个字节)。

ị6,6,11,5+

在线尝试!


1
我认为Jelly可以为10〜16个常数保留7个字符。
lirtosiast


1

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

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


1

Python,23个字节

lambda a:a+5+(a%4)**3%7

我的JavaScript答案的端口。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.