Kiểm tra nếu điểm nằm trong tam giác


40

Mục tiêu của bạn là xác định xem một điểm 2D X đã cho có nằm trong diện tích của tam giác với các đỉnh A, B, C đã cho hay không.

Viết hàm lấy tọa độ của điểm kiểm tra X và ba đỉnh tam giác (sao cho tổng 8 tọa độ) và trả về True nếu điểm nằm bên trong tam giác đó và Sai nếu nằm bên ngoài.

Đừng lo lắng về các trường hợp cạnh. Nếu điểm nằm trên đường biên của tam giác (cạnh hoặc đỉnh) hoặc tam giác thực sự là một đoạn thẳng, mã của bạn có thể làm bất cứ điều gì, bao gồm cả sự cố. Cũng đừng lo lắng về độ ổn định số hoặc độ chính xác của dấu phẩy động.

Mã của bạn phải là một hàm được đặt tên. Đoạn mã sẽ không được chấp nhận.

Ít nhân vật nhất chiến thắng.

Đầu vào:

Tám số thực biểu thị tọa độ. Các con số sẽ nằm trong phạm vi (-1,1).

Các định dạng đầu vào chính xác là linh hoạt. Ví dụ, bạn có thể lấy tám số, một danh sách tám số, một danh sách bốn điểm được đưa ra bởi một tuple, ma trận 2 * 4, bốn số phức, hai danh sách tọa độ x và tọa độ y, vân vân

Đầu vào chỉ cần là các số trong một số container, không có dữ liệu bổ sung. Bạn không thể sử dụng đầu vào để thực hiện bất kỳ quá trình tiền xử lý nào, bạn cũng không thể yêu cầu bất kỳ ràng buộc nào đối với đầu vào, chẳng hạn như yêu cầu các điểm được đưa ra theo tọa độ y tăng dần. Đầu vào của bạn phải cho phép tám tọa độ bất kỳ (mặc dù mã của bạn có thể hoạt động tùy ý trong các trường hợp cạnh được đề cập trước đó).

Vui lòng cho biết định dạng đầu vào của bạn.

Đầu ra:

Hoặc Boolean tương ứng True/ False, số tương ứng 1/ 0hoặc tương tự trong ngôn ngữ của bạn.

Các trường hợp thử nghiệm

Các đầu vào được đưa ra một danh sách [X,A,B,C]gồm bốn bộ dữ liệu, điểm kiểm tra đầu tiên, sau đó là ba đỉnh tam giác. Tôi đã nhóm chúng thành những người có đầu ra nên Truevà những người nên có False.

True trường hợp:

