Cuente cuántos meses tiene 31 días completos contando nudillos

11

¿Cuántos de ustedes todavía usan su propio nudillo para determinar si un mes tiene 31 días completos o menos?

Su trabajo es escribir un programa para contar cuántos meses, en un rango de meses, tienen 31 días completos y cuántos tienen menos de 31 días "contando los nudillos".

Contando días del mes por nudillos

Cortesía: amsi.org.au


Entrada

Un par de meses, el primero de los cuales no tiene que venir cronológicamente antes del segundo, dado en cualquier formato adecuado. Por ejemplo: 201703 201902- marzo de 2017 a febrero de 2019. Describa el formato de entrada que elija. Tenga en cuenta que la entrada debe poder incluir todos los años del 1 al 9999. El rango de meses especificado incluye tanto los meses iniciales como los finales.

Salida

Dos enteros: el número de meses en el rango dado con 31 días y el número de meses en el rango con menos de 31 días.

Ejemplo: 14 1014 nudillos, 10 surcos (significa que en ese rango de meses tenemos 14 meses que tienen 31 días completos y 10 meses que tienen menos de 31 días).

Para una entrada donde el segundo mes en el rango viene cronológicamente antes que el primero, por ejemplo 201612 201611, debe generar un par de cero.

Ejemplos de entrada y salida.

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

Reglas

  • Puedes elegir el idioma que quieras
  • Una entrada por línea
  • Este es el , por lo que gana el código más corto en bytes.
  • El ganador será elegido el 9 de abril.
  • Se aplican lagunas estándar
  • PD: esta es mi primera pregunta en PCG, podría tener algunas inconsistencias. Siéntase libre de editar y confirmar lo que no está claro para usted.
Rizki Pratama
fuente
55
Usted dice que el primero de los cuales está garantizado que vendrá cronológicamente antes del segundo , pero esto es falso para el caso de prueba 201612 201611.
Dennis
2
Existe un sandbox en el sitio donde puede publicar la pregunta únicamente para aclarar todas las dudas.
ghosts_in_the_code
1
Treinta días tiene septiembre, abril, junio y noviembre. Después de febrero, todos los demás tienen treinta y uno. Así es como lo recuerdo.
AdmBorkBork
@AdmBorkBork El único problema con eso es el bucle infinito (referencia obligatoria de xkcd).
wizzwizz4
¿Supongo que tiene la intención de utilizar el calendario gregoriano en todo el rango de fechas?
Pausado hasta nuevo aviso.

Respuestas:

7

Jalea , 21 bytes

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

Toma entrada como [[y, m], [y, m]].

Pruébalo en línea!

Cómo funciona

ḅ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.
Dennis
fuente
5

JavaScript (ES6), 70 68 67 64 bytes

Toma la entrada como dos enteros en yyyymmformato, en sintaxis curry (a)(b). Emite una matriz de dos enteros [knuckles, grooves].

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

Formateado y comentado

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)

Casos de prueba

Nota : El tercer caso de prueba no está incluido en este fragmento, porque no funcionará a menos que su navegador tenga habilitada la Optimización de llamadas de cola.

Arnauld
fuente
5

Python 2 , 92 90 86 80 bytes

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

Pruébalo en línea!

6 más al convertir a una lambda, gracias a @math_junkie por la idea. Ahora genera una lista que contiene los dos números.

Versión anterior que no es lambda (86 bytes)

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

Pruébelo en línea de edad!

2 guardado gracias a @ovs por ayudarme a deshacerme del len(k). No había pensado en usar None.

La entrada es una lista de enteros en el formato y1,m1,y2,m2

Algún crédito debido a @KeerthanaPrabhakaran que obtuve bin(2741)[2:]antes que yo, lo que ahorra 1 byte sobre la codificación dura de la cadena binaria.

ElPedro
fuente
Impresionante ... k = bin (2741) [2:] * (c + 1-a) me dejó boquiabierto
officialaimm
1
Esto es 2 bytes más corto
ovs
¡Brillante! Estaba tratando de resolver la azada para deshacerme de len(k)la última rebanada. Gracias.
ElPedro
1
Puede guardar 6 bytes usando una lambda: TIO
math junkie
4

PHP , 259 256 249 248 237 221 bytes

Superado por aross : /codegolf//a/114512/38505

Formato de entrada 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;

Pruébalo en línea!


versiones anteriores

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

Pruébalo en línea!

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

Pruébalo en línea!

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

