Перетин двох трикутників


19

Давши 4 точки на площинах 2D A, B, C, D, обчисліть площу перетину трикутників OABі OCD, де Oцентр площини, має координату (0, 0).

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

Правила

  • Кожна точка представлена ​​у вигляді двох дійсних чисел, позначає їх координати X і Y.
    • За бажанням, якщо ваша мова програмування (або якась бібліотека вашої мови програмування) має вбудований Pointтип або еквівалент, дозволено приймати Pointоб'єкт як вхід.
  • Вхід подається у вигляді 4 балів у форматах, включаючи, але не обмежуючись ними:
    • Список з 8 координат.
    • Список з 4 балів, кожна точка може бути представлений у будь-якому зручному форматі.
    • Два списки по 2 бали.
    • тощо.
  • Ви не можете припускати особливого впорядкування точок (порядок проти годинникової стрілки чи за годинниковою стрілкою)
  • Ви не можете припустити, що точка Oпередається як вхід. Іншими словами, програма не повинна приймати та використовувати сторонні введення.
  • Ви не можете припустити, що всі пункти різні. Іншими словами, трикутники можуть бути виродженими. Вам також потрібно розглянути цей випадок (див. Тестові випадки нижче)
  • Абсолютна або відносна різниця повинна бути меншою, ніж для наведених нижче зразків тестових випадків.10-3

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

Це , найкоротша відповідь у виграші байтів!

Зразки тестових кейсів

Ax Ay Bx By Cx Cy Dx Dy area

5 1 1 3 -1 0 0 -1 0
5 1 1 3 -1 0 0 0 0
5 1 1 3 0 0 0 0 0
5 1 1 3 3 4 4 -3 4.50418
5 1 1 3 1 2 2 1 1.5
5 1 1 3 -2 5 4 -2 1.74829
5 1 1 3 -2 5 5 4 2.96154
5 1 1 3 3 5 5 4 1.88462
5 1 1 3 3 5 3 1 3.92308
5 1 1 3 3 5 4 -1 5.26619
5 1 1 3 5 1 4 -1 0
5 1 1 3 5 1 1 3 7
1 3 1 3 5 1 1 3 0
1 3 1 3 1 3 1 3 0
4 8 4 -1 -2 6 -2 -3 0

1.2 3.4 -0.3 4.2 5 7.6 -1.1 2.4 2.6210759326188535
3.1 0.6 0.1 7.2 5.2 0.7 0.9 8 9.018496993987977

Якщо хто хоче, ось результати першої групи тестових випадків у точному вигляді:

0
0
0
46375/10296
3/2
1792/1025
77/26
49/26
51/13
23345/4433
0
7
0
0
0

Ілюстраційне зображення для тестового випадку 5 1 1 3 3 4 4 -3(площа зеленого чотирикутника - очікуваний вихід):

[ Зображення]


Один з ваших тестових випадків має 9 входів, а не 8. 1.2 3.4 -0.3 4.2 5 3 7.6 -1.1 2.4 0
Келлі Лоудер

1
Виправлено @KellyLowder.
користувач202729

Відповіді:


16

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

0&@@Area@BooleanRegion[And,Simplex[{0{,}}~Join~#]&/@#]&

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

Поголив кілька байтів від тривіальної відповіді.

%@{{{5, 1}, {1, 3}}, {{3, 4}, {4, -3}}} yields 46375/10296 or 4.504176379

Заміна Areaна DiscretizeRegionпокаже перехрестя.

введіть тут опис зображення

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

-1 байт завдяки JungHwan Min

@ пропозиція користувача202729 додала 4 байти, але змушує отримати 0 для вироджених трикутників


1
Полігон можна замінити і на Simplex
Келлі Лоудер

1
Ще один байт: {{0,0}}до {0{,}}(це працює, оскільки вираз оцінюється до {Times[0, {Null, Null}]})
JungHwan Min

Невдача для цього тестового випадку , який вказаний у зразках тестових випадків.
користувач202729

Вже зазначалося, що це НЕ працює на TIO. Не впевнені, що у них під капотом.
Келлі Лоудер

1
Я бачу, що це не працює для перетину двох прямих. Моє погано пропустити тестовий випадок. Технічно це не трикутники. Я гадаю, якщо ми збираємось отримати технічну техніку, можливо, ви повинні змінити назву посади, а також перше речення. Ми також могли б по-справжньому езотерично обговорити питання про те, чи визначена область для одновимірного об'єкта, але я вважаю за краще це не робити.
Келлі Лоудер

5

Python 2 + PIL, 341 318 313 284 270 байт

Особлива подяка Деннісу за те, що оперативно додав PIL на TIO
-23 байти завдяки панові Xcoder

import PIL.Image as I,PIL.ImageDraw as D
l=[i*1000for i in[0,0]+input()+[0,0]]
z=zip(*[[i-min(t)for i in t]for t in l[::2],l[1::2]])
print sum(map(int.__mul__,*map(lambda i,c:D.Draw(i).polygon(c,1)or i.getdata(),map(I.new,'11',[[max(l)-min(l)]*2]*2),[z[:3],z[3:]])))/1e6

Спробуйте в Інтернеті! або Спробуйте всі тестові приклади

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

Пояснення

#the image/triangles are enlarged to increase the precision
#a pair of zeros are inserted in the start and at the end, this way "l" will have all 6 points to draw the triangles 
l=[i*1000for i in[0,0]+input()+[0,0]]
#split the input in x and y, where x=l[::2] and y=l[1::2]
#get the smallest number on each list, that will be "0" if there is no negative number, to be used as offset.
#this will be used to overcome the fact that PIL won't draw on negative coords
#zip "x" and "y" lists, to create a list containing the points
z=zip(*[[i-min(t)for i in t]for t in x,y])
#create 2 (B&W) blank images
#where the size is the difference between the smallest and the largest coord.
map(I.new,'11',[[max(l)-min(l)]*2]*2)
#draw both triangles and return the pixel list of each image
map(lambda i,c:D.Draw(i).polygon(c,1)or i.getdata(),<result of previous line>,[z[:3],z[3:]])
#count the amount of overlapping pixels by summing the color of each pixel, if the pixel is "1" in both images, then the triangles are overlapping, then the amount of pixels is divided by the initial enlarging factor squared (1e6)
print sum(map(int.__mul__,*<result of previous line>))/1e6
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.