Zählen Sie die Zeitspannen

17

Inspiriert von einem realen Szenario, das ich hier um eine Antwort gebeten habe: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- erscheint in einem Datumssatz ran

Bei einem vorgegebenen Array von Zeiträumen (oder Startdatum-Enddatum-Paaren) wird für alle Tage im Gesamtbereich die Anzahl der Zeiträume ausgegeben, die jeden Tag abdecken.

Beispielsweise:

  #      Start      End
  1    2001-01-01 2001-01-01
  2    2001-01-01 2001-01-03
  3    2001-01-01 2001-01-02
  4    2001-01-03 2001-01-03
  5    2001-01-05 2001-01-05

In Anbetracht der obigen Daten sollten die Ergebnisse wie folgt aussehen:

2001-01-01: 3 (Records 1,2,3)
2001-01-02: 2 (Records 2,3)
2001-01-03: 2 (Records 2,4)
2001-01-04: 0
2001-01-05: 1 (Record 5)

Sie müssen nur die Zählungen für jeden Tag ausgeben (in der Reihenfolge, sortiert nach ältesten und neuesten). nicht in welchen Datensätzen sie erscheinen.

Sie können davon ausgehen, dass jede Zeitspanne nur Daten und keine Zeiten enthält. und so sind immer ganze tage vertreten.

I / O

Eingang kann in jedem Format erfolgen, das eine Reihe von Zeiträumen darstellt - also entweder eine Reihe von Zeitpaaren oder eine Sammlung von (eingebauten) Objekten, die Start- und Enddaten enthalten. Die Datumsangaben sind, wie bei PPCG-Herausforderungen üblich, auf einen Zeitraum zwischen 1901 und 2099 begrenzt.

Sie können davon ausgehen, dass die Eingabe nach Belieben vorsortiert ist (in Ihrer Antwort angeben). Eingabedaten sind inklusive (der Bereich umfasst also das gesamte Start- und Enddatum).

Sie können auch davon ausgehen, dass von den beiden Daten in einem bestimmten Bereich das erste älter oder gleich dem zweiten ist (dh Sie haben keinen negativen Datumsbereich).

Die Ausgabe ist ein Array, das die Anzahl für jeden Tag vom ältesten bis zum neuesten in der Eingabe enthält, wenn nach Startdatum sortiert.

Die Ausgabe für das obige Beispiel wäre also {3,2,2,0,1}

In diesem Fall sind einige Tage möglicherweise nicht in einem Zeitbereich enthalten 0 wird für dieses Datum ausgegeben.

Gewinnkriterien

Dies ist Code-Golf, also gewinnt das niedrigste Byte. Es gelten die üblichen Ausschlüsse

Pseudo-Algorithmus Beispiel

For each time range in input
    If start is older than current oldest, update current oldest
    If end is newer than current newest, update current newest
End For
For each day in range oldest..newest
   For each time range
       If timerange contains day
            add 1 to count for day
End For
Output count array

Andere Algorithmen, um zum gleichen Ergebnis zu gelangen, sind in Ordnung.

simonalexander2005
quelle
3
Ist ein Array von Ganzzahlen erforderlich oder dürfen wir etwas anderes zurückgeben, z. B. ein Wörterbuch mit Schlüsseln für jedes Datum? Wenn wir ein Wörterbuch zurückgeben dürfen, können wir dann Daten weglassen, die in keinem der Zeiträume liegen?
JungHwan Min
1
Können wir Eingaben als zwei Listen vornehmen, eine mit Startdaten und die andere mit entsprechenden Enddaten?
Giuseppe,
Ja, all diese Dinge sind in Ordnung, außer ein Datum wegzulassen - ich sage ausdrücklich, dass in diesem Fall 0 ausgegeben werden sollte
simonalexander2005
3
Darf ich fragen, warum 0sollte in einem Wörterbuch sein? Es scheint nur den Benutzer zu zwingen, von min(input)bis zu iterieren max(input), was nichts zum Kern der Herausforderung (Rechenzeit) hinzuzufügen scheint.
JungHwan Min
2
@JungHwanMin Ich denke, es ändert nichts daran. aber weil ich es ausdrücklich in der Spezifikation hatte, als ich es veröffentlichte, möchte ich nicht damit
herumspielen

