2016年の明けましておめでとうございます!


40

入力は1970年から2090年までの整数で、1年を表します。プログラムは、入力された年と同じ曜日に新年が当たる翌年を出力する必要があります。

テストケース:

以下はサンプルの入力と出力です

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
すべての日付の課題では、うるう年の計算を副問題として行う必要があり、古くなってきていると感じています。
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 Adari

@Vasu:このコードは、5 6 6 11他の回答で使用されるのと同じトリックを実装する匿名関数ですが、リストは「ベース12の9587の数字」としてエンコードされます。
リン

了解、ありがとう。あなたの答えをチェックする人がそれが言語に対してどのように機能するかを理解できるように、私はあなたに説明を加えたかった。
ヴァスアダリ

10

gs2、12バイト

V@¶4☻s%☺♀i50

CJam回答の翻訳。通常どおりCP437でエンコードされます。オンラインでお試しください


リンクは2spooky4meを生成コードに移行し、Iカットとは、上記のコードを貼り付けた場合、私は間違っ年取得:imgur.com/VAkXT0kを(「間違った年」で、私は1年前に意図年より入手平均します)
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

文字列の4バイトはである必要があります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      ;

最初の3つの命令は「NOP」ですが、コードの後半でデータとしてインデックス付けされます。戻ると、出力はになりHLます。


うん、私はそれを投稿に追加しました。
リン

2097年と2098年は適切に見えません。それぞれ7と12の追加が必要です。
トビーSpeight

1
OPによれば、入力年は1970〜2090年の範囲内であることが保証されています。
リン

6
私は答えた後に変更される質問が本当に好きではありません!
トビーSpeight

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のバイト

おそらく、坂本のアルゴリズムでより良い解決策を書くことができますが、今のところはこれで十分です

私は正しかったです。坂本のアルゴリズムを使用した実装を次に示します。

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

century世紀以外の年がなければ、同じ日の最初の繰り返しには、単純な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希望する状態に応じて、 `%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ありがとう:)(私は改行を数えて、ファイルシステムに尋ねました、私は窓の下にいるので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

私は1つの醜いラインに乗るのこの願い、キャリッジリターンよりも最もコストのかかるではありません理解していない;...
Tensibai

あなたは最初に除去することによって、1つの文字を保存することができますy=scan;し、使用してx=y<-scan()+1私が考える
Tensibai

あなたが使用して、より7を保存することができas.POSIXlt(paste(y,1),,"%Y %j")$wday、あなたの関数本体として
Tensibai

@Tensibaiを1行に入れずに直接コンソールに貼り付けるとscan、2行目を入力として読み取ります。x=y<-scan()+12014年に標準入力として、あなたには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
プランナパス

あなたの最後のアドバイスに@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)";

次のように、コマンドラインから1つの入力を受け取ります。

$ 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修飾子を使用して1年を追加する代わりに+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からのアイデア; 平日のボーナス表示を追加しました。

文字コードをより快適な範囲にシフトすることにより、文字列を短くしました。短い平日の計算コードをx*5/4%7機能させるには、正しいシフト量(43など)を選択する必要がありました。


あなたの文字コードはこれをASCII互換エンコーディングに制限していると思いますか?
トビーSpeight

はい。コードは31より大きい必要があります。したがって、コードに追加する最小数は27で、文字列が与えられます" !!&"
アナトリグ

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-.2)* 323(1-.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"";
    }
}

オンラインでお試しください!

new Longとで短縮できることを指摘してくれた@Kenneyに感謝しprintfます!:D


long y=new Long(a[0])6(12)バイトprintf節約し、使用するとさらに3(6)バイト節約できます。
ケニー

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

入力はコマンドライン引数からであり、出力は標準出力です。

説明

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

試運転:

すべてのロケール設定はCまたは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)

制限:これは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の回答と同様に、文字列の4バイトはになります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

私は歴史に目を通しました。どうやらOPは答えを賞金しようとしたが、賞金を授与するのを忘れていたため、コミュニティはこの答えに評判の半分を渡すことを選択しました(最近の賛成票に基づいていると思います)。

2

ゼリー、14バイト

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

オンラインでお試しください!

今日まで、Jellyには配列のインデックス付けがなかったため、上記のことを行う必要があります。最新のコミット以降、配列のインデックス付けはとして実装されており、次のソリューション(10バイト)が提供されています

ị6,6,11,5+

オンラインでお試しください!


1
Jellyは10〜16個の定数で7文字を節約できると思います。
リトシアスト


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

Javascript ES7、17バイト

a=>a+5+(a%4)**3%7

JSを使用するのは初めてです。Pythonスクリプトを使用してこれを見つけましたが、最適であると信じています。ので、それは動作し0**30 MOD 7であり、1**3そして2**3両方とも1であり、及び3**36です。


1
指数演算子**ES7の機能ではありませんか?または、バベルを使用していますか?
insertusernamehere

@insertusernamehere修正されました。
リルトシアスト


1

Pyth、12バイト

++5%^%Q4 3 7

オンラインでお試しください!または、テストスイートをチェックアウトします。

パイス、18バイト

この2番目のアプローチは、主に@ wizzwizz4のPyth answerのゴルフです。

J%Q4+?q3J11?qJZ5 6

オンラインでお試しください!または、テストスイートをチェックアウトします。


説明

++ 5%^%Q4 3 7Q-Qは評価された入力を意味し、最後は暗黙的です。

     %Q4-入力mod 4。
    ^ 3-キューブ。
   %7-Mod 7。
 +5-プラス5
+ Q-プラス入力。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.