Mercoledì Prime


22

Mercoledì Prime

Il tuo compito è contare il numero di mercoledì che cadono in un primo giorno del mese in un determinato anno. Ad esempio, 7-13-16è un mercoledì privilegiato. Per coerenza, utilizzare il calendario gregoriano per tutte le date.

Ingresso

L'input per il tuo programma / funzione sarà di un anno (ad es. 2016) Ed è flessibile. L'anno sarà un numero intero compreso tra il 1912 e il 2233 incluso.

Produzione

L'output è anche flessibile e dovrebbe essere il numero di mercoledì primi (ad es 18.).

punteggio

Questo è quindi vince il codice più breve in byte!

Casi test

input -> output
--------------------
1912 -> 19
1914 -> 16
1984 -> 17
1996 -> 19
2063 -> 19
2150 -> 16
2199 - > 18
2233 -> 18

Risposte:


7

MATL , 38 36 34 byte

FT+"@llI$YO]q&:t8XO!s9\~)9#1$ZOZps

Provalo online! Oppure verifica tutti i casi di test (richiede alcuni secondi).

Spiegazione

FT+     % Input year implicitly. Add [0 1] element-wise. Gives array with input year
        % and next year
"       % For each of those two years
  @     %   Push year
  ll    %   Push 1 twice. This indicates January 1.
  I$YO  %   Convert year, month, day to serial date number
]       % End for each. We now have the serial date number for January 1 of the input
        % year and that of the following year
q       % Subtract 1 to the latter, to yield December 31 of the input year
&:      % Inclusive range between those two numbers. This gives an array of serial date
        % numbers for the whole input year
t       % Push another copy of that array
8XO     % Convert to date string with format 8. This gives weekday as "Mon", "Tue" etc.
        % The result is a 3-column 2D char array, where each row is a day
!s      % Transpose, sum of each column. 'Wed' gives 288 (sum of ASCII codes)
9\~     % 288 gives 0 modulo 9, and is the only weekday to do so. So we compute modulo 9
        % and negate. This gives true for Wednesdays, false for the rest
)       % Apply as logical index into the array of serial date numbers
9#1$ZO  % Array of month numbers corresponding to those serial date numbers
Zp      % Array that contains true for prime numbers, false for the rest
s       % Sum of array. Display implicitly

Sono convinto che MATL non possa essere battuto su sfide basate sulla data. Dovremmo creare DATL che è ulteriormente ottimizzato per gestire le sfide basate sulla data.
Suever,

@Suever Haha, bel nome
Luis Mendo,

20

Python 2, 95 93 68 67 byte

lambda y:0x10ea2c8dbb06c5619/5**((y+((y-22)/99-y/2002)*16)%28)%5+16

Grazie a @Josay per giocare a golf a 1 byte!

Provalo su Ideone .


3
Puoi salvare 1 carattere con 0x10ea2c8dbb06c5619invece di 19501370182350951961.
SylvainD,

Capisco l'idea big_constant//5**long_expressionma come mai sei venuto con quella costante e quell'espressione? È pazzesco: D
Sherlock9,

2
La costante è semplice una tabella di ricerca che utilizza le cifre di base 5, ma viene convertita in base 10, in modo che le cifre vengano estratte numericamente anziché utilizzare un indice di stringa. L'espressione mi sembra un calendario perpetuo. (Il problema sarebbe troppo semplice se fosse limitato a anni dal 1901 al 2099, poiché le risposte si ripetono ogni 28 anni in quell'intervallo, quindi sarebbe solo un caso di prendere l'anno mod 28 e cercarlo nella tabella. )
Neil,

13

Brain-Flak , 6588 , 2310 , 2308 , 2290 byte

Per prima cosa, non ho scritto quasi il 100% di questo programma, il che è probabilmente dimostrato dall'enorme dimensione del programma. Gran parte di questo codice è stato scritto dal mio algoritmo di golf Brain-Flak . Insieme a un ulteriore script Python ho scritto per spingerlo nella giusta direzione.

Provalo online!

({}<(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()()())){}{}){})[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])()())[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])())()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())[()()()])())())[()])[()])()()())[()()])()())[()()()()])()())())[()()])())()())[()()()()])())()()())[()()()])()())[()()()])()())[()]))())()())[()()()()])())()()())>[(((((((((()()()()())){}{}){}){}){}){}[()]){}){}){}]){({}[()]<{}>)}{}({}<{{}}>)

