Zaman aralıklarını sayın


17

Burada bir cevap istediğim gerçek hayat senaryosundan esinlenerek: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- görünür-in-a-set-of-tarih-ran

Bir dizi zaman aralığı (veya başlangıç ​​tarihi-bitiş tarihi çiftleri) göz önüne alındığında, toplam aralıktaki tüm günler için her gün kaç zaman aralığını kapsadığının bir sayımını alın.

Örneğin:

  #      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

Yukarıdaki veriler göz önüne alındığında, sonuçlar aşağıdaki gibi olmalıdır:

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)

Sadece her gün için sayıları çıkarmanız gerekir (sırayla, en eski-en yeni sıralanır); hangi kayıtlarda göründüklerini değil.

Her zaman aralığının zaman değil yalnızca tarih içerdiğini varsayabilirsiniz; ve böylece bütün günler daima temsil edilir.

I / O

Girdi , bir zaman aralıklarını temsil eden herhangi bir format olabilir - bu nedenle ya bir çift zaman kümesi ya da başlangıç ​​ve bitiş tarihleri ​​içeren (yerleşik) nesneler koleksiyonu. Tarih saatleri, PPCG zorlukları için normal olduğu gibi 1901 ve 2099 arasında sınırlıdır.

Girişin istediğiniz gibi önceden sıralandığını varsayabilirsiniz (cevabınızda belirtin). Giriş tarihleri ​​kapsayıcıdır (bu nedenle aralık başlangıç ​​ve bitiş tarihlerinin tamamını içerir).

Herhangi bir aralıktaki iki tarih arasında birincinin ikinciden daha eski veya ona eşit olacağını varsayabilirsiniz (yani, negatif bir tarih aralığınız olmaz).

Çıktı , Başlangıç ​​Tarihine göre sıralandığında, her gün için sayıyı içeren en eski ile en yeni arasındaki sayıyı içeren bir dizidir.

Yani, yukarıdaki örneğin çıktısı {3,2,2,0,1}

Bazı günlerin herhangi bir zaman aralığına dahil edilmemesi mümkündür, bu durumda 0o tarih için çıktı alınabilir .

Kazanma Kriterleri

Bu kod golf, bu yüzden en düşük bayt kazanır. Genel istisnalar geçerlidir

Yalancı algoritma örneği

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

Aynı sonuca ulaşmak için diğer algoritmalar iyidir.


3
Bir tamsayı dizisi gerekli mi, yoksa başka bir şey döndürmemize izin veriliyor mu, her tarihte anahtarları olan bir sözlük mi? Bir sözlük döndürmemize izin verilirse, zaman aralıklarında olmayan tarihleri ​​atlayabilir miyiz?
JungHwan Min

1
girdiyi biri başlangıç ​​tarihleri ​​diğeri karşılık gelen bitiş tarihleri ​​olan iki liste olarak alabilir miyiz?
Giuseppe

Evet, tüm bu şeyler iyi, bir tarihi atlamak dışında - açıkça bu durumda 0 çıktısı gerektiğini söylüyorum
simonalexander2005

3
Neden 0sözlükte olması gerektiğini sorabilir miyim ? Sadece gelen yineleme için kullanıcı zorlamak için görünür min(input)için max(input)meydan (bilgisayar zaman geçişleri) özüne bir şey eklemek görünmüyor hangi.
JungHwan Min

2
@JungHwanMin Sanırım bunu değiştirmez; ancak yayınladığımda açık bir şekilde spesifikasyonda bulunduğum için, onunla
uğraşmak

Yanıtlar:


3

APL (Dyalog Unicode) , 32 bayt SBCS

Tam program. Stdin'i Uluslararası Tarih Numaraları çiftlerinin bir listesi için ister (Excel ve MATLAB'ın kullandığı gibi). Hem liste hem de çiftler herhangi bir sırayla verilebilir, örneğin (End, Start). Sayımların listesini stdout'a yazdırır.

¯1+⊢∘≢⌸(R,⊢)∊(R←⌊/,⌊/+∘⍳⌈/-⌊/)¨⎕Çevrimiçi deneyin!

Bu geçersizse, (YMD) çiftlerinin listesi ek olarak 21 bayt için dönüştürülebilir ve toplamda 53:

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


 değerlendirilmiş girdi için istem konsolu

