Знайдіть перетин двох наборів у об'єднаних інтервальних позначеннях


10

Знайдіть перетин двох наборів у об'єднаних інтервальних позначеннях

Давши два набори реальних чисел, описаних як об'єднання інтервалів, виведіть опис перетину цих двох множин як об'єднання одного і того ж типу інтервалу.

Набори входів завжди будуть складатися з об'єднань інтервалів, так що кожен інтервал починається і закінчується з різним цілим числом (тобто жоден інтервал не має міри нуля). Однак різні інтервали в одному і тому ж наборі можуть починатися або закінчуватися одним і тим же цілим чи перекриттям.

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

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

Наприклад, ви можете представити набір рівнянняяк:

[-10,-4]u[1,5]u[19,20]

Або як:

[[-10,-4],[1,5],[19,20]]

Або як:

[-10,-4;1,5;19,20]

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

Приклади / Тестові приклади:

Вхід:

[[[-90,-4],[4,90]],[[-50,50]]]

Вихід:

[[-50,-4],[4,50]]

Іншими словами, ми перетинаємо множину, яка містить усі дійсні числа від -90 до -4 і всі дійсні числа між 4 і 90, з набором, який містить усі дійсні числа від -50 до 50. Перетин - це множина, що містить усі реальні числа від -50 до -4 і всі дійсні числа між 4 і 50. Більш наочне пояснення:

-90~~~~~-4  4~~~~~90   intersected with
    -50~~~~~~~~50        yields:
    -50~-4  4~~50

Вхід:

"[-2,0]u[2,4]u[6,8]
[-1,1]u[3,5]u[5,9]"

Вихід:

"[-1,0]u[3,4]u[6,8]"

Вхід:

[-9,-8;-8,0;-7,-6;-5,-4]
[-7,-5;-1,0;-8,-1]

Вихід:

[-8,0]

Недійсний вихід (навіть якщо він представляє той самий набір):

[-8,0;-7,-5;-5,0]

Оцінка:

Це тому найкоротше джерело в байтах виграє, як потенційно модифіковане наступним бонусом.

Бонус:

-15%, якщо ви також підтримуєте позитивну та негативну нескінченність як межі інтервалів. Ви можете вибрати, які маркери представляють ці числа. (І так, нескінченність - це число у гіперреалах; P)


Чи можемо ми припустити, що різні об'єднані множини у кожній збитках перетину записуються у порядку збільшення? Іншими словами (але навпаки), чи дійсний наступний вхід? [[[4,90],[-90,-4]],[[-50,50]]]
msh210

2
@ msh210 третій приклад повинен відповісти на це запитання. (Ні. Сортуйте їх самі.)
Кінтопія

@nimi ти маєш рацію. виправлено
Кінтопія

Відповіді:


3

Математика, 41 байт - 15% = 34,85

Mathematica має вбудовану функцію для інтервального перетину.

List@@IntervalIntersection@@Interval@@@#&

Приклад:

In[1]:= List@@IntervalIntersection@@Interval@@@#&[{{{-90, -4}, {4, Infinity}}, {{-50,Infinity}}}]

Out[1]= {{-50, -4}, {4, Infinity}}

2
Нічого собі ... Я просто придумав таке саме рішення, не читаючи цього. +1
LegionMammal978

Треба любити автоматичне об'єднання Mathematica Interval.
mbomb007

3

Haskell, 145 байт

import Data.List
q(a,b)=[a,a+0.5..b]
p@(a,b)%(h:t)|h==b+0.5=(a,h)%t|1<2=p:(h,h)%t
p%_=[p]
a#b|h:t<-nub$sort$intersect(q=<<a)$q=<<b=(h,h)%t|1<2=[]

Приклад використання: [(-2.0,0.0),(2.0,4.0),(5.0,6.0),(6.0,8.0)] # [(-1.0,1.0),(3.0,5.0),(5.0,9.0)]-> [(-1.0,0.0),(3.0,4.0),(5.0,8.0)].

Як це працює:

                 q=<<a            -- turn each pair in the 1st input list into
                                  -- lists with halves in between (e.g. (1,4) ->
                                  -- [1,1.5,2,2.5,3,3.5,4]) and concatenate them
                                  -- to a single list
                      q=<<b       -- same for the second input list
    nub$sort$intersect            -- sort the intersection of those lists
                                  -- and remove duplicates
h:t<-                             -- call the first element h and the rest t
                       (h,h)%t    -- start rebuilding the intervals
                          |1<2=[] -- if there's no first element h, one of the
                                  -- input lists is empty, so the output is also
                                  -- empty


p@(a,b)%(h:t)                     -- an interval p = (a,b), build from a list (h:t)
             =(a,h)%t             -- becomes (a,h)
      |h==b+1                     --   if h equals b+0.5
                    p:(h,h)%t     -- or is put in the output list, followed by
                                  --       a new interval starting with (h,h)
      |1<2                        --   otherwise
p%_=[p]                           -- base case of the interval rebuilding function 

Я ставлю «половинку»-значення x.5в списку, тому що мені потрібно відрізняти (1,2),(3,4)від (1,4). Без того x.5обидва стали б [1,2,3,4], але з x.51-м стає [1,1.5,2,3,3.5,4](чого не вистачає 2.5) і з другим [1,1.5,2,2.5,3,3.5,4].


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

@quintopia: так, дякую.
nimi

2

Рубін, 90 байт

Мапи кожного з двох наборів на плоский масив, отримує перетин набору цих масивів, а потім розрізає результат на шматки континуалу і відображає кожен фрагмент в перший і останній елемент. Простенька.

->s{a,b=s.map{|y|y.flat_map{|f,l|[*f..l]}.sort}
(a&b).slice_when{|a,b|b-a>1}.map &:minmax}

Використання:

f=->s{a,b=s.map{|y|y.flat_map{|f,l|[*f..l]}.sort}
(a&b).slice_when{|a,b|b-a>1}.map &:minmax}

s = [[[-90,-4],[4,90]], [[-50,50]]]
p f[s] # => [[-50, -4], [4, 50]]

s = [[[-2,0],[2,4],[6,8]], [[-1,1],[3,5],[5,9]]]
p f[s] # => [[-1, 0], [3, 4], [6, 8]]

s = [[[-9,-8],[-8,0],[-7,-6],[-5,-4]],[[-7,-5],[-1,0],[-8,-1]]]
p f[s] # => [[-8, 0]]

Для чого виводиться ваша програма s = [[[1,2],[3,4]], [[1,2],[3,4]]]? (У моїй рубіновій версії немає slice_when, тому я не можу перевірити себе)
nimi

@mimi це дає [[1, 4]]. slice_whenМетод був доданий де - то близько 2,2 Рубіна я думаю.
daniero

... але це повинно бути [[1,2], [3,4]]
німі

Набори є над реальними числами, лише межі інтервалу є цілими числами, тому 2.2не на вході s = [[[1,2],[3,4]], [[1,2],[3,4]]], а на вашому виході [[1, 4]].
німі

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