Antworten:

3

APL (Dyalog Unicode) , 32 Byte SBCS

Volles Programm. Fordert stdin zur Eingabe einer Liste mit Paaren internationaler Datumsnummern auf (z. B. was Excel und MATLAB verwenden). Sowohl Liste als auch Paare können in beliebiger Reihenfolge angegeben werden, z. B. (Ende, Start). Gibt die Liste der Zählungen in Standard aus.

¯1+⊢∘≢⌸(R,⊢)∊(R←⌊/,⌊/+∘⍳⌈/-⌊/)¨⎕Probieren Sie es online!

Wenn dies ungültig ist, kann eine Liste von (YMD-) Paaren für zusätzliche 21 Bytes konvertiert werden, was insgesamt 53 ergibt:

¯1+⊢∘≢⌸(R,⊢)∊(R⌊/,⌊/+∘⍳⌈/-⌊/)¨{2⎕NQ#'DateToIDN'⍵}¨¨⎕Probieren Sie es online!


 Eingabeaufforderung Konsole für ausgewertete Eingabe

( Wenden Sie auf jedes Paar die folgende implizite Funktion an

⌊/ das Minimum (lit. min-reduktion), dh das Startdatum

⌈/- das Maximum (dh Enddatum) minus das

⌊/+∘⍳ das Startdatum plus den Bereich 1-bis-das

⌊/, das Anfangsdatum, das dem vorausgeht

R← diese Funktion zuweisen R(für R ange)

ϵ nlist (verflachen) Sie die Liste der Bereiche in eine einzige Liste

() Wenden darauf folgende implizite Funktion an:

R,⊢ das Ergebnis der Anwendung R(dh den Datumsbereich), gefolgt von dem Argument
  (dies stellt sicher, dass jedes Datum im Bereich mindestens einmal dargestellt wird und die Daten in sortierter Reihenfolge angezeigt werden)

 Für jedes eindeutige Paar (Datum, seine Vorkommensindizes in der Eingabe) Folgendes tun:

⊢∘≢ Ignorieren Sie das aktuelle Datum zugunsten der Indexzählung

¯1+ Addiere -1 zu diesen Werten (weil wir eines von jedem Datum im Bereich vorangestellt haben)

Adam
quelle
9

JavaScript (ES6), 85 Byte

Nimmt die Eingabe als Liste von DatePaaren. Erwartet, dass die Liste nach dem Startdatum sortiert wird. Gibt ein Array von Ganzzahlen zurück.

f=(a,d=+a[0][0])=>[a.map(([a,b])=>n+=!(r|=d<b,d<a|d>b),r=n=0)|n,...r?f(a,d+864e5):[]]

Probieren Sie es online!

oder 84 Bytes, wenn wir JS-Zeitstempel als Eingabe verwenden können (wie von @Shaggy vorgeschlagen)

Arnauld
quelle
Speichern Sie ein Byte, indem Sie die primitiven Werte als Eingabe verwenden: TIO
Shaggy
7

JavaScript, 75 73 Bytes

Nimmt Eingaben als sortiertes Array von Arrays von Datumsprimitivpaaren an, gibt ein Objekt aus, bei dem die Schlüssel die Primitive jedes Datums sind und die Werte die Anzahl dieser Datumsangaben in den Bereichen.

a=>a.map(g=([x,y])=>y<a[0][0]||g([x,y-864e5],o[y]=~~o[y]+(x<=y)),o={})&&o

Versuch es


Ich habe an dieser 60-Byte-Version gearbeitet, bis bestätigt wurde, dass Daten, die in keinem der Bereiche enthalten sind , aufgenommen werden müssen. Aktualisieren Sie sie daher hastig auf die obige Lösung.

a=>a.map(g=([x,y])=>x>y||g([x+864e5,y],o[x]=-~o[x]),o={})&&o

Probieren Sie es online aus (oder mit lesbaren Daten in der Ausgabe )

Zottelig
quelle
Es sieht so aus, als ob ES6 eine Schlüsselreihenfolge für JS-Objekte definiert ( stackoverflow.com/a/31102605/8127 ), und im Grunde genommen eine Einfügereihenfolge für Zeichenfolgen- und Symbolschlüssel (und TIOs Nodejs scheinen dieser zu folgen: tinyurl.com/ybjqtd89 ). Im Allgemeinen bin ich der Meinung, dass ein Implementierungsdetail (das ist, was das Ziel hier ist) nicht die Interpretation der Herausforderungsregeln bestimmen sollte, aber ich werde auf den Meta-Post warten.
Sundar - Wiedereinsetzung von Monica am
6

Oktave , 63 Bytes

@(x)histc(t=[cellfun(@(c)c(1):c(2),x,'un',0){:}],min(t):max(t))

Probieren Sie es online!

Das war hässlich!

Erläuterung:

Nimmt die Eingabe als ein Zellenarray von datenumElementen (dh eine Zeichenfolge, "2001-01-01"die in einen numerischen Wert konvertiert wurde und wie folgt aussieht:

{[d("2001-01-01") d("2001-01-01")]
[d("2001-01-01") d("2001-01-03")]
[d("2001-01-01") d("2001-01-02")]
[d("2001-01-03") d("2001-01-03")]
[d("2001-01-05") d("2001-01-05")]};

wo d()ist die funktion datenum. Wir verwenden danncellfun erstellen für jede dieser Zeilen Zellen mit den Bereichen von der ersten bis zur zweiten Spalte. Wir verketten diese Bereiche horizontal, sodass wir einen langen horizontalen Vektor mit allen Daten haben.

Aus histcdiesen Werten wird ein Histogramm erstellt , wobei die Klassen durch den Bereich zwischen dem niedrigsten und dem höchsten Datum angegeben werden.

Stewie Griffin
quelle
5

R , 75 Bytes

function(x,u=min(x):max(x))rowSums(outer(u,x[,1],">=")&outer(u,x[,2],"<="))

Probieren Sie es online!

Die Eingabe ist eine Matrix, deren erste Spalte Start und deren zweite Spalte Ende ist. Nimmt an, dass Start <= Ende ist, erfordert jedoch keine Sortierung der Startdaten.

JayCe
quelle
Dies ist so weit wie ich in der Lage war , versucht zu gehen , um die Octave Antwort von Stewie Griffin zu replizieren ... was mache ich falsch?
JayCe
es liegt an der Art und Weise, in der R seine Bins macht hist; Sie tun können , c(-25668,min(x):max(x))da -25568vor ist 1900aber diese endet länger als Ihre vorgeschlagene Antwort. Davon abgesehen gibt es eine bessere Möglichkeit, die Daten zu generieren als apply; Ich habe eine, die bei 68 Bytes ist und ich habe einfach nicht die Zeit gefunden, es selbst zu posten.
Giuseppe,
Ah, nein, tatsächlich verwenden (min(x)-1):max(x)und es sollte wie erwartet funktionieren; Wenn Sie dann keine applyMöglichkeit finden, die Daten zu generieren, können Sie diese auf 63 Bytes bringen und die Oktavantwort binden.
Giuseppe,
@ Giuseppe Du solltest es als separate Antwort
posten
posted :-) Ich muss zugeben, ich habe verwendet tableund factorvor dem war meine ursprüngliche Verwendung Mapfür 68 Bytes, aber es histist eine nette Vorgehensweise, die ich immer vergesse, wahrscheinlich, weil es ärgerlich ist, die Mülleimer genau richtig zu machen (wie wir gesehen haben) )
Giuseppe
4

Rot , 174 Bytes

func[b][m: copy #()foreach[s e]b[c: s
until[m/(c): either none = v: m/(c)[1][v + 1]e < c: c + 1]]c: first sort b
until[print[either none = v: m/(c)[0][v]](last b)< c: c + 1]]

