Conte quantos meses estão tendo 31 dias completos contando juntas

11

Quantos de vocês ainda usam sua própria junta para determinar se um mês está tendo 31 dias ou menos?

Seu trabalho é escrever um programa para contar quantos meses, em um intervalo de meses, estão com 31 dias completos e quantos estão com menos de 31 dias "contando as juntas".

Contando os dias do mês por juntas

Cortesia: amsi.org.au


Entrada

Um par de meses, o primeiro dos quais não precisa ser cronologicamente anterior ao segundo, fornecido em qualquer formato adequado. Por exemplo: 201703 201902- março de 2017 a fevereiro de 2019. Descreva o formato de entrada que você escolher. Observe que a entrada deve poder incluir todos os anos de 1 a 9999. O intervalo de meses especificado inclui os meses inicial e final.

Resultado

Dois números inteiros: o número de meses no intervalo especificado com 31 dias e o número de meses no intervalo com menos de 31 dias.

Exemplo: 14 10- 14 articulações, 10 ranhuras (significa que nesse intervalo de meses temos 14 meses com 31 dias completos e 10 meses com menos de 31 dias).

Para uma entrada em que o segundo mês no intervalo vem cronologicamente antes do primeiro, por exemplo 201612 201611, você precisa emitir um par de zero.

Exemplos de entrada e saída

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

Regras

  • Você pode escolher qualquer idioma que desejar
  • Uma entrada por linha
  • Isso é , então o código mais curto em bytes vence!
  • O vencedor será escolhido em 9 de abril
  • Aplicam-se brechas padrão
  • PS: esta é minha primeira pergunta no PCG, pode ter algumas inconsistências. Sinta-se à vontade para editar e confirmar o que não está claro para você.
Rizki Pratama
fonte
5
Você diz que o primeiro é garantido que vem cronologicamente antes do segundo , mas isso é falso para o caso de teste 201612 201611.
Dennis
2
Existe uma sandbox no site onde você pode postar a pergunta apenas para esclarecer todas as dúvidas.
ghosts_in_the_code
1
Trinta dias têm setembro, abril, junho e novembro. Depois de fevereiro, todo o resto tem trinta e um. É assim que eu me lembro.
AdmBorkBork 30/03
@AdmBorkBork O único problema com isso é o loop infinito (referência obrigatória xkcd).
Wizzwizz4
Presumo que você pretenda usar o calendário gregoriano em todo o período?
Pausado até novo aviso.

Respostas:

7

Gelatina , 21 bytes

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

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

Experimente online!

Como 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
fonte
5

JavaScript (ES6), 70 68 67 64 bytes

Recebe a entrada como dois números inteiros no yyyymmformato, na sintaxe de curry (a)(b). Produz uma matriz de dois números inteiros [knuckles, grooves].

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

Formatado e 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 teste

Nota : o terceiro caso de teste não está incluído neste trecho, porque não funcionará a menos que o seu navegador tenha a Otimização de chamada de cauda ativada.

Arnauld
fonte
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']

Experimente online!

6 convertendo para um lambda, com agradecimentos a @math_junkie pela ideia. Agora gera uma lista contendo os dois números.

Versão não lambda anterior (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),

Experimente on-line antigo!

2 economizado com graças ao @ovs por me ajudar a me livrar do len(k). Eu não tinha pensado em usar None.

Entrada é uma lista de números inteiros no formato y1,m1,y2,m2

Algum crédito devido ao @KeerthanaPrabhakaran, que obteve bin(2741)[2:]antes de mim, o que economiza 1 byte em vez de codificar a string binária.

ElPedro
fonte
Impressionante ... k = bin (2741) [2:] * (c + 1-a) me deixou louco
officialaimm
1
Isso é 2 bytes mais curto
ovs 30/03
Brilhante! Eu estava tentando malhar para me livrar da len(k)última fatia. Obrigado.
ElPedro
1
Você pode salvar 6 bytes usando um lambda: TIO
viciado em matemática
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;

Experimente online!


versões mais antigas

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

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

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

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

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

