Порахуйте часові плани


17

Натхненний сценарієм реального життя, на який я попросив відповідь тут: /superuser/1312212/writing-a-formula-to-count-how-many-times-each-date- з'являється в наборі дату-запущена

Враховуючи масив часових просторів (або пари startdate-enddate), виведіть підрахунок, скільки часових просторів охоплює кожен день, за всі дні в загальному діапазоні.

Наприклад:

  #      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

З огляду на вищезазначені дані, результати мають бути такими:

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)

Вам потрібно лише вивести підрахунки за кожен день (по порядку, відсортовано найстаріше-новітнє); не в яких записах вони з’являються.

Ви можете припустити, що кожен проміжок часу містить лише дати, а не часи; і так цілі дні завжди представлені.

I / O

Введенням може бути будь-який формат, який представляє набір часових просторів - тобто або набір пар разів, або набір (вбудованих) об'єктів, що містять дати початку та закінчення. Час проведення дат обмежується між 1901 та 2099 роками, як це нормально для проблем, пов'язаних з ППГ.

Ви можете припустити, що вхід попередньо відсортовано, як вам подобається (вкажіть у своїй відповіді). Дати введення включені (тому діапазон включає всю дату початку та кінця).

Ви також можете припустити, що з двох дат у будь-якому даному діапазоні перша буде старшою або дорівнює другій (тобто у вас не буде негативного діапазону дат).

Вихід - це масив, що містить кількість за кожен день, від найдавнішого до найновішого вхідного даних, відсортованого за датою початку.

Отже, вихід для вищевказаного прикладу був би {3,2,2,0,1}

Можливо, що деякі дні не включаються в будь-який часовий діапазон, і в цьому випадку 0виводяться на цю дату.

Критерії виграшу

Це код-гольф, тому виграє найнижчий байт. Застосовуються звичайні виключення

Приклад псевдоалгоритму

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

Інші алгоритми, щоб дійти до того ж результату, чудово.


3
Чи потрібен масив цілих чисел, чи нам дозволено повернути щось інше, скажімо словник з ключами як кожної дати? Якщо нам дозволено повертати словник, то чи можемо ми пропустити дати, які відсутні в жодному із часових просторів?
JungHwan Мін

1
чи можемо ми сприймати дані як два списки, один із датами початку та інший із відповідними датами закінчення?
Джузеппе

Так, все це добре, крім пропущення дати - я прямо заявляю, що в такому випадку слід вивести 0
simonalexander2005

3
Чи можу я запитати, чому 0має бути в словнику? Він з'являється тільки , щоб змусити користувача ітерованих від min(input)до max(input), який , здається, не додає нічого до ядру завдання (обчислювальні timespans).
JungHwan Min

2
@JungHwanMin Я думаю, це не змінює його; але тому що я явно мав це у специфікації, коли я розміщував це, я не хочу йти з цим возитися і змушувати когось ще повторити свою відповідь
simonalexander2005

Відповіді:


3

APL (Dyalog Unicode) , 32 байти SBCS

Повна програма. Запрошує stdin для переліку пар Міжнародних номерів дат (наприклад, які використовують Excel та MATLAB). І список, і пари можуть бути задані в будь-якому порядку, наприклад (Кінець, Старт). Друкує список відліків, які потрібно відкласти.

¯1+⊢∘≢⌸(R,⊢)∊(R←⌊/,⌊/+∘⍳⌈/-⌊/)¨⎕Спробуйте в Інтернеті!

Якщо це недійсно, список пар (YMD) можна перетворити на додаткові 21 байт, що становить 53:

¯1+⊢∘≢⌸(R,⊢)∊(R⌊/,⌊/+∘⍳⌈/-⌊/)¨{2⎕NQ#'DateToIDN'⍵}¨¨⎕Спробуйте в Інтернеті!


 швидка консоль для оцінюваного вводу

( Застосувати наступну негласну функцію до кожної пари

⌊/ мінімальний (літ. хв. зменшення), тобто дата початку

⌈/- максимальний (тобто кінцева дата) мінус це

⌊/+∘⍳ дата початку плюс діапазон від 1 до кінця

⌊/, дата початку була передчутною для цього

R← призначити цю функцію R(для R ange)

ϵ nlist (вирівнювати) список діапазонів в єдиний список

() Застосувати до цього таку негласну функцію:

R,⊢ результат застосування R(тобто діапазон дат) з подальшим аргументом
  (це гарантує, що кожна дата в діапазоні представлена ​​хоча б один раз і дати відображаються в упорядкованому порядку)

 Для кожної пари унікальних (дата, її показники появи на вводі) виконайте:

⊢∘≢ ігнорувати фактичну дату на користь підрахунку індексів

¯1+ додати -1 до цих толстовок (тому що ми попереджали одну кожну дату в діапазоні)


9

JavaScript (ES6), 85 байт

Вводиться в якості списку Dateпар. Очікує, що список буде відсортований за датою початку. Повертає масив цілих чисел.

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

Спробуйте в Інтернеті!

або 84 байти, якщо ми можемо взяти часові позначки JS як вхідні дані (як це запропонував @Shaggy)



Збережіть байт, взявши за вхідні значення примітивні значення: TIO
Shaggy

7

JavaScript, 75 73 байт

Приймає вхід як відсортований масив масивів примітивних пар дат, виводить об'єкт, де ключі - примітиви кожної дати, а значення діапазонів цих дат у діапазонах.

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

Спробуй це


Я працював над цією 60-байтною версією, поки не було підтверджено, що дати, які не відображаються в жодному з діапазонів, повинні бути включені, тому поспішно оновив її до рішення вище.

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

Спробуйте в Інтернеті (або з людськими читаними датами у висновку )


Схоже, ES6 визначає порядок ключів для JS-об'єктів ( stackoverflow.com/a/31102605/8127 ), в основному порядок вставки для рядкових та символьних клавіш (а Nodejs TIO, схоже, слідує тому: tinyurl.com/ybjqtd89 ). І взагалі моя думка полягає в тому, що детальна інформація про реалізацію (яка тут є об'єктом) не повинна диктувати тлумачення правил виклику, але я зачекаю на пост Meta.
sundar

6

Октава , 63 байти

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

Спробуйте в Інтернеті!

Тепер це було некрасиво!

Пояснення:

Приймає дані як масив datenumелементів комірки (тобто рядок, "2001-01-01"перетворений на числове значення, виглядаючи так:

{[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()функція datenum. Потім ми використовуємоcellfun для створення комірок з діапазонами від першого стовпця до другого для кожного з цих рядків. Ми поєднуємо ці діапазони по горизонталі, щоб у нас був довгий горизонтальний вектор з усіма датами.

Потім ми створюємо гістограму, використовуючи histcці значення, з проміжками, заданими діапазоном між найнижчою та найвищою датою.


5

R , 75 байт

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

Спробуйте в Інтернеті!

Вхід - це матриця, перший стовпець - "Пуск", а другий - "Кінець". Передбачає Початок <= Кінець, але не вимагає сортування дати початку.


Це настільки, наскільки мені вдалося спробувати повторити відповідь Октави Стіві Гріффін ... що я роблю неправильно?
JayCe

це через те, як R робить свої бункери hist; ви могли б зробити c(-25668,min(x):max(x))так, як -25568це раніше, 1900але це закінчується довше, ніж запропонована відповідь. Як сказано, є кращий спосіб генерувати дати, ніж apply; У мене є один, який має 68 байт, і я просто не знайшов часу, щоб сам його розмістити.
Джузеппе

А, ні, насправді, використовуйте, (min(x)-1):max(x)і це має працювати так, як очікувалося; то якщо ви не можете знайти applyдати генерувати дати, ви можете отримати це до 63 байт і прив’язати відповідь Октави.
Джузеппе

@Giuseppe Ви повинні опублікувати це як окрему відповідь :)
JayCe

Опубліковано :-) Я мушу визнати, я використовував tableі factorдо цього було моїм оригінальним використанням Map68 байт, але histце акуратний підхід, про який я завжди забуваю, напевно, тому що це дратує, щоб отримати кошти правильно (як ми бачили )
Джузеппе

4

Червоний , 174 байти

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

Досить довга і буквальна реалізація.

Спробуйте в Інтернеті!

Читає:

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 байти

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

Сігналы абмеркавання

Відформатовано:

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

Пітон 2 , 114 87 93 байт

-27 байт завдяки Джонатану Аллану
+6 байт завдяки sundar

Приймає введення як список пар об'єктів datetime.
Припускається, що перша пара починається з найнижчої дати.

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)

Спробуйте в Інтернеті!


daysє аргументом за замовчуванням для timedelta.
Джонатан Аллан

... насправді я думаю , що ви можете відкинути from datetime import*і замінити d+=timedelta(days=1)з , d+=type(d-d)(1)так як входи вже dateс. 87 байт
Джонатан Аллан

1
Це, мабуть, припускає, що початок першого діапазону є найнижчою датою, а кінець останнього діапазону найвищим - але я думаю, що іноді це неможливо, навіть якщо ОП дозволяє нам брати впорядковані дані. Наприклад, наприклад. якщо введення є [(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]. Якщо OP не дозволяє нам розділити і переставити ці діапазони під час попередньої обробки (що здається малоймовірним), цей вхід не може бути оброблений цим кодом належним чином.
sundar

@sundar Так, я бачу, про що ти говориш. Я оновив рішення для вирішення цього питання. Спасибі!
Мертвий Поссум

3

Мова Вольфрама (Mathematica) , 62 байти

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

Спробуйте в Інтернеті!

+35 байт, оскільки ОП це вказало 0 повинні бути включені у висновок.

Якщо пропускати запис у словнику було дозволено, 27 байт

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

Спробуйте в Інтернеті!

Вбудований DayRangeприймає два DateObjects (або еквівалент рядка) і виводить список Datesміж цими датами (включно).


3

R , 65 63 байти

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

Спробуйте в Інтернеті!

Це співпраця між JayCe і мною, передаючи відповідь Стюа Гріффін Р.

Щоб цитувати JayCe:

Вхід - це матриця, перший стовпець - "Пуск", а другий - "Кінець". Передбачає Початок <= Кінець, але не вимагає сортування дати початку.

Можливо, $cце непотрібно, але це не зовсім в дусі виклику, тому я включив його.


1
Min (x-1) на 2 байти?
JayCe

^ Під чим я маю на увазі це
JayCe

@JayCe так, приємно! Я мав намір повернутися до цього раніше, але забув.
Джузеппе

3

Powershell, 122 121 118 113 байт

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

збережіть як count-timespan.ps1. Тестовий сценарій:

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

Пояснення

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)

Спасибі! $cnt.Keys.Dateзвичайно.
mazzy

-3 байти: functionзамінено на scriptblock. перевіряються коди для гольфу та безгольф.
маззи

-5 байт: scriptblockзамінено на filter. Виклик a filterбільш компактний.
маззи

3

J, 43 байти

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

вхід - це список пар цілих чисел, де кожне ціле число є зміщенням від будь-якого довільного загального 0-денного.

неозорий

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

пояснення

структура:

(A)&:(B) C
  • C створює гачок, який дає головному дієслову A&:Bвведення зліва, а введення сплющено праворуч
  • B aka ((>./ (] + i.@>:@-) <./)"1)приймає min і max списку і повертає отриманий діапазон, і діє з ранг 1. Отже, він дає загальний діапазон справа, а окремі діапазони зліва.
  • Тоді використовується =з рангом "0 _(тобто ранг {), щоб підрахувати, скільки разів кожен вхід з'являється в будь-якому діапазоні. нарешті, вона щороку замикається з цими підрахунками.

Спробуйте в Інтернеті!


2

JavaScript (Node.js) , 80 байт

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

Спробуйте в Інтернеті!

undefinedозначає нуль; Перший елемент повинен починатися якомога раніше

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u коротше, якщо ви бачите лише елементи та використовуєте більше стеку


6
Вам слід попросити підтвердження того, що заміщення іншого значення на 0прийнятне.
Кудлатий


1

R (70)

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

Передбачає кадр даних xз двома стовпцями ( Startі, Endможливо, Sі E) з датами (класом Date).

Спробуйте в Інтернеті


Привіт, ви могли б включити посилання TIO (див. Інші відповіді) із прикладом введення / виводу? Включати пакет не обман, але library(magrittr)його потрібно включати в число байтів.
JayCe

Крім того, згідно з консенсусом, подані документи повинні бути повноцінними функціями чи програмами, а не фрагментами, тож якщо ви переходите до функції, єдиним аргументом якої є xваша відповідь, function(x)а потім тіло функції.
JayCe

1

Джулія 0,6 , 77 байт

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

Спробуйте в Інтернеті!

Натхненний @ DeadPossum's Python .

Вводить введення як матрицю, де кожен рядок має дві дати: дати початку та кінця діапазону введення. Припустимо, що вхід має спочатку найдавнішу дату, і що кожен рядок має першу дату початку, але не передбачає сортування, що не перевищує значення між різними рядками.


Старіше рішення:

Джулія 0,6 , 124 байти

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

Спробуйте в Інтернеті!

Приймає введення як масив діапазонів дат. Не передбачає сортування серед різних діапазонів масиву.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.