Sehr lange und wörtliche Implementierung.

Probieren Sie es online!

Lesbar:

f: func [ b ] [
    m: copy #()
    foreach [ s e ] b [
        c: s
        until [
            m/(c): either none = v: m/(c) [ 1 ] [ v + 1 ]   
            e < c: c + 1
        ]      
    ]
    c: first sort b
    until[
        print [ either none = v: m/(c) [ 0 ] [ v ] ]
        ( last b ) < c: c + 1
    ]      
]
Galen Ivanov
quelle
4

Groovy, 142 Bytes

{a={Date.parse('yyyy-mm-dd',it)};b=it.collect{a(it[0])..a(it[1])};b.collect{c->b.collect{it}.flatten().unique().collect{it in c?1:0}.sum()}}

Für den Fall, dass Sie nicht mehr weiterkommen möchten

Formatiert aus:

 {                                   // Begin Closure
    a={Date.parse('yyyy-mm-dd',it)}; // Create closure for parsing dates, store in a().
    b=it.collect{                    // For each input date pair...
        a(it[0])..a(it[1])           // Parse and create date-range.
    };
    b.collect{                       // For each date range...
        c->
        b.collect{                   // For each individual date for that range...
           it
        }.flatten().unique().collect{ // Collect unique dates.
            it in c?1:0
        }.sum()                      // Occurrence count.
    }
}
Magische Kraken-Urne
quelle
4

