Advance Happy New Year, 2016!


40

Il tuo input sarà un numero intero tra il 1970 e il 2090 (incluso), che rappresenta un anno. Il programma dovrebbe produrre l'anno successivo in cui cade il giorno di Capodanno nello stesso giorno della settimana dell'anno di input.

Casi test:

Di seguito sono riportati gli input e gli output di esempio

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

Bonus del 20%: uscita il giorno della settimana del capodanno

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

Bonus del 30%: uscitaAdvance Happy New Year, <year>

2010 => Advance Happy New Year, 2016

Bonus del 50%: fai entrambi i bonus sopra indicati

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

Scrivi un programma che legge input da STDIN o accetta argomenti della riga di comando o una funzione che accetta un argomento.

Nota: aggiungere un collegamento per testare il codice, se possibile.

Classifica:


6
Sento che ogni singola sfida per le date richiede di fare il calcolo degli anni bisestili come sottoproblema e sta diventando obsoleta.
xnor


@xnor Se così non fosse, sarebbe stato solo un +7.
Vale a

@EriktheGolfer No. Quando ho scritto quel commento, la mia risposta è stata quella accettata.
Dennis,

Risposte:


1

Gelatina, 9 byte

%4*3%7+5+

Questa è una catena monadica che accetta come input un argomento della riga di comando intero. Usa il mio (x+5+(x%4)**3%7)algoritmo.

Provalo qui . Anche se questa è la versione corrente di Jelly, funziona anche in questa versione , che precede la sfida. (Grazie @Dennis!)


Questo è fantastico! Posso confermare che funziona con questa revisione dell'interprete Jelly, che precede la sfida.
Dennis,

31

Mathematica, 45 37 27 24 byte

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

Miglioramenti grazie a @ MartinBüttner (10 byte) e @ChipHurst (altri 3 byte).


7
Oh wow. Nessuno sembra aver notato questo schema, ma funziona.
Lynn,

4
Ecco una versione leggermente più corta:#+5[6,6,11][[#~Mod~4]]&
Chip Hurst il

@ChipHurst molto intelligente con 5[6, 6, 11][[0]]:)
martin

18

CJam, 21 12 11 byte

{_9587Cb=+}

@martin ha trovato un metodo molto semplice!

Provalo qui .

EDIT: Grazie, Dennis!


1
@Mauris Potresti aggiungere una spiegazione?
Vasu Adari,

@Vasu: questo codice è una funzione anonima che implementa lo stesso 5 6 6 11trucco utilizzato in altre risposte, ma l'elenco è codificato come "le cifre di 9587 nella base 12" .
Lynn,

Capito grazie. Volevo che aggiungessi una spiegazione in modo che le persone che controllano la tua risposta possano capire come funziona il linguaggio.
Vasu Adari,

10

gs2, 12 byte

V@¶4☻s%☺♀i50

Traduzione della mia risposta CJam. Codificato in CP437 come al solito. Provalo online !


Il link va al codice che produce 2spooky4me, e se taglio e incollo il codice sopra, ottengo l'anno sbagliato: imgur.com/VAkXT0k (per "anno sbagliato", voglio dire ottengo un anno prima dell'anno previsto)
question_asker

Avevo dimenticato un byte. Prova ora.
Lynn,

Ho anche modificato il link.
Lynn,

Bene, ora funziona
question_asker

8

JavaScript (ES6), 50 49 20 byte (nessun bonus)

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

L'algoritmo di @martin si rivela molto più piccolo, quindi ci sono andato.

Ho scelto un approccio matematico perché JavaScript tende ad essere dettagliato. Il codice è abbastanza breve che i bonus lo rendono solo più lungo.

Ecco la mia risposta precedente (49 byte) e la mia risposta originale (50 byte):

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

Funzionano prendendo l'anno e calcolando un numero (0-6) per rappresentare il "giorno di inizio dell'anno". Poiché l'intervallo di date per questa sfida è compreso nell'intervallo di anni che segue le semplici regole dell'anno bisestile (nessun salto nel 2000), è abbastanza semplice da calcolare. Quindi è solo una questione di confronto in avanti per trovare anni che iniziano con lo stesso valore. La ricorsione si è rivelata il modo più conciso per farlo.


7

Pyth, 14 12 11 byte

+QC@"♣♠♠♂"Q

I quattro byte nella stringa dovrebbero essere 05 06 06 0B.

EDIT: Grazie, FryAmTheEggman!

EDIT: Grazie, Dennis!


6

JavaScript (ES6), 104 byte - 50% di bonus = 52

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

Spiegazione

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+")"

Test


6

Codice macchina Z80, 12 byte

Una procedura Z80 in cui essere memorizzata 0000h, chiamata con l'ingresso in HL, e tutti gli altri registri cancellano:

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

Le prime tre istruzioni sono "NOP", ma vengono indicizzate come dati più avanti nel codice. Al ritorno, l'uscita è in HL.


Sì, l'ho aggiunto al post.
Lynn,

Non sembra giusto per gli anni 2097 e 2098, che necessitano di aggiunte rispettivamente di 7 e 12.
Toby Speight,

1
L'OP afferma che l'anno di ingresso è compreso nell'intervallo 1970-2090.
Lynn,

6
Non mi piacciono davvero le domande che vengono cambiate dopo aver risposto!
Toby Speight,

2
Hai il permesso di specificare che l'ingresso è in DEe quindi puoi usare LD A, 3; AND E; LD L, A; LD L, (HL);?
Neil,

5

Python 3, 140 100 102 84,5 154 * 0,5 = 77 byte

Probabilmente potrei scrivere una soluzione migliore con l'algoritmo di Sakamoto, ma per ora lo farà

