Conta il numero di mesi che trascorrono 31 giorni contando le nocche


12

Quanti di voi usano ancora la propria nocca per determinare se un mese dura 31 giorni o meno?

Il tuo compito è quello di scrivere un programma per contare quanti mesi, in un intervallo di mesi, stanno avendo 31 giorni completi e quanti hanno meno di 31 giorni "contando le nocche".

Contando i giorni del mese dalle nocche

Per gentile concessione: amsi.org.au


Ingresso

Un paio di mesi, il primo dei quali non deve venire cronologicamente prima del secondo, dato in un formato adatto. Ad esempio: 201703 201902- da marzo 2017 a febbraio 2019. Descrivi il formato di input che scegli. Si noti che l'input deve essere in grado di includere tutti gli anni da 1 a 9999. L'intervallo di mesi specificato include sia i mesi di inizio che di fine.

Produzione

Due numeri interi: il numero di mesi nell'intervallo specificato con 31 giorni e il numero di mesi nell'intervallo con meno di 31 giorni.

Esempio: 14 10- 14 nocche, 10 scanalature (significa che in quell'intervallo di mesi abbiamo 14 mesi che hanno 31 giorni interi e 10 mesi che hanno meno di 31 giorni).

Per un input in cui il secondo mese dell'intervallo arriva cronologicamente prima del primo, ad esempio 201612 201611, è necessario generare una coppia di zero.

Esempi di input e output

| Input         | Output      |
|---------------|-------------|
| 201703 201902 | 14 10       |
| 201701 202008 | 26 18       |
| 000101 999912 | 69993 49995 |
| 201802 201803 | 1 1         |
| 201601 201601 | 1 0         |
| 201612 201611 | 0 0         |

Regole

  • Puoi scegliere la lingua che preferisci
  • Un input per riga
  • Questo è , quindi vince il codice più breve in byte!
  • Il vincitore sarà scelto il 9 aprile
  • Si applicano scappatoie standard
  • PS: questa è la mia prima domanda in PCG, potrebbe avere alcune incongruenze. Sentiti libero di modificare e confermare ciò che non è chiaro per te.

5
Dici che il primo dei quali è garantito per venire cronologicamente prima del secondo , ma questo è falso per il caso di test 201612 201611.
Dennis,

2
Esiste una sandbox sul sito in cui è possibile pubblicare la domanda esclusivamente per chiarire tutti i dubbi.
ghosts_in_the_code

1
Trenta giorni ha settembre, aprile, giugno e novembre. Dopo che febbraio è finito, tutto il resto ne ha trentuno. È così che me lo ricordo.
AdmBorkBork

@AdmBorkBork L'unico problema è il loop infinito (riferimento xkcd obbligatorio).
wizzwizz4,

Presumo che intendi utilizzare il calendario gregoriano nell'intervallo di date?
In pausa fino a ulteriore avviso.

Risposte:


7

Gelatina , 21 byte

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$

Accetta input come [[y, m], [y, m]].

Provalo online!

Come funziona

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$  Main link. Argument: [[a, b], [c, d]]

ḅ12                    Unbase 12; yield [x, y] := [ 12a + b, 12c + d].
   r/                  Reduce by range; yield [x, ..., y].
           ¤           Combine the five links to the left into a niladic chain.
      7                  Set the return value to 7.
       R                 Range; yield [1, 2, 3, 4, 5, 6, 7].
        Ḃ                Bit; yield [1, 0, 1, 0, 1, 0, 1].
         ṁ12             Mold 12; repeat the Booleans to create an array of length
                         12. Yields [1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1].
     ị                 At-index; yield the elements of the array to the right at 
                       the indices (1-based and modular) of the array to the left.
               $       Combine the two links to the left into a monadic chain.
              C          Complement; map t -> 1-t over the array.
             ż           Zip the original array with the complements.
                S      Take the sum of each column.
                    $  Combine the two links to the left into a monadic chain.
                  Ṣ      Sort [[a, b], [c, d]].
                   ⁼     Compare the result with [[a, b], [c, d]], yielding 1 if
                         the input is sorted, 0 if not.
                 ×     Multiply the results to both sides.

5

JavaScript (ES6), 70 68 67 64 byte

Accetta input come due numeri interi nel yyyymmformato, nella sintassi del curry (a)(b). Emette un array di due numeri interi [knuckles, grooves].

a=>g=(b,c=d=0)=>a>b?[c,d-c]:g(--b,c+!((b%=100)>11||b/.87&!!++d))

Formattato e commentato

a =>                        // main function: takes start date (a) as input / returns g
  g = (                     // recursive function g, which takes:
        b,                  //   - b = end date
        c = d = 0           //   - c = number of knuckles
      ) =>                  // and also keeps track of: d = total number of months
    a > b ?                 // if a is greater than b:
      [ c, d - c ]          //   stop recursion and return the final result
    :                       // else:
      g(                    //   do a recursive call to g():
        --b,                //   - decrement the end date
        c +                 //   - increment the # of knuckles if
        !(                  //     both of these conditions are false:
          (b %= 100)        //     - the end month (now stored in b in 0-based indexing)
          > 11 ||           //       is greater than 11
          b / 0.87 & !!++d  //     - the number of days in this month is not 31
        )                   //       (at the same time, d is incremented if the first
      )                     //       condition is false)

Casi test

NB : il terzo caso di test non è incluso in questo frammento, perché non funzionerà a meno che nel tuo browser non sia abilitata l'ottimizzazione della chiamata di coda.


5

Python 2 , 92 90 86 80 byte

lambda a,b,c,d:[(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x)for x in'10']

Provalo online!

6 in più convertendosi in lambda, grazie a @math_junkie per l'idea. Ora genera un elenco contenente i due numeri.

Versione precedente non lambda (86 byte)

a,b,c,d=input()
for x in'10':print(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x),

Provalo online vecchio!

2 salvato con grazie a @ovs per avermi aiutato a sbarazzarmi di len(k) . Non avevo pensato di usare None.

L'input è un elenco di numeri interi nel formato y1,m1,y2,m2

Un po 'di credito dovuto a @KeerthanaPrabhakaran che è arrivato bin(2741)[2:]prima di me, il che consente di risparmiare 1 byte sulla codifica hard della stringa binaria.


Impressionante ... k = bin (2741) [2:] * (c + 1-a) mi ha lasciato senza fiato
officialaimm

1
Questo è più corto di 2 byte
ovs

Brillante! Stavo cercando di allenare la zappa per sbarazzarmi len(k)dell'ultima fetta. Grazie.
ElPedro,

1
Puoi salvare 6 byte usando un lambda: TIO
drogato di matematica il

4

PHP , 259 256 249 248 237 221 byte

Superato da aross : /codegolf//a/114512/38505

Formato di input: yyyymm,yyyymm

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_(Ym,$i[0]),new DateInterval(P1M),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.++$y;

Provalo online!


Versioni precedenti

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),new DateInterval('P1M'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

Provalo online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.$y;

Provalo online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))==31?++$x:++$y;
echo $x.' '.$y;