Mentre questo programma è piuttosto lungo per il golf del codice, è davvero abbastanza breve per Brain-Flak. Attualmente il record mondiale per la divisione di interi è superiore a 1000 byte.

Spiegazione

L'algoritmo è abbastanza semplice. Poiché è disponibile un numero limitato di anni (321), inserisce semplicemente le risposte in ordine inverso sotto l'input e utilizza un algoritmo di ricerca per trovare la risposta corretta. Mentre codificare tutte le 321 possibilità può sembrare piuttosto inefficiente con un compito complesso come questo e un linguaggio tanto esoterico quanto quello del cervello, può benissimo essere la soluzione migliore. (Ho intenzione di scoprirlo nella prossima settimana).

Poiché la maggior parte dei 321 numeri sono in media circa 18 e differiscono di molto da un anno all'altro invece di spingere tutti i numeri singolarmente, io spingo normalmente il primo anno (2233) e poi doppio e cambio un po 'il valore per ogni anno dopo. In questo modo invece di pagare per spingere ~ 18 per tutti i 321 anni pago solo per spingere ~ 2 per ogni anno.

Una volta che tutte le risposte sono state spinte sottrae 1912 dall'input ({}[(((((((((()()()()())){}{}){}){}){}){}[()]){}){}){}])(potrebbe non essere ottimale, riscrivo l'ottimizzatore per saltare alcuni valori che credevo non fossero ottimali perché i numeri hardcoding sono un processo super-esponenziale e l'esecuzione fino al completamento potrebbe avere preso alcuni giorni).

Quindi sottrae dal primo elemento e si apre il secondo elemento fino al risultato raggiunge lo zero, {({}[()]<{}>)}.

Apre lo zero {}e tutti gli elementi sotto l'elemento superiore ({}<{{}}>).


Qual è l'approccio generale ai numeri del golf?
Neil,

L'idea semplice è che se hai un numero con i fattori n e m premi n m-1 volte e poi fai scoppiare m-1 volte. Il push iniziale viene valutato come n e ogni pop viene valutato come n aggiuntivo, creando (1 + m-1) (n) che è uguale a mn. Questo viene fatto in modo ricorsivo perché per spingere n dobbiamo giocare anche a n. Poiché questo metodo non funziona bene per alcuni numeri, in particolare per i numeri primi, ci guardiamo intorno per vedere se c'è un numero più efficiente nelle vicinanze e in tal caso lo esprimiamo come la somma di quel numero e la differenza.
Wheat Wizard

Vedo ... quindi dati due numeri ne mquali hanno lunghezze ke l, presumo, n+mavrebbero lunghezza k+l? Che dire n*m?
Neil,

n*msarebbe k+4m-4o l+4n-4. Questo perché la moltiplicazione è codificata. Innanzitutto spingiamo i n m-1tempi. Per fare ciò abbiamo bisogno di ksimboli per esprimere ne 2m-2simboli per esprimere le spinte (ogni spinta è di 2 simboli). Quindi pop m-1volte, costandoci un ulteriore 2m-2(pop costa anche 2 simboli). Questo è totale k+4m-4. possiamo anche moltiplicare m*n(proprietà commutativa) per ottenere l+4n-4. Il risultato sarà il più breve dei due.
Wheat Wizard

1
Bene, se è vero, allora +1costa 2, *2costa 4, *3costa 8, *4costa 12, che è più costoso di *2*2, quindi non ne vale la pena (su numeri inferiori a 1000 ho trovato solo 10 che non usavano *2: 1, 2, 3 , 4, 5, 9, 15, 27, 45, 135). Per il 1912 il meglio che potei fare fu ((((((1+1+1)*2+1)*2*2+1)*2+1)*2+1)*2+1)*2*2*2con una lunghezza di 52.
Neil,

7

Bash + utility comuni, 39

ncal $1|grep W|factor|egrep -c ': \S+$'

Prende l'anno di input come parametro della riga di comando. Tipicamente invia messaggi come questo a STDERR - Penso che questo sia legale secondo questa meta-risposta :

factor: We is not a valid positive integer

