Policz przedziały czasowe


17

Zainspirowany scenariuszem z życia, o który poprosiłem o odpowiedź tutaj: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- pojawia się w zestawie z datą uruchomienia

Biorąc pod uwagę tablicę przedziałów czasowych (lub par data-data-początek), wypisz liczbę, ile przedziałów czasowych obejmuje każdego dnia, dla wszystkich dni w całym zakresie.

Na przykład:

  #      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

Biorąc pod uwagę powyższe dane, wyniki powinny być następujące:

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)

Musisz podać tylko liczby dla każdego dnia (w kolejności, posortowane od najstarszych do najnowszych); nie w jakich rekordach się pojawiają.

Możesz założyć, że każdy przedział czasowy zawiera tylko daty, a nie godziny; a więc całe dni są zawsze reprezentowane.

I / O

Dane wejściowe mogą być dowolnym formatem reprezentującym zestaw przedziałów czasowych - a więc albo zestaw par czasów, albo zbiór (wbudowanych) obiektów zawierających daty początkowe i końcowe. Terminy są ograniczone do okresu od 1901 do 2099, co jest normalne w przypadku wyzwań PPCG.

Możesz założyć, że dane wejściowe są wstępnie posortowane, jak chcesz (podaj w odpowiedzi). Daty wprowadzania są włącznie (więc zakres obejmuje całość dat rozpoczęcia i zakończenia).

Możesz również założyć, że z dwóch dat w danym zakresie pierwszy będzie starszy lub równy drugiemu (tzn. Nie będziesz miał ujemnego zakresu dat).

Dane wyjściowe to tablica zawierająca liczbę dla każdego dnia, od najstarszego do najnowszego na wejściu, posortowane według daty początkowej.

Zatem wynik dla powyższego przykładu byłby {3,2,2,0,1}

Możliwe jest, że niektóre dni nie zostaną uwzględnione w żadnym przedziale czasowym, w którym 0to przypadku jest generowany dla tej daty.

Zwycięskie kryteria

To jest golf golfowy, więc wygrywa najmniej bajtów. Obowiązują zwykłe wyłączenia

Przykład pseudo-algorytmu

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

Inne algorytmy pozwalające uzyskać ten sam wynik są w porządku.


3
Czy wymagana jest tablica liczb całkowitych, czy też możemy zwrócić coś innego, np. Słownik z kluczami jako każdą datą? Jeśli wolno nam zwrócić słownik, to czy możemy pominąć daty, których nie ma w żadnym z przedziałów czasowych?
JungHwan Min

1
czy możemy brać dane wejściowe jako dwie listy, jedną z datami rozpoczęcia, a drugą z odpowiadającymi im datami zakończenia?
Giuseppe

Tak, wszystkie te rzeczy są w porządku, z wyjątkiem pominięcia daty - wyraźnie mówię, że w takim przypadku powinno być 0
simonalexander2005

3
Czy mogę zapytać, dlaczego 0powinienem znajdować się w słowniku? Wydaje się to tylko zmuszać użytkownika do iteracji od min(input)do max(input), co wydaje się nie dodawać niczego do rdzenia wyzwania (obliczanie przedziałów czasowych).
JungHwan Min

2
@JungHwanMin Myślę, że to nie zmienia; ale ponieważ wyraźnie zamieściłem go w specyfikacji, kiedy go opublikowałem, nie chcę się z nim bawić i zmusić kogoś innego do
ponownej

Odpowiedzi:


3

APL (Dyalog Unicode) , 32 bajty SBCS

Pełny program Monituje stdin o listę par międzynarodowych numerów dat (np. Tego, czego używają Excel i MATLAB). Zarówno lista, jak i pary mogą być podawane w dowolnej kolejności, np. (End, Start). Wyświetla listę zliczeń na standardowe wyjście.

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

Jeśli jest to nieprawidłowe, listę par (YMD) można przekonwertować na dodatkowe 21 bajtów, łącznie 53:

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


 monit konsoli do oceny danych wejściowych

