Cuenta los tiempos

17

Inspirado en un escenario de la vida real, al que he pedido una respuesta aquí: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- aparece en un conjunto de fechas

Dada una serie de intervalos de tiempo (o pares de fecha de inicio-fin), genera un recuento de cuántos intervalos de tiempo cubren cada día, para todos los días en el rango total.

Por ejemplo:

  #      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

Dados los datos anteriores, los resultados deberían ser los siguientes:

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)

Solo necesita generar los recuentos de cada día (en orden, ordenados más antiguo-más nuevo); no en qué registros aparecen.

Puede suponer que cada intervalo de tiempo solo contiene fechas, no horarios; y así días completos siempre están representados.

I / O

La entrada puede ser cualquier formato que represente un conjunto de intervalos de tiempo, por lo que puede ser un conjunto de pares de tiempos o una colección de objetos (incorporados) que contienen fechas de inicio y finalización. Las fechas y horas están limitadas entre 1901 y 2099, como es normal para los desafíos de PPCG.

Puede suponer que la entrada está ordenada previamente como desee (especifique en su respuesta). Las fechas de entrada son inclusivas (por lo que el rango incluye la totalidad de las fechas de inicio y finalización).

También puede suponer que, de las dos fechas en cualquier rango dado, la primera será más antigua o igual a la segunda (es decir, no tendrá un rango de fechas negativo).

La salida es una matriz que contiene el recuento de cada día, desde el más antiguo hasta el más nuevo en la entrada cuando se ordena por Fecha de inicio.

Entonces, la salida para el ejemplo anterior sería {3,2,2,0,1}

Es posible que algunos días no se incluyan en ningún intervalo de tiempo, en cuyo caso 0se emite para esa fecha.

Criterios ganadores

Este es el código de golf, por lo que gana los bytes más bajos. Se aplican exclusiones habituales.

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

Otros algoritmos para llegar al mismo resultado están bien.

simonalexander2005
fuente
3
¿Se requiere un conjunto de enteros, o se nos permite devolver algo más, por ejemplo, un diccionario con claves como cada fecha? Si se nos permite devolver un diccionario, ¿podemos omitir fechas que no están en ninguno de los intervalos de tiempo?
JungHwan Min
1
¿Podemos tomar la entrada como dos listas, una con fechas de inicio y la otra con las fechas de finalización correspondientes?
Giuseppe
Sí, todas esas cosas están bien, excepto omitir una fecha. Explícitamente digo que debería salir 0 en ese caso
Simonalexander2005
3
¿Puedo preguntar por qué 0debería estar en un diccionario? Solo parece forzar al usuario a iterar de min(input)a max(input), lo que no parece agregar nada al núcleo del desafío (tiempos de cálculo).
JungHwan Min
2
@JungHwanMin Supongo que no lo altera; pero debido a que explícitamente tenía en la especificación cuando me envió, yo no quiero ir a jugar con él y hacer que otra persona rehacer su respuesta
simonalexander2005

Respuestas:

3

APL (Dyalog Unicode) , SBCS de 32 bytes

Programa completo Solicita stdin para obtener una lista de pares de números de fecha internacional (como lo que usan Excel y MATLAB). Tanto la lista como los pares se pueden dar en cualquier orden, por ejemplo (Fin, Inicio). Imprime la lista de recuentos en stdout.

¯1+⊢∘≢⌸(R,⊢)∊(R←⌊/,⌊/+∘⍳⌈/-⌊/)¨⎕Pruébalo en línea!

Si esto no es válido, se puede convertir una lista de pares (YMD) para 21 bytes adicionales, con un total de 53:

