Zählen Sie, wie viele Monate volle 31 Tage haben, indem Sie die Knöchel zählen


11

Wie viele von Ihnen verwenden immer noch Ihren eigenen Knöchel, um festzustellen, ob ein Monat volle 31 Tage oder weniger hat?

Ihre Aufgabe ist es, ein Programm zu schreiben, um zu zählen, wie viele Monate in einem Monatsbereich volle 31 Tage und wie viele weniger als 31 Tage haben, indem Sie "die Knöchel zählen".

Zähltage des Monats mit den Fingerknöcheln

Mit freundlicher Genehmigung von amsi.org.au.


Eingang

Ein paar Monate, von denen der erste nicht chronologisch vor dem zweiten stehen muss, in einem geeigneten Format. Zum Beispiel: 201703 201902- März 2017 bis Februar 2019. Bitte beschreiben Sie das von Ihnen gewählte Eingabeformat. Beachten Sie, dass die Eingabe alle Jahre von 1 bis 9999 umfassen kann. Der angegebene Monatsbereich umfasst sowohl den Start- als auch den Endmonat.

Ausgabe

Zwei ganze Zahlen: die Anzahl der Monate im angegebenen Bereich mit 31 Tagen und die Anzahl der Monate im Bereich mit weniger als 31 Tagen.

Beispiel: 14 10- 14 Knöchel, 10 Rillen (dies bedeutet, dass wir in diesem Monatsbereich 14 Monate mit vollen 31 Tagen und 10 Monate mit weniger als 31 Tagen haben).

Für eine Eingabe, bei der der zweite Monat im Bereich chronologisch vor dem ersten liegt 201612 201611, müssen Sie beispielsweise ein Nullpaar ausgeben.

Beispiele für Eingabe und Ausgabe

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

Regeln

  • Sie können eine beliebige Sprache auswählen
  • Ein Eingang pro Zeile
  • Dies ist , also gewinnt der kürzeste Code in Bytes!
  • Der Gewinner wird am 9. April ermittelt
  • Es gelten Standardlücken
  • PS: Dies ist meine erste Frage in PCG, es kann einige Inkonsistenzen geben. Sie können jederzeit bearbeiten und bestätigen, was für Sie unklar ist.

5
Sie sagen, dass der erste garantiert chronologisch vor dem zweiten liegt , aber dies ist für den Testfall falsch 201612 201611.
Dennis

2
Auf der Website befindet sich eine Sandbox, in der Sie die Frage nur posten können, um alle Zweifel auszuräumen.
Ghosts_in_the_code

1
Dreißig Tage haben September, April, Juni und November. Nach dem Februar haben alle anderen einunddreißig. So erinnere ich mich daran.
AdmBorkBork

@AdmBorkBork Das einzige Problem dabei ist die Endlosschleife (obligatorische xkcd-Referenz).
wizzwizz4

Ich nehme an, Sie beabsichtigen, den Gregorianischen Kalender im gesamten Datumsbereich zu verwenden?
Bis auf weiteres angehalten.

Antworten:


7

Gelee , 21 Bytes

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

Nimmt Eingaben wie [[y, m], [y, m]].

Probieren Sie es online aus!

Wie es funktioniert

ḅ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

Übernimmt die Eingabe als zwei Ganzzahlen im yyyymmFormat und in der Curry-Syntax (a)(b). Gibt ein Array mit zwei Ganzzahlen aus [knuckles, grooves].

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

Formatiert und kommentiert

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)

Testfälle

NB : Der dritte Testfall ist in diesem Snippet nicht enthalten, da er nur funktioniert, wenn in Ihrem Browser die Tail Call-Optimierung aktiviert ist.


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

Probieren Sie es online aus!

6 weitere durch Konvertierung in ein Lambda, danke an @math_junkie für die Idee. Gibt jetzt eine Liste mit den beiden Zahlen aus.

Vorherige Nicht-Lambda-Version (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),

Probieren Sie es online alt!

2 gespeichert mit Dank an @ovs für die Hilfe, die ich loszuwerden len(k). Ich hatte nicht daran gedacht, es zu benutzen None.

Eingabe ist eine Liste von Ganzzahlen im Format y1,m1,y2,m2

Etwas Dank an @KeerthanaPrabhakaran, der bin(2741)[2:]vor mir bekommen hat, was 1 Byte über die harte Codierung der Binärzeichenfolge spart.


Beeindruckend ... k = bin (2741) [2:] * (c + 1-a) hat mich umgehauen
offiziell am

1
Dies ist 2 Bytes kürzer
ovs

Brillant! Ich habe versucht, die Hacke herauszuarbeiten, um len(k)die letzte Scheibe loszuwerden . Vielen Dank.
ElPedro

1
Sie können 6 Bytes speichern, indem Sie ein Lambda verwenden: TIO
Mathe-Junkie

4

PHP , 259 256 249 248 237 221 Bytes

