Hitung rentang waktu

17

Terinspirasi oleh skenario kehidupan nyata, yang saya minta jawabannya di sini: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- muncul-dalam-a-set-of-date-ran

Diberikan array rentang waktu (atau pasangan mulai-akhir-tanggal), menghasilkan hitungan berapa banyak rentang waktu setiap hari, untuk semua hari dalam rentang total.

Sebagai contoh:

  #      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

Mengingat data di atas, hasilnya harus sebagai berikut:

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)

Anda hanya perlu menampilkan hitungan untuk setiap hari (agar, diurutkan terlama-terbaru); bukan catatan mana mereka muncul.

Anda dapat mengasumsikan bahwa setiap rentang waktu hanya berisi tanggal, bukan waktu; dan sepanjang hari selalu terwakili.

I / O

Input dapat berupa format apa pun yang mewakili sekumpulan rentang waktu - jadi sekumpulan pasangan waktu, atau kumpulan objek (bawaan) yang berisi tanggal mulai dan berakhir. Tanggal-waktu dibatasi antara 1901 dan 2099, seperti biasa untuk tantangan PPCG.

Anda dapat berasumsi bahwa input sudah disortir sesuka Anda (sebutkan dalam jawaban Anda). Tanggal input termasuk (sehingga rentang mencakup seluruh tanggal mulai dan berakhir).

Anda juga dapat mengasumsikan bahwa, dari dua tanggal dalam rentang tertentu, yang pertama akan lebih tua atau sama dengan yang kedua (yaitu Anda tidak akan memiliki rentang tanggal negatif).

Keluaran adalah larik yang berisi hitungan untuk setiap hari, dari yang terlama hingga yang terbaru dalam input saat diurutkan berdasarkan Tanggal Mulai.

Jadi, output untuk contoh di atas akan menjadi {3,2,2,0,1}

Mungkin saja beberapa hari tidak termasuk dalam rentang waktu apa pun, dalam hal ini 0 ini output untuk tanggal tersebut.

Kriteria Menang

Ini adalah kode-golf, sehingga byte terendah menang. Pengecualian biasa berlaku

Contoh algoritma palsu

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

Algoritme lain untuk mendapatkan hasil yang sama baik-baik saja.

simonalexander2005
sumber
3
Apakah diperlukan array bilangan bulat, atau apakah kami boleh mengembalikan yang lain, misalnya kamus dengan kunci setiap tanggal? Jika kami diizinkan mengembalikan kamus, dapatkah kami menghilangkan tanggal yang tidak ada dalam rentang waktu?
JungHwan Min
1
dapatkah kita mengambil input sebagai dua daftar, satu dengan tanggal mulai dan yang lainnya dengan tanggal akhir yang sesuai?
Giuseppe
Ya, semua itu baik-baik saja, kecuali menghilangkan tanggal - saya secara eksplisit mengatakan bahwa 0 harus menjadi output dalam kasus itu
simonalexander2005
3
Bolehkah saya bertanya mengapa 0harus di kamus? Tampaknya hanya memaksa pengguna untuk beralih dari min(input)ke max(input), yang tampaknya tidak menambahkan apa pun ke inti tantangan (menghitung rentang waktu).
JungHwan Min
2
@JungHwanMin Saya kira itu tidak mengubahnya; tetapi karena saya secara eksplisit memilikinya di spec ketika saya mempostingnya, saya tidak ingin mengacaukannya dan membuat orang lain mengulangi jawaban mereka
simonalexander2005

Jawaban:

3

APL (Dyalog Unicode) , 32 byte SBCS

Program lengkap. Anjurkan stdin untuk daftar pasangan Nomor Tanggal Internasional (seperti apa yang digunakan Excel dan MATLAB). Daftar dan pasangan dapat diberikan dalam urutan apa pun, misalnya (Akhir, Mulai). Mencetak daftar hitungan ke stdout.

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

