Прямоугольная разница

20

В этом задании вам дается два перекрывающихся прямоугольника, и вам нужно вычислить прямоугольники, созданные путем удаления одного из другого.

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

прямоугольники

Вы получите один из следующих двух наборов прямоугольников:

сплит-один сплит-два

Вам также нужно будет обработать следующее:

Все тесты

Чтобы быть более явным:

  • Вы введете координаты двух прямоугольников A и B.
  • Вам нужно вывести наименьшее количество непересекающихся прямоугольников, которые покрывают всю область 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

Это , поэтому сделайте ваш код как можно короче!

Натан Меррилл
источник
3
Связанный.
Мартин Эндер
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 случаев; Например, первый пример OP - это случай, который мы можем пометить (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))

Если выполняется одно из следующих условий, вернуть первый прямоугольник как есть:

  • х3> х2
  • х4 <х1
  • у3> у2
  • у4 <у1

в противном случае

  • Если x1 <x3 <x2, то мы генерируем прямоугольник ((x1, y1), (x3, y2)); и установите x1: = x3
  • Если x1 <x4 <x2, то мы генерируем прямоугольник ((x4, y1), (x2, y2)); и установите х2: = х4
  • Если 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]]
Час Браун
@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]));}}}}}

Ungolfed

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

Python 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 по отношению к другой, и ИЛИ результат. Если другой не пересекает = 0 с первым, то возвращается оригинал, в противном случае возвращается некоторая комбинация левого, правого, верхнего и нижнего слоев с возможностью перекрытия.

SmileAndNod
источник