Provalo online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.++$y;

Provalo online!

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

Provalo online!


3

Lotto, 93 byte

@set/ag=(y=%2/100-%1/100)*5+(x=%2%%100+6)*5/12-(w=%1%%100+5)*5/12,k=y*12+x-w-g
@echo %k% %g%

Accetta due parametri nel formato ymm (ovvero 101 - 999912). Precedente soluzione basata su loop a 129 byte:

@set/al=%1-%1/100*88,u=%2-%2/100*88,k=g=0
@for /l %%i in (%l%,1,%u%)do @set/a"m=%%i%%12,k+=1451>>m&1,g+=2644>>m&1
@echo %k% %g%

Risultato errato per 000101 999912, probabilmente a causa del limite di dimensioni intere?
officialaimm,

1
@officialaimm Formato di input errato, scusa, l'anno non dovrebbe avere zeri iniziali.
Neil

3

Python 3.5 ( 164 162 154 152 150 148 140 137 byte)

n=int;a,b=input().split();t=k=0
for r in range(n(a[4:]),(n(b[:4])-n(a[:4]))*12+n(b[4:])+1):t+=1;k+=n('101010110101'[r%12-1])
print(k,t-k)

repl.it

prende input sotto forma di yyyymm yyyymm

stampa l'output come number_of_knuckles number_of_grooves

  • salvato 2 byte: grazie a Cole
  • salvato 8 byte: rimosse variabili indesiderate
  • salvato 2 byte: ridotto t = 0; k = 0 come t = k = 0
  • salvato 2 byte: grazie a Cole (questo l'avevo perso prima)
  • salvato 2 byte: grazie a Keerthana
  • salvato 8 byte: rimosse variabili indesiderate
  • salvato 3 byte: grazie a math_junkie (split ('') a split ())

1
Penso che puoi ridurre alcuni byte facendo n=inte forse anche qualche execstupidaggine.
Cole

1
Penso che tu possa fare 2773&1<<r%12-1>0invece diint('101010110101'[r%12-1])
Loovjo

@Loovjo Sto riscontrando errori nel farlo!
officialaimm,

1
l'utilizzo di print([k,t-k])as print(k,t-k)produrrebbe il risultato desiderato (k,g)riducendo in tal modo 2 byte!
Keerthana Prabhakaran,

1
Credo che tu possa sostituire split(' ')consplit()
drogato di matematica il

3

Python 2 , 147 146 142 byte

def s(a,b):y=100;r=bin(2741)[2:];x=b/y-a/y;i=r*(x-1);return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]