Jika ini tidak valid, daftar pasangan (YMD) dapat dikonversi untuk 21 byte tambahan, dengan total 53:

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


 konsol yang cepat untuk input yang dievaluasi

(...  terapkan fungsi diam-diam berikut untuk setiap pasangan

⌊/ minimum (lit-mnt reduksi), yaitu tanggal mulai

⌈/- maksimum (yaitu tanggal akhir) dikurangi itu

⌊/+∘⍳ tanggal mulai plus rentang 1-hingga-itu

⌊/, tanggal mulai diawali dengan itu

R← menetapkan fungsi ini untuk R(untuk R ange)

ϵ daftar (ratakan) daftar rentang menjadi satu daftar

(... ) terapkan fungsi tersembunyi berikut untuk itu:

R,⊢ hasil penerapan R(yaitu rentang tanggal) diikuti oleh argumen
   (ini memastikan bahwa setiap tanggal dalam kisaran diwakili setidaknya satu kali, dan bahwa tanggal muncul dalam urutan yang diurutkan)

...  untuk setiap pasangan unik (tanggal, indeks kemunculannya dalam input), lakukan:

⊢∘≢ abaikan tanggal aktual demi penghitungan indeks

¯1+ tambahkan -1 ke penghitungan tersebut (karena kami menambahkan satu dari setiap tanggal dalam rentang)

Adm
sumber
9

JavaScript (ES6), 85 byte

Mengambil input sebagai daftar Datepasangan. Diharapkan daftar akan diurutkan berdasarkan tanggal mulai. Mengembalikan array bilangan bulat.

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

Cobalah online!

atau 84 byte jika kita dapat mengambil cap waktu JS sebagai input (seperti yang disarankan oleh @Shaggy)

Arnauld
sumber
Ah, gila!
Shaggy
Simpan satu byte dengan mengambil nilai-nilai primitif sebagai input: TIO
Shaggy
7

JavaScript, 75 73 byte

Mengambil input sebagai array array yang diurutkan dari pasangan primitif tanggal, mengeluarkan objek di mana kuncinya adalah primitif dari setiap tanggal dan nilai penghitungan tanggal tersebut dalam rentang.

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

Cobalah


Saya sedang mengerjakan versi 60 byte ini hingga dipastikan bahwa tanggal yang tidak muncul di rentang mana pun harus dimasukkan sehingga dengan tergesa-gesa memperbaruinya ke solusi di atas.

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

Coba online (atau dengan tanggal yang dapat dibaca manusia di output )

Shaggy
sumber
Sepertinya ES6 tidak menentukan urutan kunci untuk objek JS ( stackoverflow.com/a/31102605/8127 ), pada dasarnya urutan penyisipan untuk kunci string dan simbol (dan Tode Nodejs tampaknya mengikuti hal itu: tinyurl.com/ybjqtd89 ). Dan secara umum pendapat saya adalah bahwa detail implementasi (yang merupakan objek di sini) tidak boleh mendikte interpretasi aturan tantangan, tetapi saya akan menunggu posting Meta.
sundar - Reinstate Monica
6

Oktaf , 63 byte

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

Cobalah online!

Nah, itu jelek!

Penjelasan:

Mengambil input sebagai array datenumelemen sel (yaitu string yang "2001-01-01"dikonversi ke nilai numerik, terlihat seperti ini:

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

dimana d()fungsinya datenum. Kami kemudian gunakan cellfununtuk membuat sel dengan rentang dari kolom pertama ke yang kedua untuk setiap baris tersebut. Kami menggabungkan rentang ini secara horizontal, sehingga kami memiliki vektor horizontal panjang dengan semua tanggal.

Kami kemudian membuat histogram menggunakan histcnilai-nilai ini, dengan nampan yang diberikan oleh rentang antara tanggal terendah dan tertinggi.

Stewie Griffin
sumber
5

R , 75 byte

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

Cobalah online!

Input adalah matriks yang kolom pertama adalah Mulai dan kolom kedua adalah Akhir. Asumsikan Mulai <= Akhir tetapi tidak memerlukan tanggal Mulai untuk diurutkan.

JayCe
sumber
Ini adalah sejauh yang saya bisa pergi mencoba untuk meniru jawaban Oktaf oleh Stewie Griffin ... apa yang saya lakukan salah?
JayCe
itu karena cara R memasukkan sampahnya hist; Anda dapat melakukannya c(-25668,min(x):max(x))sejak -25568sebelum 1900tetapi ini berakhir lebih lama dari jawaban yang Anda sarankan. Yang sedang berkata, ada cara yang lebih baik untuk menghasilkan tanggal daripada apply; Saya punya satu yang di 68 byte dan saya belum menemukan waktu untuk mempostingnya sendiri.
Giuseppe
Ah, tidak, sebenarnya, gunakan (min(x)-1):max(x)dan seharusnya berfungsi seperti yang diharapkan; maka jika Anda dapat menemukan applycara untuk menghasilkan tanggal Anda bisa mendapatkan ini hingga 63 byte dan mengikat jawaban Oktaf.
Giuseppe
@Giuseppe Anda harus mempostingnya sebagai jawaban terpisah :)
JayCe
diposting :-) Saya harus mengakui, saya menggunakan tabledan factorsebelumnya yang merupakan penggunaan asli saya Mapuntuk 68 byte, tetapi histmerupakan pendekatan yang rapi yang saya selalu lupa, mungkin karena itu mengganggu untuk mendapatkan tempat sampah tepat (seperti yang telah kita lihat )
Giuseppe
4

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