( Zastosuj następującą milczącą funkcję do każdej pary

⌊/ minimum (lit. min. redukcja), tj. data rozpoczęcia

⌈/- maksymalna (tj. data końcowa) minus to

⌊/+∘⍳ data rozpoczęcia plus zakres od 1 do 1

⌊/, data rozpoczęcia została do tego dodana

R← przypisz tę funkcję do R(dla R ange)

ε nlist (Spłaszczenie) wykaz zakresów na jednej liście

() Zastosuj do tego następującą milczącą funkcję:

R,⊢ wynik zastosowania R(tj. zakres dat), po którym następuje argument
  (zapewnia to, że każda data w zakresie jest reprezentowana co najmniej raz, a daty pojawiają się w posortowanej kolejności)

 Dla każdej pary unikalnych (data, jej wskaźniki wystąpienia na wejściu):

⊢∘≢ zignoruj ​​faktyczną datę na korzyść sumy indeksów

¯1+ dodaj -1 do tych danych statystycznych (ponieważ dodaliśmy jedną z każdej daty w zakresie)


9

JavaScript (ES6), 85 bajtów

Pobiera dane wejściowe jako listę Datepar. Oczekuje, że lista zostanie posortowana według daty początkowej. Zwraca tablicę liczb całkowitych.

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

Wypróbuj online!

lub 84 bajtów, jeśli możemy wziąć znaczniki czasu JS jako dane wejściowe (jak sugeruje @Shaggy)



Zapisz bajt, przyjmując prymitywne wartości jako dane wejściowe: TIO
Shaggy

7

JavaScript, 75 73 bajtów

Pobiera dane wejściowe jako posortowaną tablicę tablic par prymitywów daty, generuje obiekt, w którym klucze są prymitywami każdej daty, a wartości zlicza te daty w zakresach.

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

Spróbuj


Pracowałem nad tą 60-bajtową wersją, dopóki nie potwierdzono, że daty, które nie występują w żadnym z zakresów, muszą zostać uwzględnione, więc pospiesznie zaktualizowałem ją do powyższego rozwiązania.

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

Wypróbuj online (lub z danymi wyjściowymi czytelnymi dla ludzi )


Wygląda na to, że ES6 definiuje kolejność kluczy dla obiektów JS ( stackoverflow.com/a/31102605/8127 ), w zasadzie kolejność wstawiania kluczy ciągów i symboli (a Nodejs z TIO wydaje się postępować następująco: tinyurl.com/ybjqtd89 ). Ogólnie rzecz biorąc, moim zdaniem jest to, że szczegół implementacji (który jest tutaj celem) nie powinien dyktować interpretacji reguł wyzwania, ale poczekam na post Meta.
Sundar - Przywróć Monikę

6

Oktawa , 63 bajty

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

Wypróbuj online!

To było brzydkie!

Wyjaśnienie:

Pobiera dane wejściowe jako tablicę komórek datenumelementów (tj. Ciąg "2001-01-01"przekonwertowany na wartość liczbową, wyglądający tak:

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

gdzie d()jest funkcja datenum. Następnie używamy cellfundo tworzenia komórek z zakresami od pierwszej kolumny do drugiej dla każdego z tych wierszy. Łączymy te zakresy poziomo, dzięki czemu mamy długi poziomy wektor ze wszystkimi datami.

Następnie tworzymy histogram przy użyciu histctych wartości, z przedziałami podanymi w przedziale od najniższej do najwyższej daty.


5

R , 75 bajtów

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

Wypróbuj online!

Dane wejściowe to macierz, której pierwsza kolumna to Start, a druga kolumna to Koniec. Zakłada Początek <= Koniec, ale nie wymaga sortowania dat rozpoczęcia.


Tak dalece, jak mogłem spróbować powtórzyć odpowiedź Oktawy autorstwa Stewie Griffin ... co robię źle?
JayCe

dzieje się tak ze względu na sposób, w jaki R wprowadza swoje kosze hist; można zrobić, c(-25668,min(x):max(x))ponieważ -25568jest przed 1900, ale to kończy się dłużej niż sugerowane odpowiedzi. Biorąc to pod uwagę, istnieje lepszy sposób na generowanie dat niż apply; Mam taki, który ma 68 bajtów i po prostu nie znalazłem czasu, aby go opublikować.
Giuseppe,

Ach, nie, właściwie używaj (min(x)-1):max(x)i powinno działać zgodnie z oczekiwaniami; to jeśli nie możesz znaleźć applysposobu na generowanie dat, możesz uzyskać to do 63 bajtów i powiązać odpowiedź Octave.
Giuseppe

@Giuseppe Powinieneś opublikować to jako osobną odpowiedź :)
JayCe

wysłano :-) Muszę przyznać, że używałem, tablea factorwcześniej było to moje pierwotne użycie Mapdla 68 bajtów, ale histjest to fajne podejście, o którym zawsze zapominam, prawdopodobnie dlatego, że denerwujące jest prawidłowe umieszczenie pojemników (jak widzieliśmy )
Giuseppe,

4

Czerwony , 174 bajty

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

Całkiem długie i dosłowne wdrożenie.

Wypróbuj online!

Czytelny:

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 bajty

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

W pobliżu

Sformatowany:

 {                                   // 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 bajtów

-27 bajtów dzięki Jonathanowi Allanowi
+6 bajtów dzięki sundarowi

Pobiera dane wejściowe jako listę par obiektów datetime.
Zakłada, że ​​pierwsza para zaczyna się od najniższej daty.

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)

Wypróbuj online!


daysjest domyślnym argumentem dla timedelta.
Jonathan Allan

... w rzeczywistości myślę, że można upuścić from datetime import*i wymienić d+=timedelta(days=1)z d+=type(d-d)(1)od wejścia są już dates. 87 bajtów
Jonathan Allan