[(-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 trường hợp:

[(-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)]

Định nghĩa của bạn về một nhân vật là gì? Ái chà? Có thể mã hóa trong 7 bit? Trong một byte? Bất kỳ Unicode?
isaacg

Bạn có đề nghị gì? Đã có giải pháp sử dụng mã nén.
xnor

Thông thường, tôi tin rằng các byte được sử dụng cho các ký tự không phải là chữ Asii, vì nếu không thì lợi thế của Utf-32 là không thể vượt qua.
isaacg

Chà, tôi không thể quay lại bây giờ; bất kỳ ký tự Unicode nào cũng là một ký tự. Nén nếu bạn muốn.
xnor

Câu trả lời:


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}

Phiên bản ECMAScript 6 (cảm ơn m.buettner, lưu 6 ký tự)

$=(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}

Gọi nó là như vậy (trả về truehoặc false):

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

Sử dụng một số phép toán tọa độ barycentric lạ mắt dựa trên mã từ câu trả lời này . Một phiên bản không phù hợp cho bạn thưởng thức đọc sau:

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, nếu chỉ cho các tên tham số!
Matt

Tại sao bạn phải phá vỡ UserScript đếm ký tự của tôi ???
kitcar2000

@ kitcar2000 có nghĩa là gì?
Áp-ra-ham

Các quy tắc nói rằng các ký tự được tính, không phải byte. Vì vậy, bạn có thể sử dụng điều này: xem.github.io/obfuscatweet để phù hợp với 122 ký tự
xem

1
Tôi đã nhầm, hoặc bạn có thể đã sử dụng (a*(l-n)+i*(g-e)+n*e-g*l)thay vì (-g*l+a*(-n+l)+i*(g-e)+n*e)?
Zacharý

19

Con trăn 2.7 128 127 117 110 109 103 99 95 94 91 90

Nỗ lực chơi gôn đầu tiên của tôi!

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

Lấy làm đầu vào (x, y, t) trong đó (x, y) là điểm chúng tôi đang kiểm tra và t là tam giác t = ((x1, y1), (x2, y2), (x3, y3)).

Giải trình

Tôi đang tính các yếu tố quyết định của ma trận

| 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  |

Các xác định này biểu thị khoảng cách đã ký từ các cạnh của tam giác đến điểm (x, y). Nếu tất cả chúng đều có cùng một dấu, thì điểm nằm ở cùng một phía của mọi đường và do đó được chứa trong tam giác.

Trong đoạn mã trên, a*y+c*b+d*x-d*a-c*y-b*xlà một yếu tố quyết định của một trong những ma trận này.

Tôi đang sử dụng thực tế đó True+True+True==3False+False+False==0để xác định xem tất cả các yếu tố quyết định này có cùng một dấu hiệu hay không.

Tôi sử dụng các chỉ mục danh sách phủ định của Python bằng cách sử dụng t[-1]thay vì t[(i+1)%3].

Cảm ơn Peter về ý tưởng sử dụng s%3<1thay vì s in(0,3)kiểm tra xem s là 0 hay 3!

Phiên bản Sagemath

Không thực sự là một giải pháp khác vì vậy tôi đưa nó vào câu trả lời này, một giải pháp sagemath sử dụng 80 ký tự:

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

ở đâu p=[x,y]t=[[x1,y1],[x2,y2],[x3,y3]]


1
s in (0,3)thể rút ngắn thành s%3<1?
Peter Taylor

1
Việc sử dụng các chỉ số tiêu cực có thể được điều chỉnh để tiết kiệm thêm một lần nữa: -1,0,1 ... t[i]+t[i+1]tương đương với0,1,2 ... t[i-1]+t[i]
Peter Taylor

@PeterTaylor Hoàn toàn đúng! Quá tệ, tôi đã loại bỏ không gian trong in -1,0,1trước khi đọc này. Trên thực tế, cách của bạn dễ đọc hơn vì vậy tôi sẽ sử dụng nó.
Alex L

1
Chào mừng bạn đến với mã golf! Bạn có thể thoát khỏi dấu ngoặc vuông để hiểu danh sách bên trong sumnếu bạn đặt 0,1,2dấu ngoặc đơn, trong trường hợp một ký tự bằng cách thay thế khoảng trắng. Lý do là Python cho phép sự hiểu biết không được chấp nhận được truyền vào các hàm, nhưng dấu phẩy trong bộ dữ liệu trần trụi làm 1,2,3nó bối rối vì nó cố phân tích chúng thành các đối số riêng biệt.
xnor

16

Toán học, 67 byte

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

Hàm này có hai đối số, điểm Xvà danh sách các điểm {A,B,C}, được gọi là ##2tương ứng. Đó là nếu bạn gọi

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

sau đó bạn sẽ nhận được #như X#2như {A,B,C}. (Lưu ý rằng có hai hàm ẩn danh khác được lồng bên trong mã - ##2có ý nghĩa khác nhau trong các hàm đó.)

Dưới đây là một lời giải thích về chức năng:

                                              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. *)

Lưu ý rằng hàm này sẽ thực sự hoạt động đối với mọi n-gon lồi miễn là các đỉnh của nó được đưa ra theo thứ tự chiều kim đồng hồ hoặc ngược chiều kim đồng hồ.


Sẽ không hiệu quả hơn nếu kiểm tra xem sản phẩm của khoảng cách có dương hay không nếu tất cả các dấu hiệu đều bằng nhau? Tôi không Mathicala, nhưng có vẻ như điều đó sẽ dễ dàng hơn.
isaacg

@isaacg Có ba thuật ngữ, vì vậy nếu tất cả đều âm, sản phẩm của họ là âm và nếu tất cả đều dương, sản phẩm của họ là dương. Cách tiếp cận của bạn chỉ hoạt động nếu dấu của hai số bằng nhau.
Martin Ender

Tại sao không sử dụng Det?
alephalpha

