Conta le fasce orarie


17

Ispirato da uno scenario di vita reale, a cui ho chiesto una risposta qui: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- appare-in-a-set-of-date-ran

Dato un array di periodi di tempo (o coppie startdate-enddate), genera un conteggio del numero di periodi di tempo coperti ogni giorno, per tutti i giorni nell'intervallo totale.

Per esempio:

  #      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

Dati i dati di cui sopra, i risultati dovrebbero essere i seguenti:

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)

Devi solo generare i conteggi per ogni giorno (in ordine, ordinati dal più vecchio al più recente); non in quali record compaiono.

Puoi presumere che ogni periodo di tempo contenga solo date, non orari; e così i giorni interi sono sempre rappresentati.

I / O

L'input può essere qualsiasi formato che rappresenti un insieme di intervalli di tempo, quindi un insieme di coppie di tempi o una raccolta di oggetti (incorporati) contenenti le date di inizio e fine. Le date sono limitate tra il 1901 e il 2099, come è normale per le sfide PPCG.

Puoi presumere che l'input sia preordinato come preferisci (specifica nella tua risposta). Le date di input sono incluse (quindi l'intervallo comprende tutte le date di inizio e fine).

Puoi anche supporre che, delle due date in un dato intervallo, la prima sarà più vecchia o uguale alla seconda (cioè non avrai un intervallo di date negativo).

L'output è un array che contiene il conteggio per ogni giorno, dal più vecchio al più recente nell'input quando ordinato per Data di inizio.

Quindi, l'output per l'esempio sopra sarebbe {3,2,2,0,1}

È possibile che alcuni giorni non siano inclusi in alcun intervallo di tempo, nel qual caso 0viene emesso per quella data.

Criteri vincenti

Questo è code-golf, quindi vince il byte più basso. Si applicano le esclusioni usuali

Esempio di pseudo-algoritmo

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

Altri algoritmi per ottenere lo stesso risultato vanno bene.


3
È necessaria una matrice di numeri interi o è possibile restituire qualcos'altro, ad esempio un dizionario con chiavi come ogni data? Se ci è permesso di restituire un dizionario, allora possiamo omettere le date che non sono in nessuno dei periodi?
JungHwan Min

1
possiamo prendere input come due elenchi, uno con le date di inizio e l'altro con le date di fine corrispondenti?
Giuseppe,

Sì, tutte queste cose vanno bene, tranne omettere una data - dico esplicitamente che in quel caso dovrebbe essere emesso 0
simonalexander2005

3
Posso chiedere perché 0dovrebbe essere in un dizionario? Sembra solo forzare l'utente a iterare da min(input)a max(input), il che non sembra aggiungere nulla al nocciolo della sfida (calcolo dei tempi).
JungHwan Min,

2
@JungHwanMin Immagino che non lo modifichi; ma poiché l'ho esplicitamente inserito nelle specifiche quando l'ho pubblicato, non voglio andare a rovinarlo e far ripetere a qualcun altro la sua risposta
simonalexander2005

Risposte:


3

APL (Dyalog Unicode) , 32 byte SBCS

Programma completo. Richiede stdin per un elenco di coppie di numeri di data internazionali (come quello che usano Excel e MATLAB). Sia l'elenco che le coppie possono essere indicati in qualsiasi ordine, ad es. (Fine, Inizio). Stampa l'elenco dei conteggi su stdout.

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

Se ciò non è valido, è possibile convertire un elenco di coppie (YMD) per altri 21 byte, per un totale di 53:

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


 pronta console per input valutato

