Перевірте, чи точка лежить всередині трикутника


40

Ваша мета - визначити, чи лежить задана 2D точка X у межах трикутника із заданими вершинами A, B, C.

Напишіть функцію, яка бере координати тестової точки X і трьох вершин трикутника (так це всього 8 координат) і повертає True, якщо точка лежить всередині цього трикутника, і False, якщо вона лежить зовні.

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

У вашому коді повинна бути названа функція. Фрагменти коду не приймаються.

Виграє мало хто з персонажів.

Вхід:

Вісім реальних чисел, що представляють координати. Цифри будуть лежати в діапазоні (-1,1).

Точний формат введення є гнучким. Ви можете, наприклад, взяти вісім чисел, список з восьми чисел, список з чотирьох точок, кожен з яких задається кортежем, матриця 2 * 4, чотири комплексних числа, два списки x-координат та y-координат, і так далі.

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

Будь ласка, вкажіть формат введення.

Вихід:

Або відповідний булевий True/ False, відповідний номер 1/ 0, або аналоги вашої мови.

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

Вхідним дається список [X,A,B,C]із чотирьох кортежів, спочатку тестовий пункт, потім три вершини трикутника. Я згрупував їх у ті, чиї результати мають бути, Trueі ті, які повинні бути False.

True екземпляри:

[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]

False екземпляри:

[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]

Яке ваше визначення характеру? Асці? Розширюється в 7 біт? У байті? Будь-який Unicode?
isaacg

Що ти пропонуєш? Вже є рішення, які використовують стислий код.
xnor

Як правило, я вважаю, що байти використовуються для символів, які не є Ascii, тому що в іншому випадку перевага Utf-32 є непереборною.
isaacg

Ну, я не можу повернутися назад; будь-який символ Unicode - це символ. Стисніть, якщо хочете.
xnor

Відповіді:


19

Javascript / ECMAScript 6, 161 159 158/152

Javascript:

function $(t,r,i,a,n,g,l,e){b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

Версія ECMAScript 6 (спасибі m.buettner, економить 6 символів)

$=(t,r,i,a,n,g,l,e)=>{b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

Назвіть це як таке (повертається trueабо false):

$(pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y);

Використовує деяку фантазійну барицентричну математику координат на основі коду з цієї відповіді . Недолікована версія для задоволення від читання наступна:

function $ (pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y) {
  var A =  (-v2Y * v3X + v1Y * (-v2X + v3X) + v1X * (v2Y - v3Y) + v2X * v3Y) / 2;
  var sign = A < 0 ? -1 : 1;
  var s = (v1Y * v3X - v1X * v3Y + (v3Y - v1Y) * pointX + (v1X - v3X) * pointY) * sign;
  var t = (v1X * v2Y - v1Y * v2X + (v1Y - v2Y) * pointX + (v2X - v1X) * pointY) * sign;
  return s > 0 && t > 0 && s + t < 2 * A * sign;
}

12
+1, якщо тільки для імен параметрів!
Метт

Чому ви повинні зламати мій UserScript, що рахує персонажів ???
kitcar2000

@ kitcar2000, що ти маєш на увазі?
Авраам

У правилах сказано, що символи рахуються, а не байти. Таким чином, ви можете використовувати це: xem.github.io/obfuscatweet, щоб вмістити 122 символи
xem

1
Я помиляюсь, чи ти міг використати (a*(l-n)+i*(g-e)+n*e-g*l)замість цього (-g*l+a*(-n+l)+i*(g-e)+n*e)?
Zacharý

19

Пітон 2,7 128 127 117 110 109 103 99 95 94 91 90

Моя перша спроба коду-гольфу!

Код

f=lambda x,y,t:sum(a*y+c*b+d*x<d*a+c*y+b*x for i in(0,1,2)for a,b,c,d in[t[i-1]+t[i]])%3<1

Вважається входом (x, y, t), де (x, y) - точка, яку ми перевіряємо, і t - трикутник t = ((x1, y1), (x2, y2), (x3, y3)).

Пояснення

Я обчислюю визначники матриць

| 1 x1 y1 |      | 1 x2 y2 |      | 1 x3 y3 |
| 1 x2 y2 | ,    | 1 x3 y3 | ,    | 1 x1 y1 | .
| 1 x  y  |      | 1 x  y  |      | 1 x  y  |

Ці детермінанти представляють підписані відстані від сторін трикутника до точки (x, y). Якщо всі вони мають однаковий знак, то точка знаходиться на одній стороні кожного прямого і, таким чином, міститься в трикутнику.

У наведеному вище коді a*y+c*b+d*x-d*a-c*y-b*xє визначником однієї з цих матриць.

Я використовую те, що True+True+True==3і False+False+False==0щоб визначити, чи всі ці детермінанти мають однаковий знак.

Я використовую індекси негативного списку Python, використовуючи t[-1]замість t[(i+1)%3].

Дякую Петру за ідею використовувати s%3<1замість того, s in(0,3)щоб перевірити, чи s 0 або 3!

Версія Sagemath

Насправді не інше рішення, тому я включаю його у цю відповідь, сагемат-рішення з використанням 80 символів:

f=lambda p,t,o=[1]:sum([det(Matrix([o+t[i-1],o+t[i],o+p]))<0for i in 0,1,2])%3<1

де p=[x,y]іt=[[x1,y1],[x2,y2],[x3,y3]]


1
Можна s in (0,3)скоротити s%3<1?
Пітер Тейлор

1
Використання негативних індексів можна змінити, щоб зберегти ще один: -1,0,1 ... t[i]+t[i+1]еквівалентно0,1,2 ... t[i-1]+t[i]
Пітер Тейлор

@PeterTaylor Абсолютно правильно! Шкода, що я видалив пробіл, in -1,0,1перш ніж прочитати це. Насправді ваш шлях є більш читабельним, тому я все одно буду його використовувати.
Alex L

1
Ласкаво просимо до коду гольфу! Ви можете позбутися квадратних дужок для розуміння списку всередині, sumякщо ви вкладете 0,1,2в круглі дужки, у яких виходить символ, замінивши пробіл. Причина полягає в тому, що Python дозволяє передавати необмежене розуміння функціям, але коми в голому кортежі 1,2,3плутають його, оскільки він намагається розібрати їх як окремі аргументи.
xnor

16

Математика, 67 байт

f=Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])&