@alephalpha Vâng, chủ yếu là vì tôi đã không nghĩ về nó. : P ... Tôi sẽ xem xét điều đó
Martin Ender

@alephalpha Hừ không, tôi không thể tìm ra cách ngay bây giờ để xây dựng ba ma trận cần thiết với ít ký tự hơn.
Martin Ender

7

CJam, 66 63 59 52 46 34 32 31 30 28 ký tự

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

Sau khi chuyển đổi chuỗi Unicode, mã sau ( 33 byte ) sẽ được đánh giá:

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

Dự kiến X [A B C]là đầu vào, trong đó mỗi điểm có dạng [double double]. Đầu ra là 1 hoặc 0.

Hãy thử trực tuyến.

Xin chân thành cảm ơn bạn đã đến user23013 vì đã lưu 6 ký tự (13 byte mã không nén)!

Các trường hợp thử nghiệm

$ 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]

Đó có phải là một chức năng được đặt tên?
Martin Ender

@ m.buettner: Sắp xếp. Các wiki chính thức cho biết như sau: Block - một phần chương trình giới hạn bởi {}và điều trị như một đơn vị duy nhất. Tương tự như các khối mã trong C / java, ngoại trừ các khối là các đối tượng hạng nhất và có thể được gán cho các biến (do đó xác định các hàm).
Dennis

1
@xnor 1m<@m*chuẩn bị 3 cặp X và i+1đỉnh ( th) tiếp theo của tam giác. @-@@-di chuyển đỉnh hiện tại ( ith) sang gốc (và được nhân đôi nếu không @-\@-, nhưng nó không thành vấn đề). @@*@@*>tính toán trục z của sản phẩm chéo, hay còn gọi là định thức và trả về 1nếu nó âm. :+3%!trả về cho dù tất cả đều giống nhau, nghĩa là cả 3 đều âm hoặc không âm, có nghĩa là dương trừ các trường hợp cạnh. Tôi nghĩ rằng việc đọc CJam khó hơn chơi golf.
jimmy23013

1
37 byte : {[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T. Sử dụng 2m>hoặc Wm<cho an toàn Unicode.
jimmy23013

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

5

C - 156 byte

Đầu vào là mảng 3 phao trong X, 3 phao trong Y và x và y riêng cho điểm kiểm tra. Tiền thưởng: xử lý tất cả các trường hợp cạnh!

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;}

Chuyển thể từ 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 - đã thử nghiệm trong javascript
bebe

@bebe - Điều đó gây ra lỗi cú pháp.
Derek 朕 會

Điều đó không gây ra lỗi cú pháp.
bebe

4

Bình 1.0,5 , 57 54 51

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

Xác định hàm g, có hai đầu vào: điểm kiểm tra và sau đó là danh sách các đỉnh của tam giác. Đầu ra TrueFalse. Lưu ý: Phá hủy đầu vào, cụ thể là b, danh sách các đỉnh của tam giác.

Hãy thử nó ở đây . Một vài ký tự cuối cùng, gvwvwgọi hàm với một trường hợp thử nghiệm trên hai dòng tiếp theo.

Dựa trên thuật toán này

Giải trình:

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)

Cuộc chiến của CJam - Pyth nổi giận!


Đây phải là một chức năng được đặt tên. Là wlấy đầu vào STDIN?
xnor

@xnor Rất tiếc, tôi đã bỏ lỡ phần mô tả đó. Sẽ chỉnh sửa.
isaacg

@xnor Các chức năng in ra câu trả lời được phép hay chúng phải trả về câu trả lời? Hiện tại, điều này in ra câu trả lời, nhưng tôi có thể trả lại cho một nhân vật nữa.
isaacg

Trả lời câu trả lời.
xnor

Có lẽ bạn có thể lưu các ký tự bằng cách thay thế bộ đếm Zbằng một bộ trống mà bạn tích lũy Z|=, sau đó kiểm tra độ dài của nó để xem nếu chỉ 0hoặc 1được nhìn thấy? Chiến lược hóa ra lâu hơn trong Python, nhưng có lẽ nó đáng để sử dụng nguyên thủy Pyth.
xnor

4

J 64 45 (42 không có nhiệm vụ)

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