Implementasi yang cukup lama dan literal.

Cobalah online!

Dapat dibaca:

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

Diformat:

 {                                   // 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.
    }
}
Guci Gurita Ajaib
sumber
4

Python 2 , 114 87 93 byte

-27 byte terima kasih kepada Jonathan Allan
+6 bytes berkat sundar

Mengambil input sebagai daftar pasangan objek datetime.
Mengasumsikan bahwa pasangan pertama dimulai dengan tanggal terendah.

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)

Cobalah online!

Possum Mati
sumber
daysadalah argumen default untuk timedelta.
Jonathan Allan
... sebenarnya saya pikir Anda dapat drop from datetime import*dan ganti d+=timedelta(days=1)dengan d+=type(d-d)(1)karena input sudah dates. 87 byte
Jonathan Allan
1
Ini tampaknya mengasumsikan bahwa awal rentang pertama adalah tanggal terendah DAN akhir rentang terakhir adalah yang tertinggi - tetapi saya pikir itu kadang-kadang tidak mungkin bahkan jika OP memungkinkan kita untuk mengambil input yang disortir. Untuk misalnya. jika input [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. Kecuali OP memungkinkan kami untuk membagi dan mengatur ulang rentang ini selama preprocessing (yang tampaknya tidak mungkin), input ini tidak dapat diproses oleh kode ini dengan benar.
sundar - Reinstate Monica
@sundar Ya, saya mengerti apa yang Anda bicarakan. Saya telah memperbarui solusi untuk menangani ini. Terima kasih!
Mati Possum
3

Bahasa Wolfram (Mathematica) , 62 byte

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

Cobalah online!

+35 byte karena OP ditentukan yang 0harus dimasukkan dalam output.

Jika menghilangkan entri dalam kamus diizinkan, 27 byte

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

Cobalah online!

Built-in DayRangemenerima dua DateObjects (atau string yang setara) dan menampilkan daftar Datesantara tanggal tersebut (termasuk).

JungHwan Min
sumber
3

R , 65 63 byte

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

Cobalah online!

Ini adalah kolaborasi antara JayCe dan saya, mengirim jawaban Stewie Griffin ke R.

Mengutip JayCe:

Input adalah matriks yang kolom pertama adalah Mulai dan kolom kedua adalah Akhir. Asumsikan Mulai <= Akhir tetapi tidak memerlukan tanggal Mulai untuk diurutkan.

Mungkin, $ctidak perlu tetapi tidak dalam semangat tantangan jadi saya sudah memasukkannya.

Giuseppe
sumber
1
Min (x-1) selama 2 byte?
JayCe
^ Maksud saya ini
JayCe
@JayCe ya, bagus! Saya bermaksud untuk kembali ke hal ini sebelumnya tetapi saya lupa.
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.$_}