Функція бере два аргументи, точку Xта список точок {A,B,C}, які позначаються як #і #2відповідно. Тобто, якщо ви телефонуєте

f[X,{A,B,C}]

тоді ви отримаєте #як Xі #2як {A,B,C}. (Зверніть увагу , що є дві інші анонімні функції , вкладені в коді - #і #2. Мають різне значення в межах тих)

Ось пояснення самої функції:

                                              x=#;#2            & (* Save X into a variable x, but evaluate to {A,B,C}. *)
                                    Partition[x=#;#2,2,1,{1,1}] & (* Get a cyclic list of pairs {{A,B},{B,C},{C,B}}. *)
       (                        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Define an anonymous function and apply it to each 
                                                                     of the above pairs. The two elements are referred 
                                                                     to as # and #2. *)
       (          (#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Subtract the two points. For a pair of vertices 
                                                                     this yields a vector corresponding to the edge 
                                                                     between them. *)
        {#2,-#}&                                                  (* An anonymous function that takes two values, 
                                                                     reverses them, inverts the sign of one of them 
                                                                     and puts them into a list. *)
       ({#2,-#}&@@(#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Applied to the edge, this yields its normal. *)
       ({#2,-#}&@@(#-#2).(x-#)  &@@@Partition[x=#;#2,2,1,{1,1}])& (* Take the scalar product of that normal with a
                                                                     vector from a vertex to x. This is projection of 
                                                                     this vector onto that normal and hence the SIGNED
                                                                     distance of x from the edge. *)
       ({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check the sign of that distance, the exact mapping 
                                                                     between (left, right) and (True, False) is 
                                                                     irrelevant, as long as it's consistent. *)
Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check if all signs are equal - that is, if point X 
                                                                     lies on the same side of all edges. This is 
                                                                     equivalent to check that the point is inside the 
                                                                     triangle. *)

Зауважте, що ця функція фактично буде працювати для будь-якого опуклого n-гона до тих пір, поки його вершини будуть задані в порядку або проти годинникової стрілки.


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

@isaacg Існує три терміни, тож якщо вони всі негативні, їхній продукт негативний, а якщо вони всі позитивні, то їхній продукт є позитивним. Ваш підхід працює лише в тому випадку, якщо знаки двох чисел повинні бути рівними.
Мартін Ендер

Чому б не використовувати Det?
алефальфа

@alephalpha Ну, швидше за все, тому що я не думав про це. : P ... Я розберуся в цьому
Мартін Ендер

@alephalpha Гм ні, я зараз не можу знайти спосіб побудувати три необхідні матриці з меншими символами.
Мартін Ендер

7

CJam, 66 63 59 52 46 34 32 31 30 28 символів

"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

Після трансформації рядка Unicode оцінюється наступний код ( 33 байти ):

{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T

Очікує X [A B C]як вхід, де кожна точка має форму [double double]. Вихід - 1 або 0.

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

Велике дякую користувачеві user23013 за збереження 6 символів (13 байт нестисненого коду)!

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

$ cat triangle.cjam
"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

[
  [-0.31961 -0.12646] [ [0.38478 0.37419]   [-0.30613 -0.59754] [-0.85548 0.6633]   ] T
  [-0.87427 -0.00831] [ [0.78829 0.60409]   [-0.90904 -0.13856] [-0.80685 0.48468]  ] T
  [0.28997 -0.03668]  [ [-0.28362 0.42831]  [0.39332 -0.07474]  [-0.48694 -0.10497] ] T
  [-0.07783 0.04415]  [ [-0.34355 -0.07161] [0.59105 -0.93145]  [0.29402 0.90334]   ] T
  [0.36107 0.05389]   [ [0.27103 0.47754]   [-0.00341 -0.79472] [0.82549 -0.29028]  ] T
  [-0.01655 -0.20437] [ [-0.36194 -0.90281] [-0.26515 -0.4172]  [0.36181 0.51683]   ] T
  [-0.12198 -0.45897] [ [-0.35128 -0.85405] [0.84566 0.99364]   [0.13767 0.78618]   ] T
  [-0.03847 -0.81531] [ [-0.18704 -0.33282] [-0.95717 -0.6337]  [0.10976 -0.88374]  ] T
  [0.07904 -0.06245]  [ [0.95181 -0.84223]  [-0.75583 -0.34406] [0.16785 0.87519]   ] T
  [-0.33485 0.53875]  [ [-0.25173 0.51317]  [-0.62441 -0.90698] [-0.47925 0.74832]  ] T
  [-0.99103 0.43842]  [ [0.78128 -0.10985]  [-0.84714 -0.20558] [-0.08925 -0.78608] ] T
  [0.15087 -0.56212]  [ [-0.87374 -0.3787]  [0.86403 0.60374]   [0.01392 0.84362]   ] T
  [0.1114 0.66496]    [ [-0.92633 0.27408]  [0.92439 0.43692]   [0.8298 -0.29647]   ] T
  [0.87786 -0.8594]   [ [-0.42283 -0.97999] [0.58659 -0.327]    [-0.22656 0.80896]  ] T
  [0.43525 -0.8923]   [ [0.86119 0.78278]   [-0.01348 0.98093]  [-0.56244 -0.75129] ] T
  [-0.73365 0.28332]  [ [0.63263 0.17177]   [-0.38398 -0.43497] [-0.31123 0.73168]  ] T
  [-0.57694 -0.87713] [ [-0.93622 0.89397]  [0.93117 0.40775]   [0.2323 -0.30718]   ] T
  [0.91059 0.75966]   [ [0.60118 0.73186]   [0.32178 0.88296]   [-0.90087 -0.26367] ] T
  [0.3463 -0.89397]   [ [0.99108 0.13557]   [0.50122 -0.8724]   [0.43385 0.00167]   ] T
  [0.88121 0.36469]   [ [-0.29829 0.21429]  [0.31395 0.2734]    [0.43267 -0.78192]  ] T
]p;

$ cjam triangle.cjam
[1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0]

Це названа функція?
Мартін Ендер

@ m.buettner: Сортування. Офіційна вика говорить наступне: блок - ділянку програми , обмежені {і }і розглядаються як єдине ціле. Аналогічно кодовим блокам у C / java, за винятком того, що блоки є об'єктами першого класу і можуть бути призначені змінним (таким чином визначаючи функції).
Денніс

1
@xnor 1m<@m*готує 3 пари X і наступну ( i+1й) вершину трикутника. @-@@-переміщує поточну ( iй) вершину до початку (і дзеркально, якщо її не було @-\@-, але це не має значення). @@*@@*>обчислює вісь z поперечного добутку, яка також визначальна, і повертає, 1якщо вона від’ємна. :+3%!повертає, чи всі вони однакові, тобто всі 3 є негативними чи негативними, що означає позитивні, крім крайових випадків. Я думаю, що читати CJam складніше, ніж гольф.
jimmy23013

1
37 байт: {[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T. Використовуйте 2m>або Wm<для безпеки Unicode.
jimmy23013

1
33 байти:{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
jimmy23013

5

C - 156 байт

Вхідні дані - це масив з 3 поплавків у X, 3 поплавця у Y та окремо x та y для точки тесту. Бонус: обробляє всі крайові справи!

int f(float*X,float*Y,float x,float y){int i,j,c=0;for(i=0,j=2;i<3;j=i++)if(((Y[i]>y)!=(Y[j]>y))&&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[i]))c=!c;return c;}

Адаптовано з PNPOLY.


i;j;c;f(float*X,float*Y,float x,float y){for(c=i=0,j=2;i<3;)c^=(Y[i]>y)-(Y[j]>y)&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[j=i++]);return c;}137 - перевірено на javascript
bebe

@bebe - Це спричиняє синтаксичну помилку.
Дерек 朕 會 功夫

Це не викликає синтаксичної помилки.
bebe

4

Піт 1.0.5 , 57 54 51

DgYb=Z0J'bWbK;bDiHNR*-'H'K-@N1@K1~Z>iYJiJY=JK)R!%Z3

Визначає функцію g, яка займає два входи: тестову точку, а потім список вершин трикутника. Виходи Trueта False. Примітка: знищує вхід, зокрема b, список вершин трикутника.

Спробуйте тут . Кілька останніх символів gvwvwвикликайте функцію з тестовим випадком у наступних двох рядках.

На основі цього алгоритму

Пояснення:

DgYb                  Define g(Y,b):
=Z0                     Z=0
J'b                     J=b[0]              (No = is needed because j is special).
Wb                      While len(b)>0:     (While b:)
K;b                       K=b.pop()
DiHN                      Define i(H,N):    
R*-'H'K-@N1@K1              Return half of the linked equation.
~ZiYJiJY                  Z+=i(Y,J)>i(J,Y)
=JK                       J=K
)                       Wend
R!%Z3                   return not Z%3==0   (True iff Z == 0 or 3)

CJam - Pyth війна триває!


Це має бути названа функція. Єw приймаєте STDIN?
xnor

@xnor На жаль, я пропустив цей фрагмент опису. Відредагуємо.
isaacg

@xnor Чи дозволені функції, які роздруковують відповідь, або вони повинні повертати відповідь? Наразі ця відповідь роздруковує, але я міг би повернути її ще одному символу.
isaacg

Поверніть відповідь.
xnor

Чи можете ви зберегти символи, замінивши лічильник Z на порожній набір, який ви накопичуєте Z|=, а потім протестуйте його довжину, щоб побачити, 0чи 1бачились лише ті чи вони? Стратегія виявилася довшою в Python, але, можливо, вона варта того, щоб використовувати примітиви Pyth.
xnor

4

J 64 45 (42 без призначення)

c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)

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

Сподіваючись набрати кілька додаткових балів тут ...: Ця річ працює для будь-якого виміру симплексу, не лише трикутників у площині, але й 3-х сторінної піраміди в 3d-просторі тощо. Він також працює, коли кількість вершин симплексу менше (n + 1), то він обчислює, чи є проекція точки на симплекс всередині чи ні.

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

NB. example in triangle
D =: 4 2 $ 1 1 0 0 3 0 0 2 NB. 4 rows , x first, then the vertices of the triangle

NB. subtract last vertex coordinates from the rest and drop reference node
n=: (}:-"1{:)

NB. preprocessed to barycentric coordinates
bar=: {. (, 1 - +/)@%. |:@}.

NB. all positive
ap =: *./@(>:&0)

insided =: ap@bar@n

inside D
1

Пробіг за наведеними прикладами:

   true =: 0 : 0
[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
)

   false =: 0 : 0
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]
)
   NB. replace - by _ to avoid problems
   NB. cut up per row, drop the [ ] and convert to numbers
   $dat_t =: ((4 2 $ ".)@}:@}.;._2) (true='-')} true ,: '_'
10 4 2
   $dat_f =: ((4 2 $ ".)@}:@}.;._2) (false='-')}false,: '_'
10 4 2
   NB. this results in arrays with shape 10 4 2

   NB. for each 4 x 2 array (rank 2), do c for all true instances
   c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)
   c"2 dat_t
1 1 1 1 1 1 1 1 1 1
   NB. the same for the false ones, demonstrating anonymous usage
   NB. still a function though (or verb in J parlance)
   *./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)"2 dat_f
0 0 0 0 0 0 0 0 0 0

Я попросив назвати функцію, тому символи присвоєння враховуються. Ось декілька пунктів для узагальнення до багатокутників! ······
xnor

Ну, насправді я не зовсім узагальнюю на багатокутники, а на N-мірні симплекси з максимальними N+1вершинами. Наприклад, 4 вершинна піраміда в 3-D просторі або 5 вершина симплекс у 4-D просторі. Кількість вершин може бути нижчою, ніж N+1у такому випадку алгоритм виглядає, чи ортогональна проекція на гіперплощину симплекс знаходиться лежить всередині симплекса чи ні (наприклад, 2-бальний симплекс у 2-D буде проектуватися на лінію та перевірятися чи лежить ця проекція між кінцевими точками)
jpjacobs

4

HTML5 + JS, 13b + 146b / 141b / 114 символів

HTML:

<canvas id=C>

JS (146b):

// @params: t1x, t1y, t2x, t2y, t3x, t3y, pointx, pointy
function T(a,b,c,d,e,f,g,h){with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

або ES6 (141b):

T=(a,b,c,d,e,f,g,h)=>{with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

або ES6, заблокований unicode (114 знаків):

eval(unescape(escape('𥀽𚁡𛁢𛁣𛁤𛁥𛁦𛁧𛁨𚐽🡻𭱩𭁨𚁃𛡧𩑴𠱯𫡴𩑸𭀨𘠲𩀢𚐩𬡥𭁵𬡮𘁢𩑧𪑮𤁡𭁨𚀩𛁭𫱶𩑔𫰨𨐬𨠩𛁬𪑮𩑔𫰨𨰬𩀩𛁬𪑮𩑔𫰨𩐬𩠩𛁦𪑬𫀨𚐬𘐡𩱥𭁉𫑡𩱥𡁡𭁡𚁧𛁨𛀱𛀱𚐮𩁡𭁡𦰳𧑽').replace(/uD./g,'')))

демо: http://jsfiddle.net/xH8mV/

Обфузація Unicode зроблена за допомогою: http://xem.github.io/obfuscatweet/


Схоже, це не дає правильного результату, коли точка знаходиться поруч: jsfiddle.net/L2B2A Я вважаю, що це тому, що всі входи знаходяться між (-1,1), а ваш код протестує лише 4 пікселі навколо походження.
Дерек 朕 會 功夫

це правильно, щоб відповідати прикладам, я повинен змінити походження та масштаб свого полотна, щоб обробляти трикутники всередині [-1,1]. Але чому ці трикутники все одно такі маленькі?
xem

проблема говорить про те, що всі xy знаходяться в межах від -1 до 1. Не дуже знаю, чому, але я вважаю, що ви можете просто помножити кожен вхід на 1e7 (щоб підтримувати точність), щоб отримати правильний результат: D
Дерек 朕 會 功夫

Графічне рішення, дуже розумне!
xnor

3

Пітон (65)

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

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

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

По-перше, я поясню менш гольф-версію коду;

def f(X,A,B,C):A-=X;B-=X;C-=X;return((A/B).imag>0)==((B/C).imag>0)==((C/A).imag>0)

Зсуваємо точки A,B,C,Xтак, щоб Xце було біля витоків, скориставшись вбудованою складною арифметикою Python. Нам потрібно перевірити, чи міститься походження в опуклому корпусі A,B,C. Це еквівалент походження, що завжди лежить на одній стороні (зліва чи справа) відрізків лінії AB, BC та AC.

Відрізок ABмає початок зліва, якщо один рухається проти годинникової стрілки менше 180 градусів, щоб дістатися від А до В, а праворуч інакше. Якщо розглядати кути a, bі cвідповідні цим точкам, це означає b-a < 180 degrees(прийняті кути в межах від 0 до 360 градусів). У комплексних чисел angle(B/A)=angle(B)/angle(A). Крім того, angle(x) < 180 degreesсаме для точки у верхній півплощині, яку ми перевіряємо через imag(x)>0.

Отже, чи походження лежить від AB, виражається як (A/B).imag>0. Перевірка того, чи всі вони рівні для кожної циклічної пари, A,B,Cвказує нам, чи ABCмістить трикутник початок.

Тепер повернемося до повністю гольф-коду

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

Ми генеруємо кожну циклічну пару (A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X), використовуючи перевагу негативних індексів списку Python, що обертаються навколо ( L[-1]= L[2]). Щоб перевірити, що Bools є всі True( 1) або all False( 0), ми додаємо їх і перевіряємо подільність на 3, як це робило багато рішень.


2

Фортран - 232 218 195 174

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

logical function L(x);real::x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4);L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s);endfunction

Зменшення на 14 символів відбувається через те, що я забув переймати назву функції з моїх тестових запусках. Подальше зменшення пов'язане з неявним набором тексту та забуттям змінити ім’я функції. Наступні 20 символів вийшли через читання в точках як єдиний масив. Повна програма є

program inTriagle
   real, dimension(2) :: a,b,c,x
   do 
      print*,"Enter coordinates as x,a,b,c"
      read*,x,a,b,c
      if(all(x==0.0).and.all(a==0.0).and.all(b==0.0).and.all(c==0.0)) exit
      print*,"Is point in triangle: ",T(x,a,b,c)
   enddo
 contains!                       
   logical function L(x)
     real::x(8)
     p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3)
     s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4)
     L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s)
   endfunction
end program inTriagle

1
Ви можете зробити це трохи коротше, покладаючись на неявне введення Fortran та використовуючи єдиний масив вхідних даних, що містить усі 8 чисел: logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);o=r*v-u*s;T=ALL([p*(s-v)+q*(u-r)+o,p*v-q*u,q*r-p*s]>=o);endЯ спробував це ще більше скоротити за допомогою списку операцій, але, на жаль, це не вийшло дуже добре.
Вентеро

1
Ще коротше, усуваючи більш поширені підекспресії: logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);a=r*v-u*s;b=p*v-q*u;d=q*r-p*s;T=ALL([a-b-d,b,d]>=a);endсподіваюся, я не помилився в перетвореннях! Хоча схоже, що ваш оригінальний код не проходить усі тести.
Вентеро

@ Вентеро: Я не можу повірити, що забув зловживати неявним набором тексту :(. Дякую за допомогу!
Kyle Kanos

@ Вентеро: Також, схоже, моя відповідь залежить від орієнтації трикутника. Перший Trueприклад в програмі OP дає, Falseякщо я підміняю Bі C's значеннями, даючи Trueоригінальну орієнтацію.
Кайл Канос

Дійсно, проблема виникає, коли (повторне використання позначення з мого попереднього коментаря) a < 0, що фактично перевертає стан, який ви повинні перевірити. На жаль, це неможливо просто виправити, загорнувши все у abs, оскільки тоді мається на увазі умова bта dмає той самий знак, що aвтрачається. Це можна виправити, використовуючи щось на кшталт (знову ж таки, повторне використання позначень та заздалегідь визначених змінних з мого останнього коментаря) e=a-b-d;T=ALL([a*a-b*b,a*a-d*d,a*a-e*e,a*b,a*d,a*e]>=0)- що, ймовірно, може бути більше в гольфі.
Вентеро

2

МАТЛАБ: 9!

Тут не багато мені писати

inpolygon

Можна назвати так:

inpolygon(2/3, 2/3, [0 1 1], [0 0 1])

Вихідні дані присвоюються змінній з назвою ans


Якби мені насправді довелося написати функцію, можливо, щось подібне, можливо, було б оптимізовано:

function y=f(a,b,c,d)
inpolygon(a,b,c,d)

2
можна коротше використовувати функціональну ручку:f=@(a,b,c,d)inpolygon(a,b,c,d)
jpjacobs

2

C # 218 (149?)

using P=System.Drawing.PointF;
bool F(P[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}P[]a=new P[3];Array.Copy(p,1,a,0,3);var g=new System.Drawing.Drawing2D.GraphicsPath();g.AddLines(a);return g.IsVisible(p[0]);}

Напевно, не настільки ефективний, як математичний метод, але це цікаве використання бібліотек. До речі, теж досить повільно.

Також скориставшись "Також не турбуйтеся про чисельну стабільність або точність з плаваючою комою". - на жаль, GraphicsPathвикористовує ints внутрішньо, тому значення в діапазоні -1 <f <1 може мати лише три можливі значення. Оскільки поплавці мають лише 7 цифр точності, я просто множу на 1e7, щоб перетворити їх на цілі числа. Гм, я думаю, це не дуже втрачає точність. Це також корисно іншим способом: я, мабуть, міг би скористатися ігноруванням точності і просто давши «неправильну» відповідь.

Якщо мені дозволяють ігнорувати характер символів імпорту бібліотек, 149 (як мінімум, System.Linqі System.Drawingє досить стандартними для більшості проектів WinForms, але це System.Drawing.Drawing2Dможе бути трохи розтягнутим):

bool G(PointF[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}var g=new GraphicsPath();g.AddLines(p.Skip(1).ToArray());return g.IsVisible(p[0]);}

Тестова програма (так, це некрасиво):

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using P=System.Drawing.PointF;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program prog = new Program();
        foreach (string test in
@"[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]".Split('\n'))
        {
            string t = test.Replace("[(", "").Replace(")]", "");
            string[] points = t.Split(new string[] { "), (" }, StringSplitOptions.None);

            string[] p = points[0].Split(',');
            P[] xabc = new P[4];

            for (int i = 0; i < 4; i++)
            {
                p = points[i].Split(',');
                xabc[i] = new F(float.Parse(p[0]), float.Parse(p[1]));
            }

            Console.WriteLine(test + "=>" + prog.F(xabc));
        }

        Console.ReadKey();
    }

    bool G(PointF[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }

    bool F(P[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new System.Drawing.Drawing2D.GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }
}

Симпатично, отримуючи двигун для малювання, щоб виконати роботу.
xnor

2

Хаскелл - 233 127

Використання перехресних продуктів, як описано тут :

h(a,b)(p,q)(r,s)(t,u)=z a b p q r s==z a b r s t u&&z a b r s t u==z a b t u p q where z j k l m n o =(o-m)*(j-l)+(l-n)*(k-m)>0

Попереднє рішення, реалізоване з використанням барицентричних координат та формул, описаних у цій відповіді Stack Exchange :

g(p,q)(r,s)(t,u)(v,w)=
 let (j,k)=(p+(-r),q+(-s))
     (l,m)=(t+(-r),u+(-s))
     (n,o)=(v+(-r),w+(-s))
     d=l*o-n*m
     a=(j*(m-o)+k*(n-l)+l*o-n*m)/d
     b=(j*o-k*n)/d
     c=(k*l-j*m)/d
 in (0<=a&&a<1)&&(0<=b&&b<1)&&(0<=c&&c<1)

Обидві функції gі hзаймають чотири пари, перша з яких - точка, яку слід перевірити на включення, а решта - координати вершин трикутника.

Для тестування на прикладі вибірки:

let trueTestCases =
  [((-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)),
   ((-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)),
   ((0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)),
   ((-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)),
   ((0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)),
   ((-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)),
   ((-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)),
   ((-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)),
   ((0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)),
   ((-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832))]

let falseTestCases =
  [((-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)),
   ((0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)),
   ((0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)),
   ((0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)),
   ((0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)),
   ((-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)),
   ((-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)),
   ((0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)),
   ((0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)),
   ((0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192))]

type Point = (Double, Double)

test :: [(Point, Point, Point, Point)] -> [Bool]
test testCases =
  map (\((px,py),(ax,ay),(bx,by),(cx,cy)) -> h (px,py) (ax,ay) (bx,by) (cx,cy)) testCases

test trueTestCases --> [True,True,True,True,True,True,True,True,True,True]
test falseTestCases --> [False,False,False,False,False,False,False,False,False,False]

Рішення без вогню:

type Point = (Double, Double)

-- using cross products

triangulate' (a, b) (p, q) (r, s) (t, u) =
  (side a b p q r s == side a b r s t u) && (side a b r s t u == side a b t u p q)
  where side j k l m n o = (o - m) * (j - l) + (-n + l) * (k - m) >= 0

-- using barycentric coordinates

triangulate :: (Point, Point, Point, Point) -> Bool
triangulate ((px, py), (ax, ay), (bx, by), (cx, cy)) = 
  let (p'x, p'y) = (px + (-ax), py + (-ay))
      (b'x, b'y) = (bx + (-ax), by + (-ay))
      (c'x, c'y) = (cx + (-ax), cy + (-ay))
      d = b'x * c'y - c'x * b'y
      a = (p'x * (b'y - c'y) + p'y * (c'x - b'x) + b'x * c'y - c'x * b'y) / d
      b = (p'x * c'y - p'y * c'x) / d
      c = (p'y * b'x - p'x * b'y) / d
  in
      (0 <= a && a < 1) && (0 <= b && b < 1) && (0 <= c && c < 1)

2

JavaScript (ES6) 120

C=(p,q,i,j,k,l,m,n,
 z=j*(m-k)+i*(l-n)+k*n-l*m,
 s=(j*m-i*n+(n-j)*p+(i-m)*q)/z,
 t=(i*l-j*k+(j-l)*p+(k-i)*q)/z
)=>s>0&t>0&s+t<1

Безпосередньо скопійовано з моєї відповіді на це інше питання

Тест в консолі FireFox / FireBug

Виведіть всі 1 с

;[
C(-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633),
C(-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468),
C(0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497),
C(-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334),
C(0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028),
C(-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683),
C(-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618),
C(-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374),
C(0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519),
C(-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832)
]

Виведіть усі 0

;[
C(-0.99103, 0.43842,0.78128, -0.10985,-0.84714, -0.20558,-0.08925, -0.78608),
C(0.15087, -0.56212,-0.87374, -0.3787,0.86403, 0.60374,0.01392, 0.84362),
C(0.1114, 0.66496,-0.92633, 0.27408,0.92439, 0.43692,0.8298, -0.29647),
C(0.87786, -0.8594,-0.42283, -0.97999,0.58659, -0.327,-0.22656, 0.80896),
C(0.43525, -0.8923,0.86119, 0.78278,-0.01348, 0.98093,-0.56244, -0.75129),
C(-0.73365, 0.28332,0.63263, 0.17177,-0.38398, -0.43497,-0.31123, 0.73168),
C(-0.57694, -0.87713,-0.93622, 0.89397,0.93117, 0.40775,0.2323, -0.30718),
C(0.91059, 0.75966,0.60118, 0.73186,0.32178, 0.88296,-0.90087, -0.26367),
C(0.3463, -0.89397,0.99108, 0.13557,0.50122, -0.8724,0.43385, 0.00167),
C(0.88121, 0.36469,-0.29829, 0.21429,0.31395, 0.2734,0.43267, -0.78192)
]

2

SmileBASIC, 111 100 символів

DEF T X,Y,A,B,C,D,E,F
Q=9e5GCLS
GTRI(A-X)*Q,Q*(B-Y),Q*(C-X),Q*(D-Y),Q*(E-X),Q*(F-Y)?!!GSPOIT(0,0)END

Намалює трикутник і перевіряє колір пікселя в точці. Трикутник збільшується вгору 99999x і зміщується так, що точка, яку слід перевірити, буде (0,0) перед тим, як намалювати, щоб мінімізувати втрати в точності.


2

Збірка FPU Intel 8087, 222 220 байт

Для розрахунку використовується тільки апаратне забезпечення 8087 FPU. Ось нерозібрана (і в цьому випадку нерозіграна) версія як MACRO (позбавить вас 220 шістнадцяткових байтових кодів):

; calculate the area of of a triangle ABC using determinate
; input: coordinates (float), Ax,Ay,Bx,By,Cx,Cy
; output: area in ST
TAREA   MACRO   A1,A2,B1,B2,C1,C2
    FLD  A1
    FLD  B2
    FLD  C2
    FSUB        ; ST = By - Cy
    FMUL        ; ST = Ax * ( By - Cy )
    FLD  B1 
    FLD  C2
    FLD  A2
    FSUB        ; ST = Cy - Ay
    FMUL        ; ST = Bx * ( Cy - Ay )
    FLD  C1
    FLD  A2
    FLD  B2
    FSUB        ; Ay - By
    FMUL        ; Cx * ( Ay - By )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay ) + Ax * ( By - Cy )
    FLD1        ; make a value of 2
    FADD ST,ST  ; ST = 2
    FDIV        ; divide by 2
    FABS        ; take abs value
        ENDM

; determine if point X is in triangle ABC
; input: points X, A, B, C
; output: ZF=1 if X in triangle, ZF=0 if X not in triangle
TXINABC     MACRO X1,X2,A1,A2,B1,B2,C1,C2

    TAREA  A1,A2,B1,B2,C1,C2    ; ST(3) = area of triangle ABC
    TAREA  X1,X2,B1,B2,C1,C2    ; ST(2) = area of triangle XBC
    TAREA  A1,A2,X1,X2,C1,C2    ; ST(1) = area of triangle AXC
    TAREA  A1,A2,B1,B2,X1,X2    ; ST(0) = area of triangle ABX

    FADD        ; add areas of triangles with point
    FADD        ; ST = ST + ST(1) + ST(2)
    FCOMPP      ; compare ST to ST(1) and pop results
    FWAIT       ; sync CPU/FPU
    FSTSW R     ; store result flags to R
    MOV  AX, R  ; move result to AX
    SAHF        ; store result into CPU flags for conditional check
        ENDM

Пояснення

Використовуйте детермінант для обчислення площі трикутника ABC, а потім трикутник, утворений з точкою X та двох інших точок трикутника ABC. Якщо площа трикутника ABC дорівнює сумі площ трикутників XBC + AXC + ABX, то точка знаходиться в межах трикутника. Результат повертається як ZF.

Що в цьому акуратно

Всі операції з математики та плаваючої крапки виконуються апаратно з 80-бітовою розширеною точністю. Кінцеве порівняння з плаваючою комою також проводиться в апаратному забезпеченні, тому буде дуже точним.

Тут також використовуються одразу всі вісім регістрів стеків 8087.

Що в цьому не зовсім охайно

Оскільки точки трикутника необхідно підключати до формул кілька разів під час обчислення, для цього потрібно, щоб кожна змінна пам'ять була завантажена в регістри стеків FPU по черзі в правильному порядку. Хоча це може бути досить легко моделюватися як функція як MACRO, це означає, що код розширюється щоразу при складанні, створюючи надмірний код. 41 байт було збережено, перемістивши одні і ті ж повторювані сегменти коду в PROC. Однак він робить код менш читабельним, тому вищевказаний перелік є без нього (саме тому він позначений як "необроблений").

Тести

Ось програма тестування з використанням IBM DOS, що показує вихід:

TTEST   MACRO T
        LOCAL IS_IN_TRI

    TXINABC T,T+4*1,T+4*2,T+4*3,T+4*4,T+4*5,T+4*6,T+4*7
    MOV  DX, OFFSET TEQ     ; load true string by default 
    JZ   IS_IN_TRI          ; if ZF=1, it is in triangle, skip to display
    MOV  DX, OFFSET FEQ     ; otherwise ZF=0 means not in triangle, so load false string
IS_IN_TRI:
    MOV  AH, 9              ; DOS write string function
    INT  21H 
        ENDM

START:
    FINIT                   ; reset 8087

    TTEST   T0              ; true tests
    TTEST   T1
    TTEST   T2
    TTEST   T3
    TTEST   T4
    TTEST   T5
    TTEST   T6
    TTEST   T7
    TTEST   T8
    TTEST   T9

    TTEST   F0              ; false tests
    TTEST   F1
    TTEST   F2
    TTEST   F3
    TTEST   F4
    TTEST   F5
    TTEST   F6  
    TTEST   F7
    TTEST   F8  
    TTEST   F9

    RET         ; return to DOS

T0  DD  -0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633
T1  DD  -0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468
T2  DD  0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497
T3  DD  -0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334
T4  DD  0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028
T5  DD  -0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683
T6  DD  -0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618
T7  DD  -0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374
T8  DD  0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519
T9  DD  -0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832

F0  DD  -0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608
F1  DD  0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362
F2  DD  0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647
F3  DD  0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896
F4  DD  0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129
F5  DD  -0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168
F6  DD  -0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718
F7  DD  0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367
F8  DD  0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167
F9  DD  0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192

TEQ DB 'In Triangle',0DH,0AH,'$'
FEQ DB 'Not In Triangle',0DH,0AH,'$'

Вихідні дані

In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle

1

C 414 (було 465)

Гольф

#define D double 
int F(D ax,D ay,D bx,D by,D cx,D cy,D px,D py){int y=0;double J,K;D m=(ax-bx<0.001)?(by-ay)/(ax-bx):1000;D b=m*ax+ay;J=m*cx-cy+b;K=m*px-py+b;if(J*K>=0)y=1;return y;}D T[8],k;int i,n;void G(){while(i<8){scanf("%lf",&k);T[i++]=k;}n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);printf(n==3?"True":"False");}

Для пояснення додано оригінальну декларацію функції

/**
* determine if points C & P are on same side of line AB
* return 1 if true, 0 otherwise
*/
int PointsSameSide(D ax,D ay,D bx,D by,D cx, D cy, D px, D py);

Переписано як іменовану функцію: введіть через stdin один кожен рядок або всі в одному рядку, розділеному пробілом.

#define D double
int F(D ax,D ay,D bx,D by,D cx, D cy, D px, D py)
{
int y=0;
double J,K;
D m = (ax-bx<0.001)?(by-ay)/(ax-bx):1000;
D b = m*ax+ay;
J=m*cx-cy+b;
K=m*px-py+b;
if(J*K>=0)y=1;
return y;
}
double T[8],k;
int i,n;
void G()
{
while(i<8){scanf("%lf",&k);T[i++]=k;}
n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);
n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);
n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);
printf(n==3?"True":"False");
}