(...  applica la seguente funzione tacita a ciascuna coppia

⌊/ il minimo (lit. riduzione minima), ovvero la data di inizio

⌈/- il massimo (cioè la data di fine) meno quello

⌊/+∘⍳ la data di inizio più l'intervallo da 1 a quello

⌊/, la data di inizio anteposta a quella

R← assegnare questa funzione R(per R ange)

ε nlist (Appiattisci) all'elenco di intervalli in un unico elenco

(... ) applica la seguente funzione tacita a quella:

R,⊢ il risultato dell'applicazione R(ovvero l'intervallo di date) seguito dall'argomento
  (ciò garantisce che ogni data nell'intervallo sia rappresentata almeno una volta e che le date siano visualizzate in ordine)

...  per ogni coppia di unici (data, i suoi indici di occorrenza nell'input), fai:

⊢∘≢ ignora la data effettiva a favore del conteggio degli indici

¯1+ aggiungi -1 a quei conteggi (perché abbiamo anteposto una di ciascuna data nell'intervallo)


9

JavaScript (ES6), 85 byte

Accetta input come un elenco di Datecoppie. Si aspetta che l'elenco venga ordinato per data di inizio. Restituisce una matrice di numeri interi.

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):[]]

Provalo online!

o 84 byte se possiamo prendere i timestamp JS come input (come suggerito da @Shaggy)



Salvare un byte prendendo i valori primitivi come input: TIO
Shaggy

7

JavaScript, 75 73 byte

Prende l'input come una matrice ordinata di matrici di coppie primitive di date, genera un oggetto in cui le chiavi sono le primitive di ciascuna data e i valori i conteggi di quelle date negli intervalli.

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

Provalo


Stavo lavorando su questa versione da 60 byte fino a quando non è stato confermato che le date che non compaiono in nessuno degli intervalli devono essere incluse in modo affrettato e aggiornato alla soluzione sopra.

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

Provalo online (o con date leggibili nell'output )


Sembra ES6 fa definire un ordine di chiave per gli oggetti JS ( stackoverflow.com/a/31102605/8127 ), ordine di inserimento basicaly per le chiavi di stringa e il simbolo (e Nodejs Tio sembra seguire che: tinyurl.com/ybjqtd89 ). E in generale la mia opinione è che un dettaglio di implementazione (che è l'oggetto qui) non dovrebbe dettare l'interpretazione delle regole della sfida, ma aspetterò il post Meta.
Sundar - Ripristina Monica il

6

Ottava , 63 byte

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

Provalo online!

Adesso era brutto!

Spiegazione:

Prende l'input come una matrice di celle di datenumelementi (ovvero una stringa "2001-01-01"convertita in un valore numerico, in questo modo:

{[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")]};

dov'è d()la funzione datenum. Quindi utilizziamo cellfunper creare celle con gli intervalli dalla prima colonna alla seconda per ciascuna di quelle righe. Concateniamo questi intervalli orizzontalmente, in modo da avere un vettore orizzontale lungo con tutte le date.

Quindi creiamo un istogramma utilizzando histcquesti valori, con i bin dati forniti dall'intervallo tra la data più bassa e quella più alta.


5

R , 75 byte

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

Provalo online!

L'input è una matrice la cui prima colonna è Inizio e la seconda colonna è Fine. Presuppone Inizio <= Fine ma non richiede l'ordinamento delle date di inizio.


Questo è quanto ho potuto provare a replicare la risposta Octave di Stewie Griffin ... che cosa sto facendo di sbagliato?
JayCe,

è a causa del modo in cui R fa i suoi bidoni hist; si potrebbe fare c(-25668,min(x):max(x))poiché -25568è prima 1900ma questo finisce per essere più lungo della risposta suggerita. Detto questo, c'è un modo migliore per generare le date di apply; Ne ho uno a 68 byte e non ho trovato il tempo di pubblicarlo da solo.
Giuseppe,

Ah, no, in realtà, usa (min(x)-1):max(x)e dovrebbe funzionare come previsto; quindi se riesci a trovare la non- applymodo per generare le date puoi portarlo a 63 byte e legare la risposta di Ottava.
Giuseppe,

@Giuseppe Dovresti pubblicarlo come risposta separata :)
JayCe,

postato :-) Devo ammettere che stavo usando tablee factorprima del quale era il mio uso originale Mapper 68 byte, ma histè un approccio pulito di cui mi dimentico sempre, probabilmente perché è fastidioso ottenere i bin giusti (come abbiamo visto )
Giuseppe,

4

Rosso , 174 byte

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

Implementazione abbastanza lunga e letterale.

Provalo online!

Leggibile:

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

4

Groovy, 142 byte

{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()}}

Formattato:

 {                                   // 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.
    }
}

4

Python 2 , 114 87 93 byte

-27 byte grazie a Jonathan Allan
+6 byte grazie a Sundar

Accetta input come elenco di coppie di oggetti datetime.
Presuppone che la prima coppia inizi con la data più bassa.

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)

Provalo online!


daysè l'argomento predefinito per timedelta.
Jonathan Allan,

... in effetti penso che puoi eliminare from datetime import*e sostituire d+=timedelta(days=1)con d+=type(d-d)(1)poiché gli input sono già dates. 87 byte
Jonathan Allan,

