Прямокутна різниця


20

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

Наприклад, якщо ви вилучите червоний прямокутник із чорного:

прямокутники

Ви закінчите один із наступних двох наборів прямокутників:

спліт-один розділ-два

Вам також потрібно буде обробити таке:

Усі тестові справи

Щоб бути більш чітким:

  • Ви введете координати двох прямокутників, A і B.
  • Вам потрібно вивести найменші прямокутники, що не перекриваються, які охоплюють всю площу А без В. Дозволено будь-яке можливе покриття
  • Прямокутні координати передаються у вигляді 4 цілих чисел. Ви можете передати їх двома парами (представляючи дві кутові точки), або як кортеж / список із 4 цілих чисел. Ваші входи та результати повинні бути послідовними.
  • A і B не обов'язково перетинатимуться або торкатися, і кожен матиме площу щонайменше 1

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

[(0 0) (5 5)] [(3 4) (8 7)]   -> [(0 0) (5 4)] [(0 4) (3 5)] # or [(0 0) (3 5)] [(3 0) (5 4)]
[(2 4) (10 11)] [(5 5) (6 6)]  -> [(2 4) (10 5)] [(2 5) (5 6)] [(6 5) (10 6)] [(2 6) (10 11)]    #Other sets of 4 rectangles are possible
[(3 3) (8 8)] [(0 1) (10 8)]   ->    #No rectangles should be output
[(0 0) (5 5)] [(1 1) (10 2)]   -> [(0 0) (1 5)] [(1 0) (2 1)] [(2 0) (5 5)]  #Other sets of 3 rectangles are possible
[(1 5) (7 8)] [(0 0) (1 10)]   -> [(1 5) (7 8)]  #Only possible output
[(4 1) (10 9)] [(2 5) (20 7)]   -> [(4 1) (10 5)] [(4 7) (10 9)]  #Only possible output
[(1 1) (8 8)] [(0 6) (9 9)]     -> [(1 1) (8 6)]   #Only possible output

Це , тому зробіть свій код якомога коротшим!



1
чи можна вважати, що даний вхід {(x1, y1), (x2, y2)}справедливий x1 < x2і y1 < y2?
tsh

Так. Прямокутник матиме площу 1, і ви можете замовити координати в будь-якому бажаному вам порядку.
Натан Меррілл

Край товстий? Коли визначено прямокутник, включений край?
Евгеній Новиков

Край має 0 товщини.
Натан Меррілл

Відповіді:


3

Python 2 , 375 360 345 343 байт

from itertools import*;P=product
def f(S,M):(l,t),(r,b)=S;(L,T),(R,B)=M;u,v,x,y=(L>=r)+(l<L),(T>=b)+(t<T),(R>=r)+(l<R),(B>=b)+(t<B);return[S]if v==y!=1or u==x!=1else[list(p(p(*zip(*(S+M))),repeat=2))[[43,197,6,199,9,231,142,229,53,189,134,181][int(i,36)]]for i in '38,491,258,2058,8,4B,28,208,7,41,27,461,,4,2,4A'.split(',')[u+2*v+4*x+8*y-12]]

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

ЗМІНИ: -15 з пропозицій від @notjagan; ще -15 шляхом перекодування масиву прямокутників рішення у формат int36 та коротку таблицю пошуку; ще -2, замінивши продукт на p відповідно до @musicman.

Функція, яка займає два прямокутника, кожен прямий - кортеж ((лівий, верхній), (правий, нижній)); повертає список отриманих прямокутників.

Основна стратегія:

     |     |
 0,0 | 1,0 | 2,0
-----A-----+-----
     |     |
 0,1 | 1,1 | 2,1
-----+-----B-----
     |     |
 0,2 | 1,2 | 2,2
     |     |

На наведеній діаграмі точки A і B - верхній лівий і нижній правий прямокутник прямокутника (перша пряма).

Ми знаходимо розміщення кожного верхнього лівого (u,v)та нижнього правого (x,y)кута прямокутника «Маска» у цій сітці.

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

Інакше залишилось 16 справ; наприклад, перший приклад ОП - це той випадок, який ми можемо позначити (1,1),(2,2). Кожен випадок може бути відображений у набір отриманих прямокутників, у кутах яких завжди є координати з горизонтальними значеннями або в прямокутниках з джерела, ліворуч, праворуч, або прямокутники Маски зліва, справа; і аналогічно для вертикальних значень, верхнього, нижнього або маски Джерела.

Наприклад, для (1,1),(2,2)випадку прямокутники були б ((l,t),(T,r))і ((l,T),(R,b)), де l,t,r,bі L,T,R,B- лівий, верхній, правий і нижній прямокутні джерела та маски відповідно.