Se si desidera sopprimere esplicitamente l'output STDERR, è possibile farlo invece per un punteggio di 43 :

ncal $1|grep W|factor 2>-|egrep -c ': \S+$'

Si noti che ciò presuppone una lingua inglese o C / POSIX. Non funziona così bene gd_GB.utf8, in cui tutti i nomi dei giorni sono abbreviati Di.
Toby Speight,

6

Ottava, 86 byte

Questo non è veloce, in alcun modo. Ma questo non è davvero l'obiettivo di un codice golf, vero?

function r=p(y)r=0;for(i=698346:7:815953)d=datevec(i);r+=d(1)==y*isprime(d(3));end;end

Octave può tenere traccia delle date in base al "numero data" - numero di giorni trascorsi in cui il 1 gennaio 0 è il giorno 1. Con questa misura, il 3 gennaio 1912 (il primo mercoledì del nostro set) è il giorno 698.346. Inizia da lì e ripeti ogni 7 ° giorno (tutti i mercoledì) fino alla fine del 2233 e aggiungi 1 se l'anno è l'anno di destinazione E il giorno del mese è primo.


5

Python 2.7, 166 , 165 , 150 byte

from datetime import*
y=input()
d,c=date(y,1,1),0
while d.year==y:n=d.day;c+=n>1<2==d.weekday()>0<all(n%x for x in range(2,n));d+=timedelta(1)
print c

C'è sicuramente spazio per miglioramenti qui. Sono piuttosto nuovo al golf in Python. Questo utilizza il datetimemodulo. Passa in rassegna tutti i giorni dell'anno aggiungendone uno a un accumulatore se soddisfa il criterio. Quindi stampa il risultato. La maggior parte del sollevamento pesante è nel modulo, quindi il codice può essere piuttosto sottile.

Un byte salvato grazie a Morgan Thrapp e 15 byte salvati da Pietu1998 .


1
È possibile salvare un byte passando n%x==0a n%x<1.
Morgan Thrapp,

2
Non -1è necessario poiché rangel'indice finale è esclusivo. Inoltre, puoi convertirlo filterin un generatore. [0for x in range(2,n)if n%x<1]
PurkkaKoodari,

Puoi usare any(...)o all(...)invece di not filter(...).
kennytm,

1
Combinando confronti concatenati allè possibile salvare un intero gruppo. c+=n>1<2==d.weekday()>0<all(n%x for x in range(2,n))
PurkkaKoodari,

3

J, 44 byte