Von aross outgolfed : /codegolf//a/114512/38505

Eingabeformat: 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;

Probieren Sie es online aus!


ältere Versionen

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

Probieren Sie es online aus!

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

Probieren Sie es online aus!

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

Probieren Sie es online aus!

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

Probieren Sie es online aus!

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

Probieren Sie es online aus!


3

Stapel, 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%

Akzeptiert zwei Parameter im ymm-Format (dh 101 - 999912). Bisherige 129-Byte-Lösung auf Schleifenbasis:

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

Falsches Ergebnis für 000101 999912, wahrscheinlich aufgrund der Größenbeschränkung für Ganzzahlen?
Officialaimm

1
@officialaimm Falsches Eingabeformat, sorry - Jahr sollte keine führenden Nullen haben.
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

nimmt Eingabe in Form von JJJJMJ JJJJM

Gibt die Ausgabe als Anzahl der Knöchel aus

  • 2 Bytes gespeichert: Danke an Cole
  • 8 Bytes gespeichert: unerwünschte Variablen entfernt
  • 2 Bytes gespeichert: reduziert t = 0; k = 0 als t = k = 0
  • 2 Bytes gespart: Danke an Cole (das hatte ich schon mal verpasst)
  • 2 Bytes gespeichert: Danke an Keerthana
  • 8 Bytes gespeichert: unerwünschte Variablen entfernt
  • 3 Bytes gespeichert: Dank math_junkie (split ('') to split ())

1
Ich denke, Sie können einige Bytes reduzieren, indem Sie tun, n=intund vielleicht auch etwas execDummheit.
Cole

1
Ich denke, Sie können 2773&1<<r%12-1>0stattint('101010110101'[r%12-1])
Loovjo

@Loovjo Ich bekomme dabei einen Fehler!
Officialaimm

1
Verwenden von print([k,t-k])as print(k,t-k)würde das gewünschte Ergebnis erzeugen, (k,g)wodurch 2 Bytes reduziert werden!
Keerthana Prabhakaran

1
Ich glaube , Sie ersetzen split(' ')mitsplit()
Mathe -

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]

Probieren Sie es online aus!

  • 4 Bytes gespeichert - Vielen Dank an @math_junkie für den Vorschlag der if-else-Klausel mit Array-Suche!

Code aufschlüsseln,

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
Sie können Bytes speichern, indem Sie die if-elseKlauseln durch Array-Lookups ersetzen . Siehe diesen Beitrag für Details
Mathe-Junkie

Das war in der Tat ein cooler Weg! Wusste das vorher nicht! Vielen Dank!
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;

Laufen Sie so:

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

Erläuterung

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 Bytes wurden durch Verwendung des Zeitstempelstils anstelle des DateTime-Objektstils gespeichert
  • 6 Bytes gespart, indem der Variable kein Zeitstempel für das Enddatum zugewiesen $ewurde. Vergleichen Sie einfach direkt
  • 1 Byte wurde gespeichert, indem nicht die Anzahl der Rillen gezählt, sondern nur nach der Schleife berechnet wurde

$x++statt +$x++funktioniert auch.
Titus

@Titus, ich hatte das zuerst, erkannte aber, dass mit $xnicht initialisiert die Zeichenfolge sein würde 2017-12month, was ein nicht erkanntes Format ist und 1970 resultiert
3.

Böse ... es hat irgendwo funktioniert. Böse genug, dass es ohne ein Literal +in der Zeichenfolge funktioniert .
Titus

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

Probieren Sie es online aus!

Nimmt Eingabe als Form 2017-03. Verwendet die integrierten .NET-Datumsbibliotheken und durchläuft die Eingaben $abis $b, wobei jede Iteration erhöht $x++und addiert wird, $zwenn der aktuelle .MonthWert -in 2,4,6,9,11(dh ein Monat außerhalb von 31 Tagen) ist. Dann geben wir unsere Gesamtmonate abzüglich der Nicht-31-Tage-Monate $x-$zund der Nicht-31-Tage-Monate aus $z.

Wirft einen Fehler in den 0001-01zu testenden 9999-12Fall, da .NET nur Jahre bis zu unterstützt 9999, sodass das Finale .AddMonths(1)einen Überlauf verursacht. Gibt jedoch weiterhin die korrekten Werte aus, da es sich um einen nicht abschließenden Fehler handelt. es bewirkt nur, dass die Schleife beendet wird.

Wahrscheinlich wäre es kürzer, dies arithmetisch zu tun, wie die Python- oder JavaScript-Antworten, aber ich wollte einen Ansatz zeigen, der die integrierten .NET-Funktionen verwendet.


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

Probieren Sie es online aus!

braucht Golf ...

nimmt Eingabe als 2016-03 2018-10

Ausgänge:

  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

Schnell, 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}

Die Eingabe ist ein Array von zwei Ganzzahlen im Format gemäß Beispiel

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.