( Her bir çifte aşağıdaki zımni fonksiyonu uygulayın

⌊/ minimum (lit. min-indirgeme), yani başlangıç ​​tarihi

⌈/- maksimum (yani bitiş tarihi) eksi

⌊/+∘⍳ başlangıç ​​tarihi ve aralık 1

⌊/, başlangıç ​​tarihi buna eklenir

R← bu işlevi R( R ange için) olarak ata

ε nlist (düzleştirmek) tek bir liste halinde aralıkları listesi

(… Buna ) aşağıdaki örtük işlevini uygulayın:

R,⊢ uygulamanın sonucu R(yani tarih aralığı) ve ardından bağımsız değişken
  (bu, aralıktaki her tarihin en az bir kez temsil edilmesini ve tarihlerin sıralı sırada görünmesini sağlar)

 Her bir benzersiz çift için (tarih, girdideki oluşum endeksleri) şunları yapın:

⊢∘≢ endeks taksitli lehine gerçek tarihi göz ardı

¯1+ bu hesaplara -1 ekleyin (çünkü aralıktaki her bir tarihten birini tercih ettik)


9

JavaScript (ES6), 85 bayt

Girişi Dateçiftler listesi olarak alır . Listenin başlangıç ​​tarihine göre sıralanmasını bekler. Bir tamsayı dizisi döndürür.

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

Çevrimiçi deneyin!

veya JS zaman damgalarını girdi olarak alabilirsek 84 bayt (@Shaggy tarafından önerildiği gibi)



İlkel değerleri girdi olarak alarak bir bayt kaydedin: TIO
Shaggy

7

JavaScript, 75 73 bayt

Girdiyi tarih ilkel çiftlerinin sıralı dizi dizisi olarak alır, anahtarların her bir tarihin temel öğeleri olduğu bir nesne ve aralıklardaki bu tarihlerin sayıları değerlerini verir.

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

Dene


Aralıkların hiçbirinde görünmeyen tarihlerin bu kadar aceleyle yukarıdaki çözüme güncellenmesi gerektiği doğrulanana kadar bu 60 baytlık sürüm üzerinde çalışıyordum .

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

Çevrimiçi deneyin (veya çıktıda insan tarafından okunabilir tarihlerle )


Görünüşe göre ES6, JS nesneleri ( stackoverflow.com/a/31102605/8127 ), dize ve simge anahtarları için temel olarak ekleme sırası (ve TIO Nodejs şu şekilde görünüyor: tinyurl.com/ybjqtd89 ). Ve genel olarak benim görüşüm, bir uygulama detayının (buradaki nesnenin ne olduğu) meydan okuma kurallarının yorumunu dikte etmemesi gerektiğidir, ancak Meta postasını bekleyeceğim.
sundar - Monica'yı

6

Oktav , 63 bayt

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

Çevrimiçi deneyin!

Şimdi bu çirkin!

Açıklama:

Girdiyi bir hücre datenumöğeleri dizisi olarak alır (örneğin "2001-01-01", sayısal değere dönüştürülmüş bir dize , şöyle görünür:

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

d()fonksiyon nerede datenum. Daha sonra cellfun, bu satırların her biri için birinci sütundan ikinciye kadar aralıklarla hücreler oluşturmak için kullanırız . Bu aralıkları yatay olarak birleştiririz, böylece tüm tarihleri ​​içeren uzun bir yatay vektörümüz olur.

Daha sonra histc, bu değerlerden yararlanarak, en düşük ve en yüksek tarih arasındaki aralıkta bölmeler verilen bir histogram oluştururuz .


5

R , 75 bayt

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

Çevrimiçi deneyin!

Girdi, ilk sütunu Başlat ve ikinci sütunu Bitiş olan bir matristir. Başlangıç ​​<= Bitiş olduğunu varsayar, ancak Başlangıç ​​tarihlerinin sıralanmasını gerektirmez.


Bu ben yanlış yapıyorum ... kadarıyla ben Stewie Griffin tarafından Octave cevabını çoğaltmak için çalışıyoruz gitmek başardı gibidir?
JayCe

R'nin kutularını içine alma şekli yüzünden hist; Yapabileceğin c(-25668,min(x):max(x))beri -25568öncedir 1900ama artık önerdi cevap daha olmak kadar bu biter. Bununla birlikte, tarihleri ​​oluşturmak için daha iyi bir yol var apply; 68 baytta bir tane var ve bunu kendim gönderecek zamanı bulamadım.
Giuseppe

Ah, hayır, aslında, kullanın (min(x)-1):max(x)ve beklendiği gibi çalışması gerekir; applytarihleri ​​oluşturmak için bir not bulabilirseniz, bunu 63 bayta alabilir ve Octave yanıtını bağlayabilirsiniz.
Giuseppe

@Giuseppe Ayrı bir cevap olarak göndermelisiniz :)
JayCe

gönderildi :-) itiraf etmeliyim, kullanıyordum tableve daha factorönce Map68 baytlık orijinal kullanımımdı , ancak histher zaman unutduğum düzgün bir yaklaşım, muhtemelen kutuları doğru bir şekilde almak için can sıkıcı olduğu için (gördüğümüz gibi) )
Giuseppe