Pruébalo en línea!

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

Pruébalo en línea!

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

Pruébalo en línea!

ʰᵈˑ
fuente
3

Lote, 93 bytes

@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%

Acepta dos parámetros en formato ymm (es decir, 101 - 999912). Solución basada en bucle de 129 bytes anterior:

@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%
Neil
fuente
¿Resultado incorrecto para 000101 999912, probablemente debido al límite de tamaño entero?
officialaimm
1
@officialaimm Formato de entrada incorrecto, lo siento, el año no debería tener ceros a la izquierda.
Neil
3

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

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

toma entrada en forma de aaaamm aaaamm

imprime la salida como number_of_knuckles number_of_grooves

  • guardado 2 bytes: Gracias a Cole
  • 8 bytes guardados: variables no deseadas eliminadas
  • 2 bytes guardados: reducido t = 0; k = 0 como t = k = 0
  • guardado 2 bytes: Gracias a Cole (me había perdido esto antes)
  • guardado 2 bytes: Gracias a Keerthana
  • 8 bytes guardados: variables no deseadas eliminadas
  • guardado 3 bytes: Gracias a math_junkie (split ('') a split ())
officialaimm
fuente
1
Creo que puede reducir algunos bytes haciendo n=inty quizás también algunas exectonterías.
cole
1
Creo que puedes hacer en 2773&1<<r%12-1>0lugar deint('101010110101'[r%12-1])
Loovjo
@Loovjo ¡Recibo un error al hacerlo!
officialaimm
1
¡usar print([k,t-k])as print(k,t-k)produciría el resultado deseado (k,g), reduciendo así 2 bytes!
Keerthana Prabhakaran
1
Creo que puede reemplazar split(' ')consplit()
drogadicto de matemáticas
3

Python 2 , 147 146 142 bytes

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]

Pruébalo en línea!

  • Guardado 4 bytes: ¡Gracias a @math_junkie por sugerir la cláusula if-else con búsqueda de matriz!

Rompiendo el código,

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]
Keerthana Prabhakaran
fuente
1
Puede guardar bytes reemplazando las if-elsecláusulas con búsquedas de matriz. Ver esta publicación para más detalles
adicto a las matemáticas
¡Esa fue una manera genial! ¡No lo sabía antes! ¡Gracias!
Keerthana Prabhakaran
3

PHP, 120 103 97 96 bytes

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

Corre así:

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

Explicación

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.

Ajustes

  • Se guardaron 17 bytes utilizando el estilo de marca de tiempo en lugar del estilo de objeto DateTime
  • Se guardaron 6 bytes al no asignar la fecha y hora de finalización a la variable $e, solo compare directamente
  • Se guardó 1 byte al no contar el número de ranuras, sino simplemente calcularlo después del ciclo
aross
fuente
$x++en lugar de +$x++también funciona.
Titus
@Titus, tuve que al principio, pero se dio cuenta de que con $xsin inicializar la cadena sería 2017-12month, que es un formato y los resultados no reconocida en 1970
aross
Malvado ... funcionó en alguna parte. Sin embargo, es lo suficientemente malvado como para que funcione sin un literal +en la cadena.
Titus
2

PowerShell , 96 bytes

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

Pruébalo en línea!

Toma entrada como forma 2017-03. Utiliza las bibliotecas de fechas .NET integradas y recorre desde las entradas $ahasta $b, cada iteración se incrementa $x++y agrega $zsi la actual .Monthes -in 2,4,6,9,11( es decir, un mes que no es de 31 días). Luego sacamos nuestros meses totales menos los meses que no son de 31 días $x-$zy los que no son de 31 días $z.

Arroja un error en el 0001-01que 9999-12caso de prueba, ya que sólo es compatible con .NET años hasta 9999, por lo que las últimas .AddMonths(1)causas de un rebosadero. Sin embargo, aún genera los valores correctos porque es un error que no termina; solo hace que salga el bucle.

Probablemente sería más corto hacer esto aritméticamente, como las respuestas de Python o JavaScript, pero quería mostrar un enfoque utilizando los .NET incorporados.

AdmBorkBork
fuente
2

Bash , 113 bytes

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

Pruébalo en línea!

necesita jugar al golf ...

toma entrada como 2016-03 2018-10

salidas:

  1 28
  7 30
 12 31

sin golf:

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
marcom
fuente
1

Swift, 151 bytes

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 es una matriz de dos enteros en el formato según el ejemplo

John McDowall
fuente