+/@(valdate*3=weekday)@,.&(,/(>:,"0/p:)i.12)

Ho appena scoperto che J ha incorporato per la manipolazione della data.

uso

I comandi extra vengono utilizzati per la formattazione di più input / output.

   f =: +/@(valdate*3=weekday)@,.&(,/(>:,"0/p:)i.12)
   (,.f"0) 1912 1914 1984 1996 2063 2150 2199 2233
1912 19
1914 16
1984 17
1996 19
2063 19
2150 16
2199 18
2233 18

Spiegazione

+/@(valdate*3=weekday)@,.&(,/(>:,"0/p:)i.12)  Input: year
                                       i.12   The range [0, ..., 11]
                              >:              Increment each to get the months [1, ..., 12]
                                    p:        Get the first 12 primes [2, ..., 37]
                                ,"0/          Make a table between each month and prime
                           ,/                 Join the rows
                       ,.&                    Prepend the year to each
                                              The date format is YYYY MM DD
            3=weekday                         Check if each date occurs on Wednesday
    valdate*                                  and is a valid date
+/@                                           Count the number of true values and return

1

PowerShell v3 +, 99 95 byte

Approccio a forza bruta -

param($y)(1..12|%{$m=$_;2,3,5,7,11,13,17,19,23,29,31|?{(date "$m-$_-$y").DayofWeek-eq3}}).Count

Riceve input $y, esegue il loop da 1a 12, archivia temporaneamente il mese in $m, quindi esegue il loop su ogni numero primo da 2a 31. Per ognuno di questi, costruiamo un Get-Datedi quel particolare giorno, quindi selezioniamo solo quelli con DayOfWeek -equal a 3(cioè, mercoledì). Incapsula il tutto in una parentesi per formulare una matrice e ne prende la .Countstessa.


In alternativa, approccio matematico -

PowerShell v3 +, 105 byte

param($y)(16,19,18,20,16,18,19)[($a=(date "1-1-$y").DayOfWeek)]+(1,-3,0,1,2)[$y%5]*($a-in0,2,3,4)*!($y%4)

Finisce per essere solo un pelo più lungo dell'approccio della forza bruta, ma lo includo qui poiché potrebbe essere utile per gli altri.

Anche in questo caso prende input $ycome l'anno. Questa volta eseguiamo operazioni matematiche rigorosamente basate sul primo giorno dell'anno. In primo luogo calcoliamo quale giorno della settimana è e lo memorizziamo $aper un uso successivo. Questo si indicizza nel primo array, che ci fornisce il numero che di solito è corretto. Dobbiamo aggiungere a questo un secondo indice basato sul fatto che si tratti di un potenziale anno bisestile, che si tratti di domenica, martedì, mercoledì o giovedì e in base a quale sia l'anno.

Questo si basa sulla seguente osservazione. La prima colonna è il giorno della settimana del 1 ° gennaio, la seconda è l'output normale. A meno che l'anno non sia uno dei numeri medi, è invece il numero tra parentesi. L'ultima colonna descrive come funziona l'indicizzazione% 5.

Jan-1 -> #  ... Except if $y=       (then it's this number) | $y % 5 =
Sun   -> 16 ... 1928 1956 1984 etc. (17)                    |    3
Mon   -> 19
Tue   -> 18 ... 1924 1952 1980 etc. (20)                    |    4
Wed   -> 20 ... 1936 1964 1992 etc. (17)                    |    1
Thur  -> 16 ... 1920 1948 1976 etc. (17)                    |    0
Fri   -> 18
Sat   -> 19

Nota: entrambi presuppongono che en-ussia l'impostazione PowerShell corrente per le informazioni su cultura / data. DayOfWeekPotrebbe essere necessario adattare la formattazione e il numero della data di conseguenza per altre varianti di cultura.


1

Rubino, 83 + 15 ( -rdate -rprimebandiere) = 98 byte

Provalo online! (I moduli importati sono inline perché idk se posso usare flag in repl.it)

->y{k=0;Prime.each(31){|d|k+=(1..12).count{|m|Date.new(y,m,d).wday==3 rescue p}};k}

1

JavaScript ES6, 187 182 181 179 byte

179 Scambiato in un ciclo for per il ciclo while

z=y=>{D=new Date("1/3/1912");N=0;a=()=>D.getFullYear();b=()=>D.getDate();c=()=>D.setDate(b()+7);for(;a()<=y;c())N+=y-a()?0:-1<[2,3,5,7,11,13,17,19,23,29,31].indexOf(b());return N}

181 Compattato il ternario

z=y=>{D=new Date("1/3/1912");N=0;a=()=>D.getFullYear();b=()=>D.getDate();c=()=>D.setDate(b()+7);while(a()<=y){N+=y-a()?0:-1<[2,3,5,7,11,13,17,19,23,29,31].indexOf(b());c()}return N}

182 Combinati i due anelli

z=y=>{D=new Date("1/3/1912");N=0;a=()=>D.getFullYear();b=()=>D.getDate();c=()=>D.setDate(b()+7);while(a()<=y){N+=a()==y?-1<[2,3,5,7,11,13,17,19,23,29,31].indexOf(b()):0;c()}return N}

187

z=y=>{D=new Date("1/3/1912");N=0;a=()=>D.getFullYear();b=()=>D.getDate();c=()=>D.setDate(b()+7);while(a()<y)c();for(;a()==y;c())N+=-1<[2,3,5,7,11,13,17,19,23,29,31].indexOf(b());return N}

Non credo che questo valga perché hai dato il primo mercoledì iniziale per l'anno specifico, in questo esempio. La sfida del PO afferma che ha bisogno dell'anno come unico parametro ... Grande sforzo finora ...
WallyWest

"L'input per il tuo programma / funzione sarà un anno" - ma quello che stai sottolineando non è quello. Uso il primo mercoledì del 1912 come seme perché è o è prima di ogni altro mercoledì nel periodo indicato dal PO, ma potrei usare altrettanto facilmente qualsiasi mercoledì arbitrario del 1911 o prima per seminarlo. L'input alla mia funzione è ancora di un anno e la funzione calcola ancora il numero di mercoledì primi in un dato anno nel periodo suggerito dal PO, quindi non sono sicuro di come questo non si adatti alla sfida.
Pandacoder,

Ah, mi
scuso

1
Grazie. Ho tratto ispirazione dall'implementazione di Eamon Olive Brain-Flak, che in realtà ha tutte le risposte pre-programmate, secondo la sua spiegazione.
Pandacoder,

1

Lotto, 248 byte

@set/ad=0,l=1,n=20
@for /l %%i in (1913,1,%1)do @set/ad=(d+l+1)%%7,l=!(%%i%%4)-!(%%i%%100)+!(%%i%%400)
@goto %l%%d%
:03
:06
@set/an-=1
:12
:13
:16
@set/an-=1
:01
:04
:14
@set/an-=1
:00
:05
:10
:15
@set/an-=1
:02
:11
@echo %n%

Spiegazione: dè il giorno della settimana, con 0per lunedì, che è convenientemente il 1 ° gennaio 1912. lè una bandiera per indicare se l'anno è un anno bisestile, 1per il 1912. Passiamo quindi dal 1913 all'anno di immissione, aggiornando il giorno di settimana e ricalcolando la bandiera dell'anno bisestile mentre procediamo. Infine, utilizziamo la bandiera dell'anno bisestile e il giorno della settimana per indicizzare in quello che è effettivamente una grande dichiarazione switch per determinare n, il numero di mercoledì primi. L'impostazione nsu 20 e il suo decremento con caduta è tuttavia più economico rispetto all'utilizzo della logica di controllo del flusso, ma il risultato è che se il 1 ° gennaio di un anno non bisestile è giovedì o domenica, allora ci sono 16 mercoledì primi e così via per gli altri casi .


1

JavaScript ES6 206 203 199 197 195 183 182 179

Non il più breve, ma il meglio che posso fare per ora ... Suggerimenti di golf benvenuti ...

p=n=>--d-1?n%d&&p(n):1;v=Date;D=(x,y)=>new v(x.setDate(x.getDate()-y));W=a=>eval('for(Z=0,z=D(w=new v(a,11,31),(w.getDay()+4)%7);z>new v(a,0,1);)Z+=~~p(d=z.getDate()),z=D(z,7);Z')

I cambiamenti:

  1. alterazione della componente ternaria da: 3>=x?3-x:10-xa 6-(x+10)%7, salvataggio: 3 Modifiche alle posizioni della dichiarazione;
  2. unito x=w.getDay();z=D(w,6-(x+10)%7)a z=D(w,6-(w.getDay()+10)%7), risparmiando: 4
  3. spostato Z=0dalla forsequenza alla dichiarazione della data e inserito z=D(w,6-(x+10)%7)nella forsequenza per riordinare, salvando: 2
  4. w=new Date(a,Z=0,1)dichiarazione spostata in forloop, fusione con la wdichiarazione esistente , salvataggio: 2
  5. riscrivendo la funzione di ricerca primaria in una funzione di prova primaria, salvando: 12
  6. passare +!!a ~~ridurre e convertire ancora p(d=1)da NaNa 0, consentendo alla funzione Prime Test di funzionare ancora, salvando: 1
  7. Spostato tutte le funzioni extra dalla funzione di chiamata principale W, forciclo ridefinito - andando al contrario dal 31 dicembre, scrivendo l' Dateoggetto come una variabile separata, quindi riscrivendo il forciclo in evalchiamata; risparmio 3.

@PandaCoder, ti raggiungo, amico!


1

R, 149 147 byte

y=function(x){s=strftime;b=ISOdate
a=seq(b(x,1,1),t=b(x,12,31),b='d')
length(a[s(a,'%u')==3&trimws(s(a,'%e'))%in%c(2,3,5,7,11,13,17,19,23,29,31)])}

Provalo su Ideone .


0

Groovy, 126

Groovy non ha la validazione del numero primo, ha dovuto costruire anche quello.

{n->p={x->x<3||(2..Math.sqrt(x)).every{x%it}};(new Date("1/1/$n")..new Date("12/31/$n")).collect{it[7]==4&&p(it[5])?it:0}-[0]}
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.