Таким чином, ми можемо створити таблицю пошуку, яка відображає координати до набору всіх таких можливих комбінацій (саме про це product(product(*zip(*)))є біт) до набору прямокутників, які повинні бути надані для кожного із випадків (що після деякого гофро-декомпресії , про що йдеться у решті речей із списку).


-15 байт , роблячи різні поліпшення для гольфу, або -18 байт за допомогою рядків у Python 3.
notjagan

Ви можете відірвати ще два байти, виконавши p=productі замінивши product(productнаp(p
musicman523

3

JavaScript, 115 байт

f=a=>b=>b.some((n,i)=>(a[i^2]<n)^i/2)?[a]:b.map((n,i)=>a[i&1]<n&&n<a[i|2]&&(p=[...a],p[i^2]=a[i]=n,p)).filter(x=>x)

версія, що перекривається:

f=a=>b=>b.some((n,i)=>(a[i^2]<n)^i/2)?[a]:b.map((n,i)=>a[i&1]<n&&n<a[i|2]&&(p=[...a],p[i^2]=n,p)).filter(x=>x)

Введіть у такому форматі: f([1,1,8,8])([0,6,9,9])


Позначимо введення як ((x1, y1), (x2, y2)), ((x3, y3), (x4, y4))

Якщо виконується будь-яка з наступних умов, поверніть перший прямокутник таким, яким є:

  • x3> x2
  • x4 <x1
  • y3> y2
  • y4 <y1

інакше

  • Якщо x1 <x3 <x2, то формуємо прямокутник ((x1, y1), (x3, y2)); і встановити x1: = x3
  • Якщо x1 <x4 <x2, то формуємо прямокутник ((x4, y1), (x2, y2)); і встановити x2: = x4
  • Якщо y1 <y3 <y2, то формуємо прямокутник ((x1, y1), (x2, y3)); і встановимо y1: = y3
  • Якщо y1 <y4 <y2, то формуємо прямокутник ((x1, y4), (x2, y2)); і встановіть y2: = y4

Це перспективний підхід; але в даний час вона не вдається часом, наприклад, коли прямокутник маски не перекривається прямокутником-джерелом; наприклад, f([0, 30, 10, 40])([5, 1, 6, 2])слід повернутися, [[0, 30, 10, 40]]але замість цього повертається[[0,30,5,40],[6,30,10,40]]
Chas Brown

@NathanMerrill добре, відредаговано.
tsh

@tsh добре виглядає!
Натан Меррілл

1

Java, 268 байт

class W{public static void main(String[]z) {int a[]={0,0,0,0},i,j,y[]={0,1,4,3,6,1,2,3,4,1,6,5,4,7,6,3};for(i=0;i<4;i+=1){for(j=0;j<4;j+=1){a[j]=Integer.parseInt(z[y[i*4+j]]);}if(a[0]<a[2] && a[1]<a[3]){for(j=0;j<4;j+=1){System.out.println(String.valueOf(a[j]));}}}}}

Безумовно

class W{
    public static void main(String[]z) {
        int a[]={0,0,0,0},i,j,y[]={0,1,4,3,6,1,2,3,4,1,6,5,4,7,6,3};

        for(i=0;i<4;i+=1){
            for(j=0;j<4;j+=1){
                a[j]=Integer.parseInt(z[y[i*4+j]]);
            }
            if(a[0]<a[2] && a[1]<a[3]){
                for(j=0;j<4;j+=1){
                    System.out.println(String.valueOf(a[j]));
                }
            }
        }
    }
}

Передати введення як аргументи. Приклад

java -jar W.jar 0 0 5 5 3 4 8 7

0

Пітон 2 , 272 байти

lambda((a,b),(c,d)),((e,f),(g,h)):[([([[(a,b),(e,min(h,d))]]+[[(g,max(b,f)),(c,d)]]*2+[[(max(a,e),b),(c,f)]]*4+[[(a,h),(min(c,g),d)]])[m-1]for m in M&{1,2,4,8}]if M&{0}else[(a,b),(c,d)])for M in[{(x<e)*1+(x>g)*2+(y<f)*4+(y>h)*8 for x in range(a,c)for y in range(b,d)}]][0]

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

Це працює, перевіряючи кожну комірку всередині першого прямокутника на лівості = 1, надмірність = 4, правильність = 2 та нижню частину = 8 w / r для іншої та ORing результат. Якщо інший не перетинається = 0 з першим, тоді повертається оригінал, інакше повернеться деяка комбінація лівого зрізу, правого зрізу, верхнього та нижнього фрагмента з урахуванням перекриття.

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