Avevo ragione. Ecco un'implementazione usando l'algoritmo di 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])

Spiegazione:

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

Ho aggiornato la domanda. Non è necessario controllare per anni secolo.
Vasu Adari,

1
Che ne dici di w="SMTWTFSuouehranneduit"e poi di stampare w[d(i)::7]?
Lynn,

4

Scherzi a parte, 35 17 byte

[5,6,6,11] il trucco salva la giornata.

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

Provalo online

Spiegazione:

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

Vecchia versione:

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

Provalo online

Spiegazione:

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

L'algoritmo di Sakamoto:

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

4

C, 31 byte

In seguito alla modifica della domanda che limita l'intervallo di input a 1970-2090, questo diventa piuttosto banale:

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

Senza gli anni non bisestili, c'è una semplice sequenza di intervalli 5,6,6,11 per la prima ripetizione dello stesso giorno.

Soluzione completa al problema originale (non vincolata al 2090), 90 byte:

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

Programma di test:

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

Prova:

$ ./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 byte

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)

Utilizzare %Aper il nome del giorno intero invece di `% a, dipende dallo stato desiderato.

R, 120 * 0,7 = 84 byte

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 byte

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

Tutte le risposte sopra sono lavori derivati ​​basati sulla risposta @plannapus. Utilizzo del ;separatore per evitare la necessità sourcedel file o eseguirlo come script dalla riga di comando.


1
+1 Mi sono completamente dimenticato weekdays, bello.
plannapus,

@plannapus Grazie :) (ho contato le nuove righe, ho chiesto al file system in effetti, dato che sono sotto Windows sono 2 byte ma non ho una riga finale che dovrebbe avere un file POSIX, quindi è giusto tenerlo così in realtà)
Tensibai

3

R, 145 byte -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))

Esempi:

> 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 byte (senza bonus)

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

Rientrato, con nuove linee:

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

Casi test:

> 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

Non capisco questo desiderio di salire su una brutta linea, un ritorno in carrozza non è più costoso di un ;...
Tensibai,

puoi salvare 1 carattere rimuovendo il primo y=scan;e usando x=y<-scan()+1Penso
Tensibai il

e puoi salvarne altri sette usando as.POSIXlt(paste(y,1),,"%Y %j")$wdaycome corpo funzione
Tensibai il

@Tensibai se non lo metti su una sola riga e lo incolli direttamente sulla console, scanverrà letto nella seconda riga come input. x=y<-scan()+1con 2014 come stdin ti darà x = 2015 e y = 2015 (ovvero il compito èy <- scan()+1 ) e se si tenta di fare x=1+y<-scan()che vi darà un errore ( Error in 1 + y <- scan() : target of assignment expands to non-language object), perché sta cercando di assegnare scan()a 1+y.
plannapus,

@Tensibai Per quanto riguarda il tuo ultimo consiglio, il risultato ...$wdayè il numero del giorno della settimana: ma qui ho bisogno del nome del giorno della settimana per poter stampareAdvance Happy New Year, 2012 (Sun)
plannapus,

3

VBA, 130 * 0,50 = 65 byte

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 rende così facile la ricerca di giorni settimanali ... Se solo non fosse così dettagliato.


3

PHP, 120 139 byte - 50% = 60 byte

Un approccio funzionale:

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

Prende un input dalla riga di comando, come:

$ php ahny.php 2001

Il modo OOP sembra essere più lungo, come sempre (143 byte):

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

Le modifiche

  • 18 byte salvati . Invece di aggiungere un anno usando il modificatore PHP+1year , ora semplicemente incremento l'anno dato.
  • Salvato 1 byte memorizzando -1-1in una variabile.

3

C, punteggio 53 52 (104 byte)

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

Idea presa in prestito da Toby Speight ; aggiunto il display bonus del giorno della settimana.

Riduci la stringa spostando i codici dei caratteri su un intervallo più comodo. Ho dovuto scegliere il giusto importo di spostamento (ad es. 43) per far funzionare il codice di calcolo del giorno della settimana breve x*5/4%7.


Immagino che le tue cose in codice carattere limitino questo a codifiche compatibili ASCII?
Toby Speight,

Sì. I codici dovrebbero essere maggiori di 31, quindi il numero minimo da aggiungere ai codici sarebbe 27, dando la stringa " !!&".
Anatolyg

2

Mathematica, 145 * 50% = 74 73,5 72,5 byte

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

Utilizza le funzioni di data standard.


2

Pyth, 23 byte

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

Non si qualifica per nessuno dei bonus.

Provalo qui .

Simile alla risposta in puro pitone.

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

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

Provalo online!

Grazie a @Kenney per aver sottolineato che potrei accorciare con new Longe printf! : D


long y=new Long(a[0])salva 6 (12) byte e l'utilizzo ne printfsalva altri 3 (6).
Kenney,

2

Coreutils GNU, 52 51 49 byte

(Programma 98 byte - bonus del 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

L'input proviene dall'argomento della riga di comando e l'output è stdout.

Spiegazione

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

Prova:

Tutte le impostazioni locali possono essere Co 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)

Limitazione: funziona solo fino all'anno 2147485519 (anche se la domanda è ora cambiata per consentire un limite inferiore).


2

MATL , 28 byte

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

Esempio

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

Codice spiegato

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 byte

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

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

utilizzo:

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 byte

U+"♣♠♠♂"cU%4

Come per la risposta Pyth, dovrebbero essere i quattro byte nella stringa 05 06 06 0B. Provalo 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}");


1

Python, 23 bytes

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

A port of my JavaScript answer.


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.