Provalo online!

  • Salvato 4 byte - Grazie a @math_junkie per aver suggerito la clausola if-else con la ricerca di array!

Abbattere il codice,

def s(a,b):
 y=100
 r=bin(2741)[2:] #'101010110101'
 x=b/y-a/y #to get the difference between the two years
 i=r*(x-1)
 return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]

1
È possibile salvare byte sostituendo le if-elseclausole con ricerche di array. Vedi questo post per i dettagli
drogato di matematica

Era davvero un bel modo! Non lo sapevo prima! Grazie!
Keerthana Prabhakaran,

3

PHP, 120 103 97 96 byte

for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;

Esegui in questo modo:

php -nr 'for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;' 0001-01 9999-12;echo
> 69993_49995

Spiegazione

for(
  $f=strtotime;          # Alias strtotime function which is called twice.
  $f($argv[2]) >=        # Create end date timestamp. Iterate until the end
                         # date is reached.
  $n=$f(
    $argv[1].+$x++.month # Create timestamp from start date + X months.
  );
)
  $k+=date(t,$n) > 30;   # If "t" of current date (days in month) is 31
                         # increment $k (knuckles).

echo+$k,_,$x-1-$k;       # Compute grooves (iterations - $k) and output,
                         # implicit cast to int to account for 0 count.

Ritocchi

  • Salvato 17 byte utilizzando lo stile data / ora anziché lo stile oggetto DateTime
  • 6 byte salvati non assegnando il timestamp della data di fine alla variabile $e , basta confrontare direttamente
  • Salvato 1 byte non mantenendo il conteggio dei groove, ma semplicemente calcolandolo dopo il loop

$x++invece di +$x++funzionare anche.
Tito

@Titus, all'inizio l'ho avuto, ma mi sono reso conto che con $xla stringa non inizializzata sarebbe stata 2017-12month, che è un formato non riconosciuto e risulta nel 1970
circa il

Malvagio ... ha funzionato da qualche parte. Abbastanza malvagio, però, che funziona senza un valore letterale +nella stringa.
Tito

2

PowerShell , 96 byte

for($a,$b=[datetime[]]$args;$a-le$b;$a=$a.AddMonths(1)){$x++;$z+=$a.Month-in2,4,6,9,11};$x-$z;$z

Provalo online!

Accetta input come modulo 2017-03. Utilizza le librerie di date .NET integrate e passa da input $aa $b, ogni iterazione incrementa $x++e si aggiunge a $zse la corrente .Monthè -in 2,4,6,9,11(cioè un mese non di 31 giorni). Quindi produciamo i nostri mesi totali meno i mesi non di 31 giorni $x-$ze i mesi non di 31 giorni$z .

Lancia un errore 0001-01al 9999-12banco di prova, perché .NET supporta solo anni fino a 9999, in modo che il finale.AddMonths(1) causa un overflow. Restituisce comunque i valori corretti, perché è un errore non terminante; causa solo l'uscita dal loop.

Probabilmente sarebbe più breve farlo aritmeticamente, come le risposte Python o JavaScript, ma volevo mostrare un approccio usando i built-in .NET.


2

bash , 113 byte

s="$1-1";e="$2-1";sort <(while [ "$s" \< "$e" ];do s=$(date +%F -d"$s+1month");date +%d -d"$s-1day";done)|uniq -c

Provalo online!

ha bisogno di golf ...

accetta input come 2016-03 2018-10

uscite:

  1 28
  7 30
 12 31

ungolfed:

s="$1-1"
e="$2-1"                     # adds first day of month to the dates
sort <(                    
while [ "$s" \< "$e" ]; do   #iterates over dates
s=$(date +%F -d"$s+1month")  #adds one month to start date
date +%d -d"$s-1day"         #outputs last day of previous month
done) | uniq -c              #counts ocurrences of day number prevously sorted

1

Rapido, 151 byte

let f={(m:[Int])->[Int] in var k=[0,0]
(m.min()!...m.max()!).map{$0%100}.filter{$0>0&&$0<13}.forEach{m in let n = m>7 ?m-7:m
k[(n%2+1)%2]+=1}
return k}

input è un array di due numeri interi nel formato come nell'esempio

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.