Python 2 , 114 87 93 Bytes

-27 Bytes dank Jonathan Allan
+6 Bytes dank Sundar

Übernimmt die Eingabe als Liste von Paaren von Datums- und Uhrzeitobjekten.
Angenommen, das erste Paar beginnt mit dem niedrigsten Datum.

def F(I):
 d=I[0][0]
 while d<=max(sum(I,[])):print sum(a<=d<=b for a,b in I);d+=type(d-d)(1)

Probieren Sie es online!

Totes Opossum
quelle
daysist das Standardargument für timedelta.
Jonathan Allan
... in der Tat denke ich, die fallen kann from datetime import*und ersetzen d+=timedelta(days=1)mit , d+=type(d-d)(1)da die Eingänge sind bereits dates. 87 Bytes
Jonathan Allan
1
Dies scheint vorauszusetzen, dass der Anfang des ersten Bereichs das niedrigste Datum und das Ende des letzten Bereichs das höchste ist - aber ich denke, dass dies manchmal nicht möglich ist, selbst wenn das OP uns erlaubt, sortierte Eingaben vorzunehmen. Zum Beispiel. wenn die Eingabe ist [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. Wenn wir diese Bereiche in OP nicht während der Vorverarbeitung aufteilen und neu anordnen können (was unwahrscheinlich erscheint), kann diese Eingabe von diesem Code nicht ordnungsgemäß verarbeitet werden.
Sundar - Reinstate Monica
@ Sundar Ja, ich verstehe, wovon du sprichst. Ich habe die Lösung aktualisiert, um damit umzugehen. Vielen Dank!
Dead Possum
3

Wolfram Language (Mathematica) , 62 Bytes

Lookup[d=DayRange;Counts[Join@@d@@@#],#[[1,1]]~d~#[[-1,1]],0]&

Probieren Sie es online!

+35 Bytes, weil OP dies spezifiziert hat 0 das in die Ausgabe einbezogen werden muss.

Wenn ein Eintrag in einem Wörterbuch weggelassen wurde, sind 27 Byte zulässig

Counts[Join@@DayRange@@@#]&

Probieren Sie es online!

Die integrierte Funktion DayRangeakzeptiert zwei DateObjects (oder ein String-Äquivalent) und gibt eine Liste Dateszwischen diesen Daten (einschließlich) aus.

JungHwan min
quelle
3

R , 65 63 Bytes

function(x)hist(unlist(Map(`:`,x[,1],x[,2])),min(x-1):max(x))$c

Probieren Sie es online!

Dies ist eine Zusammenarbeit zwischen JayCe und mir, die Stewie Griffins Antwort auf R. überträgt .

Um JayCe zu zitieren:

Die Eingabe ist eine Matrix, deren erste Spalte Start und deren zweite Spalte Ende ist. Nimmt an, dass Start <= Ende ist, erfordert jedoch keine Sortierung der Startdaten.

Möglicherweise $cist es unnötig, aber es ist nicht ganz im Sinne der Herausforderung, also habe ich es aufgenommen.

Giuseppe
quelle
1
Min (x-1) für 2 Bytes?
JayCe
^ Damit meine ich das
Jayce
@ JayCe ja, schön! Ich wollte früher darauf zurückkommen, aber ich habe es vergessen.
Giuseppe
3

Powershell, 122 121 118 113 Bytes

filter d{0..($_[-1]-($s=$_[0])).Days|%{$s.AddDays($_)}}$c=@{};$args|d|%{++$c.$_};,($c.Keys.Date|sort)|d|%{+$c.$_}

Speichern Sie es als count-timespan.ps1. Testskript:

.\count-timespan.ps1 `
    @([datetime]"2001-01-01", [datetime]"2001-01-01")`
    @([datetime]"2001-01-01", [datetime]"2001-01-03")`
    @([datetime]"2001-01-01", [datetime]"2001-01-02")`
    @([datetime]"2001-01-03", [datetime]"2001-01-03")`
    @([datetime]"2001-01-05", [datetime]"2001-01-05")

Erläuterung

filter d{                           # define a function with a pipe argument (it's expected that argument is an array of dates)
    0..($_[-1]-($s=$_[0])).Days|%{  # for each integer from 0 to the Days
                                    # where Days is a number of days between last and first elements of the range
                                    # (let $s stores a start of the range)
        $s.AddDays($_)              # output to the pipe a date = first date + number of the current iteration
    }                               # filter returns all dates for each range
}                                   # dates started from first element and ended to last element
$c=@{}                              # define hashtable @{key=date; value=count}
$args|d|%{++$c.$_}                  # count each date in a array of arrays of a date
,($c.Keys.Date|sort)|d|%{+$c.$_}    # call the filter via pipe with the array of sorted dates from hashtable keys

# Trace:
# call d @(2001-01-01, 2001-01-01) @(2001-01-01, 2001-01-03) @(2001-01-01, 2001-01-02) @(2001-01-03, 2001-01-03) @(2001-01-05, 2001-01-05)
# [pipe]=@(2001-01-01, 2001-01-01, 2001-01-02, 2001-01-03, 2001-01-01, 2001-01-02, 2001-01-03, 2001-01-05)
# $c=@{2001-01-03=2; 2001-01-01=3; 2001-01-05=1; 2001-01-02=2}
# call d @(2001-01-01, 2001-01-02, 2001-01-03, 2001-01-05)
# [pipe]=@(2001-01-01, 2001-01-02, 2001-01-03, 2001-01-04, 2001-01-05)
# [output]=@(3, 2, 2, 0, 1)
mazzy
quelle
Vielen Dank! $cnt.Keys.Datenatürlich.
mazzy
-3 Bytes: functionersetzt durch scriptblock. Golf- und Ungolf-Codes werden getestet.
mazzy
-5 Bytes: scriptblockersetzt am filter. Aufruf von a filterist kompakter.
mazzy
3

J, 43 Bytes

(],.[:+/@,"2="{~)&:((>./(]+i.@>:@-)<./)"1),

Die Eingabe ist eine Liste von Ganzzahlpaaren, wobei jede Ganzzahl der Versatz von einem beliebigen gemeinsamen 0-Tag ist.

ungolfed

(] ,. [: +/@,"2 ="{~)&:((>./ (] + i.@>:@-) <./)"1) ,

Erläuterung

Struktur ist:

(A)&:(B) C
  • C erzeugt einen Haken, der das Hauptverb ergibt A&:B die Eingabe links und der Eingabe rechts abgeflacht gibt
  • B aka ((>./ (] + i.@>:@-) <./)"1) nimmt das Minimum und Maximum einer Liste und gibt den resultierenden Bereich zurück und handelt mit Rang 1. Daher gibt es den Gesamtbereich rechts und die einzelnen Bereiche links an.
  • A verwendet dann =mit Rang "0 _(dh Rang von {), um zu zählen, wie oft jede Eingabe in einem der Bereiche erscheint. Mit diesen Zählungen macht es jedes Jahr einen Reißverschluss.

Probieren Sie es online!

Jona
quelle
2

JavaScript (Node.js) , 80 Byte

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-864e5],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u

Probieren Sie es online!

undefinedbedeutet Null; Das erste Element sollte frühestens beginnen

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u ist kürzer, wenn Sie nur Elemente sehen und mehr Stapel verwenden

l4m2
quelle
6
Sie sollten um Bestätigung bitten, dass das Ersetzen eines anderen Werts 0akzeptabel ist.
Shaggy
1

Ruby , 70 Bytes

->s{f,=s.min;(p s.count{|a,b|(f-a)*(f-b)<=0};f+=86400)until f>s[0][1]}

Probieren Sie es online!

Eingang:

Array von Datumspaaren, sortiert nach Enddatum in absteigender Reihenfolge.

GB
quelle
1

R (70)

function(x)(function(.)tabulate(.-min(.)+1))(unlist(Map(seq,x$S,x$E,"d")))

Setzt einen Datenrahmen xmit zwei Spalten ( Startund / Endoder möglicherweise Sund / oder) vorausE ) mit Datumsangaben (Klasse Date) .

Probieren Sie es online aus

lebatsnok
quelle
Hallo, könnten Sie TIO-Links (siehe andere Antworten) mit einem Beispiel für die Eingabe / Ausgabe einfügen? Es ist kein Betrug, ein Paket einzuschließen, sondern library(magrittr)muss in die Anzahl der Bytes einbezogen werden.
JayCe
Entsprechend dem Konsens müssen Einreichungen vollständige Funktionen oder Programme sein, keine Ausschnitte. Wenn Sie sich also für eine Funktion entscheiden, deren einziges Argument xIhre Antwort ist, beginnt mit function(x)und dann mit dem Hauptteil der Funktion.
JayCe
1

Julia 0,6 , 77 Bytes

M->[println(sum(dM[r,1]:M[r,2]for r1:size(M,1)))for dM[1]:max(M...)]

Probieren Sie es online!

Inspiriert von @ DeadPossums Python-Lösung .

Nimmt die Eingabe als Matrix, wobei jede Zeile zwei Daten enthält: das Anfangs- und das Enddatum eines Eingabebereichs. Angenommen, die Eingabe hat zuerst das früheste Datum und jede Zeile hat zuerst das Startdatum, setzt jedoch keine darüber hinausgehende Sortierung zwischen verschiedenen Zeilen voraus.


Ältere Lösung:

Julia 0,6 , 124 Bytes

R->(t=Dict();[[dkeys(t)?t[d]+=1:t[d]=1 for dg]for gR];[dkeys(t)?t[d]:0 for dmin(keys(t)...):max(keys(t)...)])

Probieren Sie es online!

Akzeptiert Eingaben als Array von Datumsbereichen. Nimmt keine Sortierung zwischen den verschiedenen Bereichen im Array an.

Sundar - Setzen Sie Monica wieder ein
quelle