¯1+⊢∘≢⌸(R,⊢)∊(R⌊/,⌊/+∘⍳⌈/-⌊/)¨{2⎕NQ#'DateToIDN'⍵}¨¨⎕Pruébalo en línea!


 consola de solicitud de entrada evaluada

(...  aplique la siguiente función tácita a cada par

⌊/ el mínimo (lit. min-reducción), es decir, la fecha de inicio

⌈/- el máximo (es decir, la fecha de finalización) menos eso

⌊/+∘⍳ la fecha de inicio más el rango de 1 a ese

⌊/, la fecha de inicio antepuesta a eso

R← asignar esta función a R(para R ange)

ε nlist (aplanar) la lista de rangos en una sola lista

() Aplica la siguiente función tácita a eso:

R,⊢ el resultado de la aplicación R(es decir, el intervalo de fechas) seguido del argumento
  (esto asegura que cada fecha en el intervalo se represente al menos una vez y que las fechas aparezcan en orden)

...  para cada par de únicos (fecha, sus índices de ocurrencia en la entrada), haga:

⊢∘≢ ignorar la fecha real a favor de la cuenta de índices

¯1+ agregue -1 a esas cuentas (porque anteponemos una de cada fecha en el rango)

Adán
fuente
9

JavaScript (ES6), 85 bytes

Toma la entrada como una lista de Datepares. Espera que la lista se ordene por fecha de inicio. Devuelve una matriz de enteros.

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

Pruébalo en línea!

o 84 bytes si podemos tomar las marcas de tiempo JS como entrada (como lo sugiere @Shaggy)

Arnauld
fuente
Ah, loco!
Shaggy
Guarde un byte tomando los valores primitivos como entrada: TIO
Shaggy
7

JavaScript, 75 73 bytes

Toma la entrada como un conjunto ordenado de conjuntos de pares de primitivas de fecha, genera un objeto donde las claves son las primitivas de cada fecha y los valores los recuentos de esas fechas en los rangos.

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

Intentalo


Estaba trabajando en esta versión de 60 bytes hasta que se confirmó que las fechas que no aparecen en ninguno de los rangos deben incluirse, por lo que la actualicé rápidamente a la solución anterior.

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

Pruébelo en línea (o con fechas legibles por humanos en la salida )

Lanudo
fuente
Parece que ES6 define un orden clave para los objetos JS ( stackoverflow.com/a/31102605/8127 ), básicamente el orden de inserción para las cadenas y las teclas de símbolos (y Nodejs de TIO parece seguir eso: tinyurl.com/ybjqtd89 ). Y en general, mi opinión es que un detalle de implementación (que es el objeto aquí) no debería dictar la interpretación de las reglas de desafío, pero esperaré la publicación de Meta.
sundar - Restablecer Monica
6

Octava , 63 bytes

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

Pruébalo en línea!

¡Eso sí que fue feo!

Explicación:

Toma la entrada como una matriz de datenumelementos de celdas (es decir, una cadena "2001-01-01"convertida a un valor numérico, que se ve así:

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

donde d()es la función datenum. Luego usamos cellfunpara crear celdas con los rangos de la primera columna a la segunda para cada una de esas filas. Concatenamos estos rangos horizontalmente, de modo que tenemos un vector horizontal largo con todas las fechas.

Luego creamos un histograma utilizando histcestos valores, con bins dados por el rango entre la fecha más baja y la más alta.

Stewie Griffin
fuente
5

R , 75 bytes

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

Pruébalo en línea!

La entrada es una matriz cuya primera columna es Inicio y la segunda columna es Fin. Asume que Start <= End pero no requiere que se ordenen las fechas de Inicio.

JayCe
fuente
Esto es todo lo que pude intentar replicar la respuesta de Octave de Stewie Griffin ... ¿qué estoy haciendo mal?
JayCe
es por la forma en que R hace sus contenedores hist; podría hacerlo c(-25668,min(x):max(x))desde -25568antes, 1900pero esto termina siendo más largo que la respuesta sugerida. Dicho esto, hay una mejor manera de generar las fechas que apply; Tengo uno que tiene 68 bytes y simplemente no he encontrado el tiempo para publicarlo yo mismo.
Giuseppe
Ah, no, en realidad, use (min(x)-1):max(x)y debería funcionar como se esperaba; entonces, si puede encontrar la no applymanera de generar las fechas, puede obtener esto en 63 bytes y vincular la respuesta de octava.
Giuseppe
@Giuseppe Deberías publicarlo como una respuesta separada :)
JayCe
publicado :-) Tengo que admitir que estaba usando tabley factorantes de lo cual era mi uso original de Map68 bytes, pero histes un enfoque ordenado que siempre olvido, probablemente porque es molesto tener los contenedores correctamente (como hemos visto )
Giuseppe
4

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

Implementación bastante larga y literal.

Pruébalo en línea!

Legible:

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

Formateado:

 {                                   // 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.
    }
}
Urna de pulpo mágico
fuente
4

Pitón 2 , 114 87 93 bytes

-27 bytes gracias a Jonathan Allan
+6 bytes gracias a sundar

Toma datos como una lista de pares de objetos de fecha y hora.
Asume que el primer par comienza con la fecha más baja.

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)

Pruébalo en línea!

