Comptez combien de mois ont 31 jours complets en comptant les jointures


12

Combien parmi vous qui utilisent encore votre propre phalange pour déterminer si un mois compte 31 jours ou moins?

Votre travail consiste à écrire un programme pour compter combien de mois, dans une fourchette de mois, ont 31 jours complets et combien ont moins de 31 jours en «comptant les jointures».

Compter les jours du mois par les phalanges

Courtoisie: amsi.org.au


Contribution

Une paire de mois, dont le premier n'a pas à venir chronologiquement avant le second, donné dans n'importe quel format approprié. Par exemple: 201703 201902- mars 2017 à février 2019. Veuillez décrire le format d'entrée que vous choisissez. Notez que l'entrée doit pouvoir inclure toutes les années de 1 à 9999. La plage de mois spécifiée comprend les mois de début et de fin.

Production

Deux nombres entiers: le nombre de mois dans la plage donnée avec 31 jours et le nombre de mois dans la plage avec moins de 31 jours.

Exemple: 14 10- 14 phalanges, 10 rainures (cela signifie que dans cette plage de mois, nous avons 14 mois qui ont 31 jours complets et 10 mois qui ont moins de 31 jours).

Pour une entrée où le deuxième mois de la plage vient chronologiquement avant le premier, par exemple 201612 201611, vous devez sortir une paire de zéro.

Exemples d'entrée et de sortie

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

Règles

  • Vous pouvez choisir n'importe quelle langue que vous aimez
  • Une entrée par ligne
  • C'est le , donc le code le plus court en octets gagne!
  • Le gagnant sera choisi le 9 avril
  • Des échappatoires standard s'appliquent
  • PS: c'est ma première question dans PCG, il pourrait y avoir quelques incohérences. N'hésitez pas à modifier et à confirmer ce qui n'est pas clair pour vous.

5
Vous dites que le premier est garanti chronologiquement avant le second , mais c'est faux pour le cas de test 201612 201611.
Dennis

2
Il existe un bac à sable sur le site où vous pouvez poster la question uniquement pour lever tous les doutes.
ghosts_in_the_code

1
Trente jours ont septembre, avril, juin et novembre. Après février, tous les autres ont trente et un ans. C'est comme ça que je m'en souviens.
AdmBorkBork

@AdmBorkBork Le seul problème avec cela est le bouclage infini (référence xkcd obligatoire).
wizzwizz4

Je suppose que vous avez l'intention d'utiliser le calendrier grégorien dans toute la plage de dates?
pause jusqu'à nouvel ordre.

Réponses:


7

Gelée , 21 octets

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

Prend l'entrée comme [[y, m], [y, m]].

Essayez-le en ligne!

Comment ça fonctionne

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

Prend l'entrée comme deux entiers au yyyymmformat, dans la syntaxe de curry (a)(b). Génère un tableau de deux entiers [knuckles, grooves].

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

Formaté et commenté

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)

Cas de test

NB : Le troisième cas de test n'est pas inclus dans cet extrait, car il ne fonctionnera que si votre navigateur a activé l'optimisation des appels de queue.


5

Python 2 , 92 90 86 80 octets

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

Essayez-le en ligne!

6 de plus en se convertissant en lambda, avec merci à @math_junkie pour l'idée. Génère maintenant une liste contenant les deux nombres.

Version précédente non lambda (86 octets)

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

Essayez-le en ligne ancien!

2 sauvé grâce à @ovs pour m'avoir aidé à me débarrasser de la len(k). Je n'avais pas pensé à utiliserNone .

L'entrée est une liste d'entiers au format y1,m1,y2,m2

Un crédit dû à @KeerthanaPrabhakaran qui a obtenu bin(2741)[2:]avant moi, ce qui économise 1 octet sur le codage en dur de la chaîne binaire.


Impressionnant ... k = bin (2741) [2:] * (c + 1-a) m'a époustouflé
officialaimm

1
C'est 2 octets plus court
ovs

Brillant! J'essayais de travailler la houe pour me débarrasser de len(k)la dernière tranche. Merci.
ElPedro

1
Vous pouvez économiser 6 octets en utilisant un lambda: TIO
math junkie

4

PHP , 259 256 249 248 237 221 octets

Dépassé par aross : /codegolf//a/114512/38505

Format d'entrée: 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;

Essayez-le en ligne!


Versions plus anciennes

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