Experimente online!

ʰᵈˑ
fonte
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%

Aceita dois parâmetros no formato ymm (por exemplo, 101 - 999912). Solução anterior de loop de 129 bytes:

@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
fonte
Resultado incorreto para 000101 999912, provavelmente por causa do limite de tamanho inteiro?
officialaimm
1
@officialaimm Formato de entrada incorreto, desculpe - o ano não deve ter zeros à esquerda.
Neil
3

Python 3.5 ( 164 162 154 152 150 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

recebe entrada na forma de aaaaaaaaaaaaaa

imprime a saída como number_of_knuckles number_of_grooves

  • economizou 2 bytes: Graças a Cole
  • salvou 8 bytes: removeu variáveis ​​indesejadas
  • salvou 2 bytes: t = 0 reduzido; k = 0 como t = k = 0
  • economizei 2 bytes: Graças a Cole (eu já tinha perdido isso antes)
  • economizou 2 bytes: Graças a Keerthana
  • salvou 8 bytes: removeu variáveis ​​indesejadas
  • salvou 3 bytes: Graças a math_junkie (split ('') to split ())
officialaimm
fonte
1
Eu acho que você pode reduzir alguns bytes fazendo n=inte talvez também algumas execbobagens.
cole
1
Eu acho que você pode fazer em 2773&1<<r%12-1>0vez deint('101010110101'[r%12-1])
Loovjo 30/03
@ Loovjo Estou recebendo erro ao fazê-lo!
officialaimm
1
usando print([k,t-k])como print(k,t-k)produziria o resultado desejado (k,g), reduzindo assim 2 bytes!
Keerthana Prabhakaran 30/03
1
Eu acredito que você pode substituir split(' ')porsplit()
matemática viciado em
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]

Experimente online!

  • 4 bytes salvos - Obrigado a @math_junkie por sugerir a cláusula if-else com pesquisa de matriz!

Quebrando o 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
fonte
1
Você pode salvar bytes substituindo as if-elsecláusulas por pesquisas de matriz. Veja esta publicação para obter detalhes
math junkie
Essa foi realmente uma maneira legal! Não sabia disso antes! Obrigado!
Keerthana Prabhakaran 30/03
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;

Execute assim:

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

Explicação

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.

Tweaks

  • Salva 17 bytes usando o estilo de carimbo de data e hora em vez do estilo de objeto DateTime
  • Economizou 6 bytes ao não atribuir o carimbo de data / hora da data final à variável $e , basta comparar diretamente
  • Economizou 1 byte, não mantendo a contagem de ranhuras, mas apenas computando após o loop
aross
fonte
$x++em vez de +$x++também funciona.
Titus
@Titus, eu tive que no início, mas percebeu que, com $xinicializado a corda seria 2017-12month, que é um formato e os resultados não reconhecida em 1970
aross
Malvado ... funcionou em algum lugar. Pior do que isso, porém, funciona sem um literal +na string.
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

Experimente online!

Toma entrada como forma 2017-03. Usa as bibliotecas de datas .NET integradas e percorre as entradas $apara $b, cada iteração $x++aumentando e adicionando $zse a corrente .Monthé -in 2,4,6,9,11(ou seja, um mês que não é de 31 dias). Em seguida, produzimos nosso total de meses menos os meses que não são de 31 dias $x-$ze os meses que não são de 31 dias $z.

Lança um erro no 0001-01para 9999-12caso de teste, porque .NET suporta apenas anos até 9999, então a final.AddMonths(1) causas um estouro. Ainda gera os valores corretos, no entanto, porque é um erro sem fim; apenas faz com que o loop saia.

Provavelmente seria mais curto fazer isso aritmeticamente, como as respostas em Python ou JavaScript, mas eu queria mostrar uma abordagem usando os built-ins do .NET.

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

Experimente online!

precisa de golfe ...

recebe entrada como 2016-03 2018-10

saídas:

  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
marcosm
fonte
1

Rápido, 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 é uma matriz de dois números inteiros no formato conforme o exemplo

John McDowall
fonte