Việc gán không cần thiết cho một thứ là một hàm, vì vậy không chắc có nên đếm nó hay không. Tận dụng lợi thế của đầu vào linh hoạt: Tôi muốn có một mảng (1 + số đỉnh) x (chiều của không gian).

Hy vọng sẽ ghi được một số điểm bổ sung ở đây ...: Điều này hoạt động cho bất kỳ kích thước nào của Simplex, không chỉ là hình tam giác trong một mặt phẳng, mà còn là một kim tự tháp 3 mặt trong không gian 3d, v.v. Nó cũng hoạt động khi số đỉnh của đơn giản nhỏ hơn (n + 1), sau đó nó tính toán xem hình chiếu của điểm lên đơn giản có ở bên trong hay không.

Nó chuyển đổi sang tọa độ barycentric , sau đó kiểm tra các điểm âm, cho biết điểm nằm ngoài. Do tâm J sử dụng _ cho phủ định

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

Chạy trên các ví dụ đã cho:

   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

Tôi yêu cầu một chức năng được đặt tên, vì vậy các ký tự gán. Dưới đây là một số điểm để khái quát cho đa giác! · //////////
xnor

Chà, thực ra, tôi không khái quát hóa cho đa giác, mà là các đơn giản N chiều, với N+1các đỉnh cực đại . Ví dụ, một kim tự tháp 4 đỉnh trong không gian 3 chiều hoặc đơn giản 5 đỉnh trong không gian 4 chiều. Số lượng đỉnh có thể thấp hơn N+1, trong trường hợp đó, thuật toán sẽ xem liệu phép chiếu trực giao lên siêu phẳng có đơn giản nằm trong đơn giản hay không (ví dụ đơn giản 2 điểm trong 2-D sẽ được chiếu trên đường thẳng và được kiểm tra liệu phép chiếu này nằm giữa các điểm cuối)
jpjacobs

4

HTML5 + JS, 13b + 146b / 141b / 114 ký tự

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]}

hoặc 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]}

hoặc ES6 unicode-obfuscated (114 ký tự):

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

bản demo: http://jsfiddle.net/xH8mV/

Giải mã Unicode được thực hiện với: http://xem.github.io/obfuscatweet/


Nó dường như không mang lại kết quả chính xác khi điểm nằm sát bên: jsfiddle.net/L2B2A Tôi tin rằng điều này là do tất cả các đầu vào nằm trong khoảng (-1,1) và mã của bạn chỉ kiểm tra 4 pixel xung quanh nguồn gốc.
Derek 朕 會

đúng vậy, để phù hợp với các ví dụ, tôi nên thay đổi nguồn gốc và tỷ lệ khung vẽ của mình để xử lý các hình tam giác bên trong [-1,1]. Nhưng tại sao những hình tam giác đó lại nhỏ đến vậy?
xem

vấn đề nói rằng tất cả xy nằm trong khoảng -1 đến 1. Không thực sự biết tại sao, nhưng tôi tin rằng bạn chỉ có thể nhân mọi đầu vào với 1e7 (để duy trì độ chính xác) có thể nhận được kết quả chính xác: D
Derek 會

Một giải pháp đồ họa, rất thông minh!
xnor

3

Con trăn (65)

Mọi người dường như đã hoàn thành việc gửi, vì vậy tôi sẽ đăng giải pháp của riêng mình cho câu hỏi của tôi.

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

Xlà số phức biểu thị các điểm kiểm tra và Llà danh sách ba điểm, mỗi điểm là một số phức.

Đầu tiên, tôi sẽ giải thích một phiên bản ít mã hơn của mã;

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)

Chúng tôi thay đổi các điểm A,B,C,Xsao cho Xcó nguồn gốc, tận dụng lợi thế của số học phức tạp tích hợp sẵn của Python. Chúng ta cần kiểm tra xem nguồn gốc có được chứa trong thân lồi không A,B,C. Điều này tương đương với nguồn gốc luôn nằm cùng phía (trái hoặc phải) của các đoạn thẳng AB, BC và AC.