Zarigüeya muerta
fuente
dayses el argumento predeterminado para timedelta.
Jonathan Allan
... de hecho creo que se puede caer el from datetime import*y reemplazar d+=timedelta(days=1)con d+=type(d-d)(1)puesto que las entradas están ya datelo es. 87 bytes
Jonathan Allan
1
Esto parece suponer que el comienzo del primer rango es la fecha más baja Y el final del último rango es el más alto, pero creo que eso a veces no es posible incluso si el OP nos permite tomar entradas ordenadas. Por ej. si la entrada es [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. A menos que OP nos permita dividir y reorganizar estos rangos durante el preprocesamiento (lo que parece poco probable), este código no puede procesar esta entrada correctamente.
sundar - Restablecer Monica
@sundar Sí, veo de lo que estás hablando. He actualizado la solución para manejar esto. ¡Gracias!
Dead Possum
3

Wolfram Language (Mathematica) , 62 bytes

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

Pruébalo en línea!

+35 bytes porque OP especificó que 0debe incluirse en la salida.

Si se permitiera omitir una entrada en un diccionario, 27 bytes

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

Pruébalo en línea!

El incorporado DayRangeacepta dos DateObjects (o un equivalente de cadena) y genera una lista de Datesentre esas fechas (inclusive).

JungHwan Min
fuente
3

R , 65 63 bytes

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

Pruébalo en línea!

Esta es una colaboración entre JayCe y yo, portando la respuesta de Stewie Griffin a R.

Para citar a JayCe:

La entrada es una matriz cuya primera columna es Inicio y la segunda columna es Fin. Asume que Start <= End pero no requiere que se ordenen las fechas de Inicio.

Posiblemente, $ces innecesario, pero no está del todo en el espíritu del desafío, así que lo he incluido.

Giuseppe
fuente
1
Min (x-1) para 2 bytes?
JayCe
^ Con lo que quiero decir esto
JayCe
@ JayCe sí, bien! Tenía la intención de volver a esto antes, pero lo olvidé.
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.$_}

guárdelo como count-timespan.ps1. Script de prueba:

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

Explicación

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
fuente
¡Gracias! $cnt.Keys.Datepor supuesto.
mazzy
-3 bytes: functionreemplazado con scriptblock. Se prueban los códigos de golf y de golf.
mazzy
-5 bytes: scriptblockreemplazado en filter. La llamada de a filteres más compacta.
mazzy
3

J, 43 bytes

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

la entrada es una lista de pares de enteros, donde cada entero es el desplazamiento de cualquier día 0 arbitrario común.

sin golf

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

explicación

estructura es:

(A)&:(B) C
  • C crea un gancho que le da al verbo principal A&:Bla entrada a la izquierda y la entrada aplanada a la derecha
  • B aka ((>./ (] + i.@>:@-) <./)"1)toma el mínimo y el máximo de una lista y devuelve el rango resultante, y actúa con el rango 1. por lo tanto, da el rango total a la derecha y los rangos individuales a la izquierda.
  • A luego usa =con rango "0 _(es decir, rango de {) para contar cuántas veces aparece cada entrada en cualquiera de los rangos. finalmente se cierra todos los años con esos recuentos.

Pruébalo en línea!

Jonás
fuente
2

JavaScript (Node.js) , 80 bytes

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

Pruébalo en línea!

undefinedsignifica cero; El primer elemento debe comenzar más temprano

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u es más corto si solo ve elementos y usa más pila

l4m2
fuente
66
Debe solicitar confirmación de que 0es aceptable sustituirlo por otro valor .
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]}

Pruébalo en línea!

Entrada:

Matriz de pares de fechas, ordenadas por fecha de finalización descendente.

GB
fuente
1

R (70)

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

Presume un marco de datos xcon dos columnas ( Starty / Endo posiblemente Sy E) con fechas (clase Date).

Pruébalo en línea

lebatsnok
fuente
Hola, ¿podría incluir enlaces TIO (ver otras respuestas) con un ejemplo de entrada / salida? No es trampa incluir un paquete, pero library(magrittr)debe incluirse en el recuento de bytes.
JayCe
Además, según las presentaciones de consenso, deben ser funciones o programas completos, no fragmentos, por lo que si va con una función cuyo único argumento es que xsu respuesta comienza con function(x)y luego el cuerpo de la función.
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...)]

Pruébalo en línea!

Inspirado en la solución Python de @ DeadPossum .

Toma la entrada como una matriz, donde cada fila tiene dos fechas: las fechas de inicio y finalización de un rango de entrada. Asume que la entrada tiene la fecha más temprana primero, y que cada fila tiene la fecha de inicio primero, pero no asume ningún orden más allá de eso entre diferentes filas.


Solución anterior:

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

Pruébalo en línea!

Acepta entradas como una matriz de rangos de fechas. No asume ninguna clasificación entre los diferentes rangos de la matriz.

sundar - Restablece a Monica
fuente