1
Wydaje się to zakładać, że początek pierwszego zakresu jest datą najniższą, a koniec ostatniego zakresu jest najwyższy - ale myślę, że czasami nie jest to możliwe, nawet jeśli OP pozwala nam posortować dane. Na przykład jeśli wejście jest [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. O ile OP nie pozwala nam dzielić i zmieniać kolejności tych zakresów podczas przetwarzania wstępnego (co wydaje się mało prawdopodobne), dane wejściowe nie mogą być poprawnie przetworzone przez ten kod.
sundar - Przywróć Monikę

@sundar Tak, rozumiem o czym mówisz. Zaktualizowałem rozwiązanie, aby sobie z tym poradzić. Dzięki!
Dead Possum

3

Wolfram Language (Mathematica) , 62 bajty

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

Wypróbuj online!

+35 bajtów, ponieważ określono OP, które 0należy uwzględnić w danych wyjściowych.

Jeżeli pominięcie wpisu w słowniku było dozwolone, 27 bajtów

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

Wypróbuj online!

Wbudowane DayRangeakceptuje dwa DateObjects (lub ciąg równoważny) i wyświetla listę Datesmiędzy tymi datami (włącznie).


3

R , 65 63 bajtów

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

Wypróbuj online!

To jest współpraca między JayCe a mną, przenosząca odpowiedź Stewiego Griffina na R.

Cytując JayCe:

Dane wejściowe to macierz, której pierwsza kolumna to Start, a druga kolumna to Koniec. Zakłada Początek <= Koniec, ale nie wymaga sortowania dat rozpoczęcia.

Być może $cjest to niepotrzebne, ale nie jest w duchu wyzwania, więc go uwzględniłem.


1
Min (x-1) dla 2 bajtów?
JayCe

^ Rozumiem przez to
JayCe

@JayCe tak, miło! Chciałem wrócić do tego wcześniej, ale zapomniałem.
Giuseppe

3

PowerShell, 122 121 118 113 bajtów

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

zapisz to jako count-timespan.ps1. Skrypt testowy:

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

Wyjaśnienie

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)

Dzięki! $cnt.Keys.Dateoczywiście.
mazzy

-3 bajty: functionzastąpione przez scriptblock. kody do gry w golfa i bez golfa są testowane.
mazzy

-5 bajtów: scriptblockwymieniane filter. Call of a filterjest bardziej kompaktowy.
mazzy

3

J, 43 bajty

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

dane wejściowe to lista par liczb całkowitych, gdzie każda liczba całkowita jest przesunięciem względem dowolnego dowolnego wspólnego 0-dni.

bez golfa

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

wyjaśnienie

struktura jest:

(A)&:(B) C
  • C tworzy hak, który daje czasownikowi głównemu A&:Bwejście po lewej, a wejście spłaszczone po prawej
  • B aka ((>./ (] + i.@>:@-) <./)"1)przyjmuje wartość minimalną i maksymalną listy i zwraca wynikowy zakres, i działa z rangą 1. stąd daje całkowity zasięg po prawej stronie, a poszczególne zakresy po lewej.
  • A używa następnie =z rangą "0 _(tj. Ranga {), aby policzyć, ile razy każde wejście pojawia się w dowolnym z zakresów. wreszcie z każdym rokiem zamyka się.

Wypróbuj online!


2

JavaScript (Node.js) , 80 bajtów

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

Wypróbuj online!

undefinedoznacza zero; Pierwszy element powinien zacząć się najwcześniej

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u jest krótszy, jeśli widzisz tylko elementy i używasz więcej stosu


6
Należy poprosić o potwierdzenie, że zastąpienie inną wartością 0jest dopuszczalne.
Shaggy

1

Rubinowy , 70 bajtów

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

Wypróbuj online!

Wejście:

Tablica par dat, posortowana według malejącej daty końcowej.


1

R (70)

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

Zakłada ramkę danych xz dwiema kolumnami ( Starti Endewentualnie Si E) z datami (klasa Date).

Wypróbuj online


Cześć, czy możesz dołączyć linki TIO (zobacz inne odpowiedzi) z przykładowym wejściem / wyjściem? Dołączanie pakietu nie jest oszustwem, ale library(magrittr)musi być uwzględnione w liczbie bajtów.
JayCe

Również zgodnie z konsensusem wnioski muszą być pełnymi funkcjami lub programami, a nie fragmentami, więc jeśli wybierzesz funkcję, której jedynym argumentem jest xtwoja odpowiedź, zaczyna się function(x)od treści funkcji.
JayCe

1

Julia 0.6 , 77 bajtów

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

Wypróbuj online!

Zainspirowany rozwiązaniem Python @ DeadPossum .

Pobiera dane wejściowe jako macierz, gdzie każdy wiersz ma dwie daty: datę początkową i końcową zakresu wejściowego. Zakłada, że ​​dane wejściowe mają najwcześniejszą datę i że każdy wiersz ma datę początkową jako pierwszą, ale nie zakłada sortowania poza tym między różnymi wierszami.


Starsze rozwiązanie:

Julia 0.6 , 124 bajty

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

Wypróbuj online!

Akceptuje dane wejściowe jako tablicę zakresów dat. Nie zakłada żadnego sortowania między różnymi zakresami w tablicy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.