3
Ви можете зберегти кілька байт, позбувшись нових рядків та зайвих пробілів. Крім того, ви doubleпереробили як, Dале ви все ще використовуєте doubleв коді.
gronostaj

1

Java, 149 символів

g=Math.atan2(100*(d-y),(a-x));h=Math.atan2(100*(e-y),(b-x));i=Math.atan2(100*(f-y),(c-x));k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;

Жахливо враховуючи, що я повинен написати "Математику". кожного разу. Це фактична програма:

package mathPackage;
public class InTriangle {
public static void main(String[] args) {
    boolean k;
    double a=-1,b=0,c=1,d=0,e=1,f=0,x=0,y=0.4;
    double g,h,i;
    g=Math.atan2(100*(d-y),(a-x));
    h=Math.atan2(100*(e-y),(b-x));
    i=Math.atan2(100*(f-y),(c-x));
    k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;
    System.out.println(k);
    System.out.println(g);
    System.out.println(h);
    System.out.println(i);
    System.out.print(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g));
}
}

де a - x точки a, b - x точки b, c для x of c, d є y a, e є y b, f - y з c, а x і y - x і y точки. Булева k визначає, правда це чи ні.


1
Для чого такі 100*?
xnor

1

JavaScript 125/198

Якщо бали подано у 8 аргументах:

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Якщо точки надаються у двовимірному масиві:

function c(s){return (z(s[1][0],s[1][1],s[2][0],s[2][1])+z(s[2][0],s[2][1],s[3][0],s[3][1])+z(s[3][0],s[3][1],s[1][0],s[1][1]))%3<1;function z(a,b,c,d){return (s[0][1]-b)*(c-a)-(s[0][0]-a)*(d-b)>0}}

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

(y-b)(c-a) - (x-a)(d-b)

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

            m = (y2-y1)/(x2-x1)
      (y2-y1) = m(x2-x1)
       (y-y1) = m(x-x1)     ,substituting point we are testing (x,y) to be the 2nd point
       (y-y1) = (x-x1)(y2-y1)/(x2-x1)  ,substitute back the original definition of m
(y-y1)(x2-x1) = (x-x1)(y2-y1)    <-- left side will be greater than the right side, if
                                     the point is on the left; otherwise, it's on the right
            0 = (y-b)(c-a)-(x-a)(d-b) ,where (a,b)=(x1,y1), (c,d)=(x2,y2)

Якщо ми перевіримо всі 3 сторони, всі 3 повинні отримати деякі числа з однаковим знаком лише тоді, коли точка знаходиться всередині трикутника, оскільки ми тестуємо її навколо трикутника. Якщо точка знаходиться збоку, один із тестів повинен повернути 0.