4

Kırmızı , 174 bayt

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

Oldukça uzun ve gerçek uygulama.

Çevrimiçi deneyin!

Okunabilir:

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 bayt

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

Biçimlendirildi:

 {                                   // 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 bayt

Jonathan Allan sayesinde -27 bayt
Sundar sayesinde +6 bayt

Girdiyi datetime nesneleri çiftleri listesi olarak alır.
İlk çiftin en düşük tarihle başladığını varsayar.

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)

Çevrimiçi deneyin!


daysiçin varsayılan argümandır timedelta.
Jonathan Allan

...in fact I think you can drop the from datetime import* and replace d+=timedelta(days=1) with d+=type(d-d)(1) since the inputs are already dates. 87 bytes
Jonathan Allan

1
This seems to assume that the start of the first range is the lowest date AND the end of the last range is the highest - but I think that's sometimes not possible even if the OP allows us to take sorted input. For eg. if input is [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. Unless OP allows us to split and rearrange these ranges during preprocessing (which seems unlikely), this input can't be processed by this code properly.
sundar - Reinstate Monica

@sundar Yes, I see what you're talking about. I've updated solution to handle this. Thanks!
Dead Possum

3

Wolfram Language (Mathematica), 62 bytes

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

Try it online!

+35 bytes because OP specified that 0 must be included in the output.

If omitting an entry in a dictionary were allowed, 27 bytes

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

Try it online!

The built-in DayRange accepts two DateObjects (or a string equivalent) and outputs a list of Dates between those dates (inclusive).


3

R, 65 63 bytes

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

Try it online!

This is a collaboration between JayCe and myself, porting Stewie Griffin's answer over to R.

To quote JayCe:

Input is a matrix whose first column is Start and second column is End. Assumes Start<=End but does not require Start dates to be sorted.

Possibly, $c is unnecessary but it's not quite in the spirit of the challenge so I've included it.


1
Min(x-1) for 2 bytes ?
JayCe

^ By which I mean this
JayCe

@JayCe yes, nice! I meant to come back to this earlier but I forgot.
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.$_}

save it as count-timespan.ps1. Test script:

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

Explanation

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)

Thanks! $cnt.Keys.Date of course.
mazzy

-3 bytes: function replaced with scriptblock. golfed and ungolfed codes are tested.
mazzy

-5 bytes: scriptblock replaced on filter. Call of a filter is more compact.
mazzy

3

J, 43 bytes

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

the input is a list of pairs of integers, where each integer is the offset from any arbitrary common 0-day.

ungolfed

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

explanation

structure is:

(A)&:(B) C
  • C creates a hook that gives the main verb A&:B the input on the left and the input flattened on the right
  • B aka ((>./ (] + i.@>:@-) <./)"1) takes the min and max of a list and returns the resulting range, and acts with rank 1. hence it gives the total range on the right, and the individual ranges on the left.
  • A then uses = with rank "0 _ (ie, rank of {) to count how many times each input appears in any of the ranges. finally it zips every year with those counts.

Try it online!


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

Try it online!

undefined means zero; First element should start earliest

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u is shorter if you only see elements and use more stack


6
You should ask for confirmation that substituting another value for 0 is acceptable.
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]}

Try it online!

Input:

Array of pairs of dates, sorted by ending date descending.


1

R (70)

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

Presumes a data frame x with two columns (Start and End or possibly S and E) with dates (class Date).

Try it online


Hi, could you include TIO links (see other answers) with an example input/output? It's not cheating to include a package, but library(magrittr) needs to be included in the byte counts.
JayCe

Also as per consensus submissions need to be full functions or programs, not snippets, so if you go with a function whose sole argument is xyour answer starts with function(x) and then the body of the function.
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...)]

Try it online!

Inspired by @DeadPossum's Python solution.

Takes input as a matrix, where each row has two dates: the starting and ending dates of an input range. Assumes the input has the earliest date first, and that each row has the starting date first, but assumes no sorting beyond that between different rows.


Older solution:

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

Try it online!

Accepts input as an array of date ranges. Does not assume any sorting among the different ranges in the array.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.