1
Questo sembra presumere che l'inizio del primo intervallo sia la data più bassa E la fine dell'ultimo intervallo sia la più alta, ma penso che a volte ciò non sia possibile anche se l'OP ci consente di prendere input ordinati. Per es. se l'input è [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. A meno che OP non ci consenta di dividere e riorganizzare questi intervalli durante la preelaborazione (che sembra improbabile), questo input non può essere elaborato correttamente da questo codice.
Sundar - Ripristina Monica il

@sundar Sì, capisco di cosa stai parlando. Ho aggiornato la soluzione per gestire questo. Grazie!
Dead Possum,

3

Wolfram Language (Mathematica) , 62 byte

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

Provalo online!

+35 byte perché OP specificato che 0deve essere incluso nell'output.

Se è stata omessa una voce in un dizionario, 27 byte

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

Provalo online!

Il built-in DayRangeaccetta due DateObjects (o un equivalente stringa) e genera un elenco Datestra quelle date (incluso).


3

R , 65 63 byte

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

Provalo online!

Questa è una collaborazione tra JayCe e me stesso, che porta la risposta di Stewie Griffin a R.

Per citare JayCe:

L'input è una matrice la cui prima colonna è Inizio e la seconda colonna è Fine. Presuppone Inizio <= Fine ma non richiede l'ordinamento delle date di inizio.

Forse, $cnon è necessario ma non è esattamente nello spirito della sfida, quindi l'ho incluso.


1
Min (x-1) per 2 byte?
JayCe,

^ Con questo
JayCe

@JayCe sì, bello! Volevo tornare su questo prima ma ho dimenticato.
Giuseppe,

3

Powershell, 122 121 118 113 byte

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

salvalo come count-timespan.ps1 . Script di prova:

.\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")

Spiegazione

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)

Grazie! $cnt.Keys.Dateovviamente.
mazzy,

-3 byte: functionsostituito con scriptblock. vengono testati i codici golf e non golf.
mazzy,

-5 byte: scriptblocksostituito il filter. La chiamata di a filterè più compatta.
mazzy,

3

J, 43 byte

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

l'input è un elenco di coppie di numeri interi, in cui ogni numero intero è l'offset rispetto a qualsiasi 0-day comune arbitrario.

ungolfed

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

spiegazione

la struttura è:

(A)&:(B) C
  • C crea un hook che fornisce il verbo principale A&:B l'input a sinistra e l'input appiattito a destra
  • B aka ((>./ (] + i.@>:@-) <./)"1) prende il minimo e il massimo di un elenco e restituisce l'intervallo risultante e agisce con il rango 1. quindi fornisce l'intervallo totale a destra e gli intervalli individuali a sinistra.
  • A utilizza quindi =con rango "0 _(cioè rango di {) per contare quante volte ogni input appare in uno degli intervalli. finalmente si chiude ogni anno con quei conteggi.

Provalo online!


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

Provalo online!

undefinedsignifica zero; Il primo elemento dovrebbe iniziare prima

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u è più corto se vedi solo elementi e usi più stack


6
Dovresti chiedere conferma che 0è accettabile la sostituzione di un altro valore .
Shaggy,

1

Rubino , 70 byte

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

Provalo online!

Ingresso:

Matrice di coppie di date, ordinate per data di fine decrescente.


1

R (70)

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

Presume un frame di dati xcon due colonne ( Starte Endo possibilmente Se E) con le date (classeDate ).

Provalo online


Ciao, potresti includere collegamenti TIO (vedi altre risposte) con un esempio di input / output? Non è ingannevole includere un pacchetto, ma library(magrittr)deve essere incluso nei conteggi dei byte.
JayCe,

Inoltre, per consenso, gli invii devono essere funzioni o programmi completi, non frammenti, quindi se vai con una funzione il cui unico argomento è la xtua risposta inizia function(x)e quindi il corpo della funzione.
JayCe,

1

Julia 0.6 , 77 byte

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

Provalo online!

Ispirato alla soluzione Python di @ DeadPossum .

Prende l'input come una matrice, in cui ogni riga ha due date: le date di inizio e fine di un intervallo di input. Presuppone che l'input abbia prima la prima data e che ogni riga abbia prima la data di inizio, ma non assume alcun ordinamento oltre quello tra righe diverse.


Soluzione precedente:

Julia 0.6 , 124 byte

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)...)])

Provalo online!

Accetta input come una matrice di intervalli di date. Non presuppone alcun ordinamento tra i diversi intervalli nell'array.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.