Код тесту jsFiddle: http://jsfiddle.net/DerekL/zEzZU/

var l = [[-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633],[-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468],[0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497],[-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334],[0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028],[-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683],[-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618],[-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374],[0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519],[-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832],
         [-0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608],[0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362],[0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647],[0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896],[0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129],[-0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168],[-0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718],[0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367],[0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167],[0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192]];

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

for(var i = 0; i < l.length; i++){
    console.log(d.apply(undefined,l[i]));    //10 true, 10 false
}

97 символів (не рахуючи пробілів чи вкладок) підраховуються при перетворенні в CoffeeScript:

d=(x,y,a,b,c,d,e,f)->
    z=(a,b,c,d)->
        (y-b)*(c-a)-(x-a)*(d-b)>0
    (z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1

115 символів при перетворенні в ES6:

d=(x,y,a,b,c,d,e,f)=>{z=(a,b,c,d)=>{return (y-b)*(c-a)-(x-a)*(d-b)>0};return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Те є «фантазія вектор математика» Я використовую: D (нє фантазії барицентричних координат наближаються деякими інші взяли, хоча). Як і відповідь у верхній частині голосу, ви можете зберегти кілька байтів, використовуючи ES6 та визначивши такі функції d=(x,y,...)=>{...}. У вашому випадку ви можете заощадити ще більше, скориставшись CoffeeScript, який не потребує return: pastebin.com/RVFk1D5k ..., і в будь-якому випадку ви можете зберегти один байт, використовуючи <1замість ==0.
Мартін Ендер

@ m.buettner: o Я вважав, що використовуване рівняння не має нічого спільного з векторами (похідними від простої алгебри), але, мабуть, вони мають одне і те ж рівняння. Математика чудова.
Дерек 朕 會 功夫

1

R, 23

Натхненний MATLAB ,

SDMTools::pnt.in.poly()

називається як, SDMTools::pnt.in.poly(point,triangle)де pointвектор довжини-2 і triangleє матрицею 3x2 вершин. SDMTools доступний на CRAN.


1

Математика, 38 символів

RegionMember[Polygon[#[[1]]],#[[2]]] &

Приклад:

d = {{{0, 0}, {1, 0}, {.5, .7}}, {.5, .6}};

RegionMember[Polygon[#[[1]]], #[[2]]] & @ d

(* Правда *)


Стандартно рахувати пробіли як символи, але, мабуть, тут ви можете їх видалити, нічого не порушивши.
xnor

1
Крім того, вам потрібно брати дані та отримувати вихід, а не використовувати попередньо визначені змінні. Ви можете шукати деякі відповіді Mathematica, щоб побачити, як вони це роблять.
xnor

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