Essayez-le en ligne!

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

Essayez-le en ligne!

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

Essayez-le en ligne!

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

Essayez-le en ligne!

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

Essayez-le en ligne!


3

Lot, 93 octets

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

Accepte deux paramètres au format ymm (c'est-à-dire 101 - 999912). Solution basée sur une boucle de 129 octets précédente:

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

Résultat incorrect pour 000101 999912, probablement à cause de la limite de taille entière?
officialaimm

1
@officialaimm Format d'entrée incorrect, désolé - l'année ne doit pas comporter de zéros en tête.
Neil

3

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

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

prend une entrée sous la forme de aaaamm

imprime la sortie en tant que number_of_knuckles number_of_grooves

  • sauvé 2 octets: Merci à Cole
  • 8 octets enregistrés: suppression des variables indésirables
  • enregistré 2 octets: réduit t = 0; k = 0 car t = k = 0
  • sauvé 2 octets: Merci à Cole (je l'avais manqué auparavant)
  • sauvé 2 octets: Merci à Keerthana
  • 8 octets enregistrés: suppression des variables indésirables
  • sauvé 3 octets: Merci à math_junkie (split ('') à split ())

1
Je pense que vous pouvez réduire certains octets en faisant n=intet peut-être aussi quelques exectromperies.
cole

1
Je pense que vous pouvez faire à la 2773&1<<r%12-1>0place deint('101010110101'[r%12-1])
Loovjo

@Loovjo Je reçois une erreur en le faisant!
officialaimm

1
l'utilisation de print([k,t-k])as print(k,t-k)produirait le résultat souhaité (k,g), réduisant ainsi de 2 octets!
Keerthana Prabhakaran

1
Je crois que vous pouvez remplacer split(' ')parsplit()
junkie de mathématiques

3

Python 2 , 147 146 142 octets

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]

Essayez-le en ligne!

  • 4 octets enregistrés - Merci à @math_junkie d'avoir suggéré la clause if-else avec recherche de tableau!

Décomposer le code,

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
Vous pouvez enregistrer des octets en remplaçant les if-elseclauses par des recherches de tableau. Voir cet article pour plus de détails
junkie de mathématiques

C'était en effet une façon cool! Je ne le savais pas avant! Merci!
Keerthana Prabhakaran

3

PHP, 120 103 97 96 octets

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

Courez comme ceci:

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

Explication

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

  • 17 octets enregistrés en utilisant le style d'horodatage au lieu du style d'objet DateTime
  • Enregistré 6 octets en n'attribuant pas d'horodatage de date de fin à la variable $e, il suffit de comparer directement
  • Sauvegardé 1 octet en ne comptant pas les grooves, mais en le calculant juste après la boucle

$x++au lieu de +$x++fonctionne également.
Titus

@Titus, je l'avais au début, mais je me suis rendu compte qu'avec une $xchaîne non initialisée 2017-12month, ce serait un format non reconnu et les résultats en 1970
autour du

Méchant ... ça a marché quelque part. Assez méchant cependant qu'il fonctionne sans littéral +dans la chaîne.
Titus

2

PowerShell , 96 octets

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

Essayez-le en ligne!

Prend la saisie sous forme 2017-03. Utilise les bibliothèques de dates .NET intégrées et passe en boucle des entrées $aà $b, chaque itération s'incrémentant $x++et s'ajoutant à $zsi le courant .Monthest -in 2,4,6,9,11(c'est-à-dire, un mois autre que 31 jours). Ensuite, nous affichons le total de nos mois moins les mois non 31 jours $x-$zet les mois non 31 jours $z.

Tosses une erreur sur le 0001-01au 9999-12cas test, parce que .NET ne supporte que des années jusqu'à 9999, de sorte que les finales .AddMonths(1)provoque un débordement. Restitue toujours les valeurs correctes, car c'est une erreur qui ne se termine pas; cela provoque simplement la sortie de la boucle.

Il serait probablement plus court de le faire de manière arithmétique, comme les réponses Python ou JavaScript, mais je voulais montrer une approche utilisant les intégrés .NET.


2

Bash , 113 octets

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

Essayez-le en ligne!

a besoin de jouer au golf ...

prend l'entrée comme 2016-03 2018-10

les sorties:

  1 28
  7 30
 12 31

non 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

1

Swift, 151 octets

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}

l'entrée est un tableau de deux entiers au format selon l'exemple

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.