Một đoạn ABcó gốc ở bên trái nếu một người đi ngược chiều kim đồng hồ dưới 180 độ để đi từ A đến B, và bên phải thì ngược lại. Nếu chúng ta xem xét các góc a, bctương ứng với các điểm, phương tiện này b-a < 180 degrees(lấy góc độ trong khoảng từ 0 đến 360 độ). Là số phức , angle(B/A)=angle(B)/angle(A). Ngoài ra, angle(x) < 180 degreeschính xác cho điểm trong nửa mặt phẳng trên, mà chúng tôi kiểm tra thông qua imag(x)>0.

Vì vậy, liệu gốc tọa độ nằm bên trái của AB được thể hiện là (A/B).imag>0. Kiểm tra xem tất cả có bằng nhau cho mỗi cặp tuần hoàn A,B,Ccho chúng ta biết tam giác ABCcó chứa gốc hay không.

Bây giờ, hãy trở lại mã được chơi đầy đủ

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

Chúng tôi tạo từng cặp theo chu kỳ (A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X), tận dụng các chỉ số danh sách Python âm bao quanh ( L[-1]= L[2]). Để kiểm tra xem Bools là tất cả True( 1) hay all False( 0), chúng tôi thêm chúng và kiểm tra tính chia hết cho 3, như nhiều giải pháp đã làm.


2

Pháo đài - 232 218 195 174

Máu kinh khủng. Hàm này rất tệ vì yêu cầu dữ liệu được truyền đến nó và chúng ta không thể xử lý trước.

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

Việc giảm 14 ký tự là do tôi quên đánh golf tên hàm từ các lần chạy thử. Việc giảm thêm là do gõ ngầm và quên thay đổi tên hàm. 20 ký tự tiếp theo xuất hiện do đọc trong các điểm dưới dạng một mảng. Chương trình đầy đủ là

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
Bạn có thể làm điều này ngắn hơn một chút bằng cách dựa vào kiểu gõ ngầm của Fortran và sử dụng một mảng đầu vào duy nhất chứa tất cả 8 số: 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);endTôi đã thử rút ngắn điều này hơn nữa bằng cách sử dụng các thao tác danh sách, nhưng thật không may là nó không hoạt động tốt.
Ventero

1
Thậm chí ngắn hơn bằng cách loại bỏ các biểu hiện phụ phổ biến hơn: 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);endTôi hy vọng tôi đã không phạm phải bất kỳ sai lầm nào trong các biến đổi! Mặc dù có vẻ như mã ban đầu của bạn không vượt qua tất cả các testcase.
Ventero

@Ventero: Tôi không thể tin rằng tôi đã quên lạm dụng việc gõ ngầm :(. Cảm ơn vì sự giúp đỡ của bạn!
Kyle Kanos

@Ventero: Ngoài ra, có vẻ như câu trả lời của tôi phụ thuộc vào hướng của tam giác. TrueVí dụ đầu tiên trong OP đưa ra Falsenếu tôi trao đổi BCcác giá trị trong khi đưa ra Truecho hướng ban đầu.
Kyle Kanos

Ah, thực sự, vấn đề được gây ra khi (sử dụng lại ký hiệu từ nhận xét trước của tôi) a < 0, điều này có hiệu quả đảo ngược điều kiện bạn phải kiểm tra. Thật không may, điều này không thể được khắc phục bằng cách gói mọi thứ trong một abs, khi đó điều kiện ngụ ý bdcó cùng dấu hiệu abị mất. Điều này có thể được khắc phục bằng cách sử dụng một cái gì đó như (một lần nữa, sử dụng lại các ký hiệu và các biến được xác định trước từ nhận xét cuối cùng của tôi) 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)- có thể có thể được đánh gôn nhiều hơn.
Ventero

2

MATLAB: 9!

Không có nhiều tôi viết ở đây

inpolygon

Có thể gọi như vậy:

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

Đầu ra được gán cho một biến có tên ans


Nếu tôi thực sự phải viết một hàm, nó có thể giống như vậy, có thể được tối ưu hóa:

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

2
có thể ngắn hơn bằng cách sử dụng một hàm xử lý: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]);}

Có lẽ không hiệu quả bằng ký tự như một phương pháp toán học, nhưng đó là cách sử dụng thư viện thú vị. Ngẫu nhiên, cũng khá chậm.