simpan sebagai count-timespan.ps1. Skrip uji:

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

Penjelasan

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
sumber
Terima kasih! $cnt.Keys.Datetentu saja.
mazzy
-3 byte: functiondiganti dengan scriptblock. kode golf dan ungolfed diuji.
mazzy
-5 byte: scriptblockdiganti aktif filter. Panggilan seorang filterlebih kompak.
mazzy
3

J, 43 byte

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

input adalah daftar pasangan bilangan bulat, di mana masing-masing bilangan bulat adalah offset dari sembarang 0 hari umum.

ungolfed

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

penjelasan

struktur adalah:

(A)&:(B) C
  • C membuat hook yang memberikan kata kerja utama A&:Binput di sebelah kiri dan input diratakan di sebelah kanan
  • B alias ((>./ (] + i.@>:@-) <./)"1)mengambil min dan maks dari daftar dan mengembalikan rentang yang dihasilkan, dan bertindak dengan peringkat 1. karenanya memberikan kisaran total di sebelah kanan, dan rentang individu di sebelah kiri.
  • A kemudian menggunakan =dengan peringkat"0 _ (yaitu, peringkat {) untuk menghitung berapa kali setiap input muncul di salah satu rentang. akhirnya ritsleting setiap tahun dengan jumlah tersebut.

Cobalah online!

Jonah
sumber
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

Cobalah online!

undefinedberarti nol; Elemen pertama harus dimulai paling awal

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u lebih pendek jika Anda hanya melihat elemen dan menggunakan lebih banyak tumpukan

l4m2
sumber
6
Anda harus meminta konfirmasi bahwa mengganti nilai lain dengan 0dapat diterima.
Shaggy
1

Ruby , 70 byte

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

Cobalah online!

Memasukkan:

Array pasang tanggal, disortir berdasarkan tanggal berakhir turun.

GB
sumber
1

R (70)

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

Menganggap frame data xdengan dua kolom ( Startdan Endatau mungkin Sdan E) dengan tanggal (kelas Date).

Cobalah online

lebatsnok
sumber
Hai, dapatkah Anda menyertakan tautan TIO (lihat jawaban lain) dengan contoh input / output? Itu tidak curang untuk memasukkan paket, tetapi library(magrittr)perlu dimasukkan dalam jumlah byte.
JayCe
Sesuai dengan konsensus, pengajuan harus berupa fungsi atau program lengkap, bukan cuplikan, jadi jika Anda menggunakan fungsi yang satu-satunya argumen adalah xjawaban Anda dimulai dengan function(x)dan kemudian badan fungsi.
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...)]

Cobalah online!

Terinspirasi oleh @ DeadPossum's solusi Python .

Mengambil input sebagai matriks, di mana setiap baris memiliki dua tanggal: tanggal awal dan akhir dari rentang input. Mengasumsikan input memiliki tanggal paling awal terlebih dahulu, dan bahwa setiap baris memiliki tanggal mulai pertama, tetapi mengasumsikan tidak ada penyortiran di luar itu antara baris yang berbeda.


Solusi yang lebih lama:

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

Cobalah online!

Menerima input sebagai larik rentang tanggal. Tidak menganggap pengurutan di antara berbagai rentang dalam array.

sundar - Pasang kembali Monica
sumber