Đồng thời tận dụng "Cũng đừng lo lắng về độ ổn định số hoặc độ chính xác của dấu phẩy động". - thật không may, GraphicsPathsử dụng ints bên trong, do đó, một giá trị trong phạm vi -1 <f <1 chỉ có thể có ba giá trị có thể. Vì phao chỉ có 7 chữ số chính xác, tôi chỉ cần nhân với 1e7 để biến chúng thành số nguyên. Hừm, tôi đoán nó không thực sự mất bất kỳ độ chính xác nào. Nó cũng có thể khai thác theo một cách khác: tôi có thể đã lợi dụng việc bỏ qua độ chính xác và chỉ đưa ra câu trả lời "sai".

Nếu tôi được phép bỏ qua chi phí nhân vật của việc nhập các thư viện, 149 (ít nhất, System.LinqSystem.Drawinglà tiêu chuẩn khá trên hầu hết các dự án WinForms, nhưng System.Drawing.Drawing2Dcó thể hơi khó khăn):

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]);}

Chương trình thử nghiệm (yea, nó xấu xí):

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]);
    }
}

Dễ thương, có được công cụ vẽ để làm việc.
xnor

2

Haskell - 233 127

Sử dụng các sản phẩm chéo như được mô tả ở đây :

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

Giải pháp trước đó được triển khai bằng tọa độ nhị phân và các công thức được mô tả trong câu trả lời Stack Exchange này :

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)

Cả hai hàm ghlấy bốn cặp, cặp đầu tiên là điểm cần kiểm tra để đưa vào và phần còn lại là tọa độ của các đỉnh của tam giác.

Để kiểm tra với đầu vào mẫu:

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]

Giải pháp không cần thiết:

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

Sao chép trực tiếp từ câu trả lời của tôi cho câu hỏi khác này

Kiểm tra trong bảng điều khiển FireFox / FireBug

Đầu ra tất cả 1 giây

;[
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)
]

Xuất tất cả 0 giây

;[
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 ký tự

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

Vẽ một hình tam giác và kiểm tra màu của pixel tại điểm. Hình tam giác được tăng lên 99999x và được dịch chuyển sao cho điểm cần kiểm tra sẽ ở (0,0) trước khi được vẽ, để giảm thiểu độ chính xác.


2

Lắp ráp Intel 8087 FPU, 222 220 byte

Chỉ sử dụng phần cứng 8087 FPU để tính toán. Đây là phiên bản chưa được lắp ráp (không được xử lý trong trường hợp này) dưới dạng MACRO (sẽ cung cấp cho bạn mã 220 byte byte):

; 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

Giải trình

Sử dụng xác định để tính diện tích của tam giác ABC, và sau đó tam giác được hình thành với điểm X và hai điểm khác của tam giác ABC. Nếu diện tích tam giác ABC bằng tổng diện tích các tam giác XBC + AXC + ABX, thì điểm nằm trong tam giác. Kết quả được trả về là ZF.

Có gì gọn gàng về điều này

Tất cả các phép toán và dấu phẩy động được thực hiện trong phần cứng với độ chính xác mở rộng 80 bit. Việc so sánh dấu phẩy động cuối cùng cũng được thực hiện trong phần cứng nên sẽ rất chính xác.

Điều này cũng sử dụng tất cả tám trong số các thanh ghi ngăn xếp của 8087 cùng một lúc.

Điều gì không hoàn toàn gọn gàng về điều này

Vì các điểm của tam giác phải được cắm lại vào các công thức nhiều lần trong quá trình tính toán, nên nó yêu cầu mỗi biến trong bộ nhớ được nạp vào ngăn xếp của FPU đăng ký một lần theo đúng thứ tự. Mặc dù điều này có thể được mô hình hóa khá dễ dàng giống như một chức năng như MACRO, điều đó có nghĩa là mã được mở rộng mỗi lần lắp ráp, tạo mã dự phòng. 41 byte đã được lưu bằng cách di chuyển một số đoạn mã lặp lại tương tự vào PROC. Tuy nhiên, nó làm cho mã ít dễ đọc hơn, vì vậy danh sách trên không có mã này (đó là lý do tại sao nó được gắn nhãn là "không được mã hóa").

Xét nghiệm

Đây là một chương trình thử nghiệm sử dụng IBM DOS hiển thị đầu ra:

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,'$'

Đầu ra

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 (là 465)

Chơi gôn

#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");}

Khai báo hàm gốc được thêm vào để giải thích

/**
* 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);

Viết lại dưới dạng một hàm được đặt tên: nhập qua stdin một dòng hoặc tất cả trong một dòng được phân tách bằng dấu cách.

#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
Bạn có thể lưu một số byte bằng cách loại bỏ các dòng mới và không gian không cần thiết. Ngoài ra, bạn đã doublexác định lại là Dnhưng bạn vẫn sử dụng doubletrong mã.
gronostaj

1

Java, 149 ký tự

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;

Kinh khủng khi xem xét tôi phải viết "Toán học." mỗi lần. Đây là chương trình thực tế:

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));
}
}

Trong đó a là x của điểm a, b là x của điểm b, c với x của c, d là y của a, e là y của b, f là y của c, và x và y là x và y của điểm. Boolean k xác định xem nó có đúng hay không.


1
Những gì 100*cho?
xnor

1

JavaScript 125/198

Nếu các điểm được cung cấp trong 8 đối số:

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}

Nếu các điểm được cung cấp trong một mảng 2 chiều:

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}}

Mã này không sử dụng bất kỳ toán học vectơ ưa thích nào. Thay vào đó, nó chỉ sử dụng một mẹo đại số đơn giản để xác định xem điểm có nằm trong tam giác hay không. Công thức:

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

cho biết điểm nằm ở phía nào của đường thẳng , bắt nguồn từ việc sắp xếp lại định nghĩa về độ dốc:

            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)

Nếu chúng ta kiểm tra cả 3 cạnh, cả 3 sẽ chỉ mang lại một số số có cùng dấu chỉ khi điểm nằm trong tam giác vì chúng ta đang kiểm tra nó quanh tam giác. Nếu điểm nằm ở một bên thì một trong các bài kiểm tra sẽ trả về 0.

mã kiểm tra 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 ký tự (không tính khoảng trắng hoặc tab) sẽ được tính nếu được chuyển đổi thành 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 ký tự nếu được chuyển đổi thành 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}

Đó "toán học vectơ ưa thích" mà tôi đang sử dụng: D (mặc dù không phải là phương pháp phối hợp barycentric ưa thích mà một số người khác đã thực hiện). Giống như câu trả lời được bình chọn hàng đầu, bạn có thể lưu một vài byte bằng cách sử dụng ES6 và xác định các hàm như thế nào d=(x,y,...)=>{...}. Trong trường hợp của bạn, bạn có thể tiết kiệm nhiều hơn bằng cách sử dụng CoffeeScript, thứ không cần return: pastebin.com/RVFk1D5k ... và trong mọi trường hợp bạn có thể lưu một byte bằng cách sử dụng <1thay vì ==0.
Martin Ender

@ m.buettner: o Tôi nghĩ phương trình tôi đã sử dụng không liên quan gì đến vectơ (xuất phát từ đại số đơn giản) nhưng rõ ràng cả hai đều cho cùng một phương trình. Toán học thật tuyệt vời.
Derek 朕 會

1

R, 23

Lấy cảm hứng từ MATLAB ,

SDMTools::pnt.in.poly()

được gọi như SDMTools::pnt.in.poly(point,triangle)nơi pointlà một vectơ có độ dài 2 và trianglelà ma trận 3x2 của các đỉnh. SDMTools có sẵn trên CRAN.


1

Toán học, 38 ký tự

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

Thí dụ:

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

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

(* Thật *)


Đó là tiêu chuẩn để đếm không gian dưới dạng ký tự, nhưng có lẽ ở đây bạn có thể xóa chúng mà không có gì phá vỡ.
xnor

1
Ngoài ra, bạn cần lấy đầu vào và tạo đầu ra thay vì sử dụng các biến được xác định trước. Bạn có thể tìm kiếm một số câu trả lời Mathicala để xem cách họ làm điều đó.
xnor

0

C (gcc) , 108 byte

i;f(a,b,c,d,e,f,g,h)float a,b,c,d,e,f,g,h;{i=(e-=a)*(h-=b)>(f-=b)*(g-=a);i=(c-=a)*f>(d-=b)*e==i&i==g*d>h*c;}

Hãy thử trực tuyến!

Lấy ba sản phẩm chéo và trả lại 1nếu dấu hiệu của thành phần không thay đổi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.