จุดในเรือนูน (2D)


10

พื้นหลัง

เปลือกนูนของจำนวน จำกัด ของจุดที่เป็นที่เล็กที่สุดนูนรูปหลายเหลี่ยมที่มีทุกจุดไม่ว่าจะเป็นจุดหรือในการตกแต่งภายใน สำหรับข้อมูลเพิ่มเติมโปรดดูที่นี้คำถามเกี่ยวกับ PGM ซึ่งกำหนดได้เป็นอย่างดี

อินพุต

N+1พิกัด 2-D ( N >= 3) ผ่านSTDIN(โดยอนุญาตให้ป้อนข้อมูลสนามกอล์ฟตามปกติอื่น ๆ ด้วย) ในรูปแบบต่อไปนี้ (จำนวนทศนิยมสามารถเปลี่ยนแปลงได้ แต่คุณสามารถสันนิษฐานได้ว่ามันยังคง "เหมาะสม" และแต่ละหมายเลขสามารถแสดงเป็นแบบลอย):

0.00;0.00000
1;0.00
0.000;1.0000
-1.00;1.000000

เอาท์พุต

ค่าความจริงที่พิมพ์ไปยังSTDOUT(หรือเทียบเท่า) หากจุดแรกในรายการ ( (0.00;0.00000)ในตัวอย่างด้านบน) อยู่ในฮัลล์นูนของจุด N อื่น ๆ และค่าเท็จ

นี่คือดังนั้นทางออกที่สั้นที่สุดในหน่วยไบต์ชนะ

  • กรณี Border : คุณสามารถคืนค่าใด ๆ (แต่ไม่ผิดพลาด) ถ้าจุดนั้นอยู่ที่ขอบของตัวเรือนูน (เช่นด้านข้างหรือจุดยอดที่ขอบด้านนอกของตัวเรือ) เนื่องจากมันเป็นศูนย์ที่น่าจะเป็นศูนย์ เหตุการณ์ (ภายใต้ความน่าจะเป็นที่สมเหตุสมผล)

  • สิ่งต้องห้าม : สิ่งใด (ภาษา, ผู้ปฏิบัติงาน, โครงสร้างข้อมูล, บิวด์อินหรือแพ็คเกจ) ที่มีอยู่เพื่อแก้ไขปัญหาทางเรขาคณิตเท่านั้น (เช่นConematicxHullของ Mathematica ) อนุญาตให้ใช้เครื่องมือทางคณิตศาสตร์ทั่วไป (เวกเตอร์, เมทริกซ์, จำนวนเชิงซ้อนเป็นต้น)

การทดสอบ


3
"โครงสร้างข้อมูลเฉพาะกิจ" คืออะไร?
DavidC

"ฟังก์ชั่น / ตัวดำเนินการเบื้องต้น" นั้นคลุมเครือเกินไป
xnor

@DavidCarraher: สิ่งต่างๆเช่นรูปหลายเหลี่ยมหรือรูปสามเหลี่ยมหรือส่วน (สิ่งที่มีอยู่เพื่อแก้ไขปัญหาทางเรขาคณิตเท่านั้น)
Alexandre Halm

2
@AlexandreHalm การแก้ไขของคุณช่วยได้มาก ฉันคิดว่า "ประถม" ไม่ใช่คำที่ถูกต้อง ฉันคิดว่ามันจะกำจัดวัตถุประสงค์ทั่วไปสร้างอินเหมือนหรือsort roundฉันคิดว่ามันชัดเจนกว่าที่จะบอกว่าไม่อนุญาตให้สร้างรูปทรงเรขาคณิตโดยเฉพาะ อะไรคือสิ่งที่เกี่ยวกับฟังก์ชั่นในการเพิ่มสองรายการเป็นเวกเตอร์ หรือฟังก์ชันเพื่อหาอาร์กิวเมนต์ (มุม) ของจำนวนเชิงซ้อน?
xnor

1
นี่คือเหตุผลที่ Diamonds ขอคนโปรดใช้ Sandboxก่อนโพสต์ความท้าทายใหม่
แมว

คำตอบ:


9

เจ 40 39 34 ไบต์

3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-

ฟังก์ชั่นที่ไม่ระบุชื่อ dyadic, การจุดPเป็นหนึ่งในข้อโต้แย้งของตนและรายการของจุดที่P , เป็นอาร์กิวเมนต์อื่น ๆ (มันไม่ได้เรื่องที่เป็นข้อโต้แย้งที่) และกลับมา0หรือ1ถ้าPอยู่นอกหรือ ภายในตัวเรือนูนของPตามลำดับ จุดpและจุดต่างๆในPถือเป็นจำนวนเชิงซ้อน

ตัวอย่าง

  is_inside =: 3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-

  0.5j0.5  is_inside  0j0 0j1 1j0 1j1
1
  1.5j0.5  is_inside  0j0 0j1 1j0 1j1
0

หรือ...

Python 2 ฟังก์ชั่น 121 103โปรแกรมเต็มรูปแบบ 162

Python 3, 149 ไบต์

import sys,cmath as C
p,q,*P=[complex(*eval(l.replace(*";,")))for l in sys.stdin]
A=[C.phase((r-p)/(q-p+(q==p)))for r in P]
print(max(A)-min(A)>C.pi)

รับอินพุตในรูปแบบเดียวกับโพสต์ดั้งเดิมผ่าน STDIN และพิมพ์ค่าบูลีนที่ระบุว่า p อยู่ในเปลือกนูนของ P หรือไม่


คำอธิบาย

โปรแกรมทดสอบว่าความแตกต่างระหว่างมุมสูงสุดและต่ำสุด (เซ็นชื่อ) ระหว่างจุดใด ๆrในP , pและจุดคงที่qในP (เราเพิ่งใช้จุดแรกในP ) น้อยกว่า 180 ° ในคำอื่น ๆ การทดสอบว่าทุกจุดในPมีอยู่ในมุมของ 180 °หรือน้อยกว่ารอบหน้า pอยู่ในตัวนูนของPถ้าหากเงื่อนไขนี้เป็นเท็จ


ด้วยค่าใช้จ่ายอีกไม่กี่ไบต์เราสามารถใช้วิธีที่คล้ายกันซึ่งไม่ต้องการให้เราคำนวณมุมอย่างชัดเจน: โปรดทราบว่าเงื่อนไขข้างต้นเทียบเท่ากับการบอกว่าpอยู่นอกตัวเรือนูนของPถ้าหากมีอยู่เท่านั้น บรรทัดลิตรผ่านหน้าเช่นว่าทุกจุดในPอยู่ในด้านเดียวกันของลิตร หากมีเส้นดังกล่าวอยู่แสดงว่ามีเส้นดังกล่าวเกิดขึ้นกับจุด (หรือมากกว่า) หนึ่งจุดในP (เราสามารถหมุนlจนกว่าจะแตะจุดใดจุดหนึ่งในP )

ที่จะ (ไม่แน่นอน) พบว่าสายนี้เราเริ่มต้นด้วยการปล่อยให้ลิตรเป็นสายผ่านหน้าและจุดแรกในP จากนั้นเราก็ย้ำผ่านจุดที่เหลือในP ; หากจุดใดจุดหนึ่งอยู่ทางซ้ายของl (เราถือว่าทิศทางบางอย่างตลอดทางซ้ายหรือขวาไม่สำคัญจริงๆ) เราแทนที่lด้วยเส้นตรงผ่านpและจุดนั้นแล้วดำเนินการต่อ หลังจากที่เราซ้ำมากกว่าทั้งหมดของPถ้า (และถ้ามี) หน้าอยู่นอกเปลือกนูนแล้วทุกจุดในPควรจะไปทางขวาของ (หรือ) จากลิตร เราตรวจสอบว่าใช้การผ่านครั้งที่สองเหนือคะแนนในP.

Python 2, 172 ไบต์

import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=reduce(lambda*x:x[C(*x)],P)
print any(C(l,q)for q in P)


อีกวิธีหนึ่งในการทำสิ่งเดียวกันในการส่งครั้งเดียวให้ไปทางซ้ายของการเป็น realtion ระหว่างจุดสองจุดใด ๆqและrในPเช่นนี้qอยู่ทางซ้ายของrถ้าqอยู่ทางซ้าย ของเส้นผ่านหน้าและR โปรดทราบว่า to-ซ้ายคือความสัมพันธ์ในการสั่งซื้อPและถ้าหากทุกจุดในPอยู่ในด้านเดียวกันของเส้นบางผ่านหน้า , ที่อยู่, ถ้าPอยู่นอกเปลือกนูนของP ขั้นตอนที่อธิบายข้างต้นพบว่าจุดต่ำสุดในPwrt คำสั่งนี้คือการ "ซ้ายสุด" จุดในP แทนที่จะทำสองรอบเราสามารถค้นหาจุดสูงสุด (เช่นจุด "ขวา") รวมถึงจุดต่ำสุดจุดในP wrt ลำดับเดียวกันในรอบเดียวและตรวจสอบว่าขั้นต่ำอยู่ทางซ้ายของ สูงสุดคือได้อย่างมีประสิทธิภาพที่ไปทางซ้ายของสกรรมกริยา

สิ่งนี้จะทำงานได้ดีถ้าpอยู่นอกตัวถังนูนของPซึ่งในกรณีนี้ไปทางซ้าย - ของจริง ๆ แล้วเป็นความสัมพันธ์แบบลำดับ แต่อาจแตกหักเมื่อpอยู่ภายในตัวเรือนูน (เช่นพยายามหาว่าจะทำอะไร เกิดขึ้นถ้าเราวิ่งอัลกอริธึมนี้ซึ่งจุดในPคือจุดยอดของรูปห้าเหลี่ยมปกติ, วิ่งทวนเข็มนาฬิกาและpเป็นศูนย์กลางของมัน) เพื่อรองรับเราเปลี่ยนอัลกอริธึมเล็กน้อย: เราเลือกจุดqในPและ bisect Pตามเส้นผ่านpและq (เช่นเราแบ่งพาร์ติชันPประมาณqwrt to-the-the-of.) ตอนนี้เรามี "ส่วนด้านซ้าย" และ "ส่วนด้านขวา" ของPซึ่งแต่ละอันมีอยู่ใน halfplane เพื่อให้ความสัมพันธ์ด้านซ้ายมีความสัมพันธ์ตามลำดับ เราพบค่าต่ำสุดของส่วนด้านซ้ายและค่าสูงสุดของส่วนด้านขวาและเปรียบเทียบกับส่วนที่อธิบายไว้ข้างต้น แน่นอนว่าเราไม่จำเป็นต้องตัดแบ่งทางกายภาพPเราสามารถจำแนกแต่ละจุดเป็นP ได้เมื่อเรามองหาค่าต่ำสุดและสูงสุดในการผ่านครั้งเดียว

Python 2, 194 ไบต์

import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=r=P[0]
for q in P:
 if C(P[0],q):l=q*C(l,q)or l
 elif C(q,r):r=q
print C(l,r)

โอกาสใดที่คุณสามารถแก้ปัญหาของคุณ (อย่างน้อย Python หนึ่งฉันไม่มีเงื่อนงำถ้า J สามารถทำได้) รับอินพุตจาก STDIN? ฉันพบว่าการเปรียบเทียบโซลูชันกับสนามเด็กเล่นในระดับนั้นจะง่ายกว่า สมมติว่าอินพุตเป็นชุดของตัวเลขหรือจุดที่ซับซ้อนที่จัดรูปแบบไว้ล่วงหน้าแล้วเป็นบิตของ IMO ที่ยืดออกได้
Alexandre Halm

@AlexandreHalm เพิ่มโปรแกรมแบบเต็ม
Ell

คุณควรแบ่งคำตอบเป็นหนึ่งคำตอบต่อภาษา
Mego

4

อ็อกเทฟ, 82 72 ไบต์

d=dlmread(0,";");i=2:rows(d);~isna(glpk(i,[d(i,:)';~~i],[d(1,:)';1]))&&1

แนวคิดคือตรวจสอบว่าโปรแกรมเชิงเส้นขั้นต่ำ {c'x: Axe = b, e'x = 1, x> = 0} มีวิธีแก้ปัญหาหรือไม่โดยที่ e คือเวกเตอร์ของทุกคนคอลัมน์ของ A เป็นพิกัดของ cloud point และ b คือจุดทดสอบและ c คือ arbitrary กล่าวอีกนัยหนึ่งเราพยายามแสดง b เป็นการรวมกันแบบนูนของคอลัมน์ของ A

เพื่อเรียกใช้สคริปต์ใช้ octave -f script.m <input.dat


2

R, 207 ไบต์

d=read.csv(file("stdin"),F,";")
q=function(i,j,k)abs(det(as.matrix(cbind(d[c(i,j,k),],1))))
t=function(i,j,k)q(i,j,k)==q(1,i,j)+q(1,i,k)+q(1,j,k)
any(apply(combn(2:nrow(d),3),2,function(v)t(v[1],v[2],v[3])))

สคริปต์ที่ใช้ปัจจัยการผลิตจาก STDIN Rscript script.R < inputFileเช่น

มันสร้างสามเหลี่ยมทั้งหมดจากNจุดสุดท้าย (บรรทัดสุดท้ายapply(combn(...) และตรวจสอบว่าจุดแรกอยู่ในรูปสามเหลี่ยมโดยใช้tฟังก์ชันหรือไม่

tใช้วิธีการพื้นที่ที่จะตัดสินใจว่าUอยู่ในABC: (เขียน(ABC)สำหรับพื้นที่ABC) Uอยู่ในIFFABC (ABC) == (ABU) + (ACU) + (BCU)นอกจากนี้ยังมีการคำนวณพื้นที่โดยใช้สูตรดีเทอร์มิแนนต์ (ดูที่นี่สำหรับการสาธิตที่ดีจาก Wolfram)

ฉันสงสัยว่าโซลูชันนี้มีแนวโน้มที่จะเกิดข้อผิดพลาดทางตัวเลขมากกว่าโซลูชันอื่นของฉัน แต่ใช้งานได้ในกรณีทดสอบของฉัน


0

R, 282 ไบต์

d=read.csv(file("stdin"),F,";")
p=function(a,b)a[1]*b[1]+a[2]*b[2]
t=function(a,b,c){A=d[a,];
U=d[1,]-A
B=d[b,]-A
C=d[c,]-A
f=p(C,C)
g=p(B,C)
h=p(U,C)
i=p(B,B)
j=p(U,B)
k=f*i-g*g
u=i*h-g*j
v=f*j-g*h
min(u*k,v*k,k-u-v)>0}
any(apply(combn(2:nrow(d),3),2,function(v)t(v[1],v[2],v[3])))

สคริปต์ที่ใช้ปัจจัยการผลิตจาก STDIN Rscript script.R < inputFileเช่น

มันสร้างสามเหลี่ยมทั้งหมดจากNจุดสุดท้าย (บรรทัดสุดท้ายapply(combn(...) และตรวจสอบว่าจุดแรกอยู่ในรูปสามเหลี่ยมโดยใช้tฟังก์ชันหรือไม่

tใช้วิธีการ Barycentric ที่จะตัดสินใจว่าUอยู่ในABC: (เขียนXYสำหรับXการYเวกเตอร์) ตั้งแต่(AB,AC)เป็นพื้นฐานสำหรับเครื่องบิน (ยกเว้นกรณีที่เลวโดยที่ A, B, C มีความสอดคล้อง) AUสามารถเขียนเป็นAU = u.AB + v.ACและUอยู่ใน IFF รูปสามเหลี่ยมu > 0 && v > 0 && u+v < 1. ดูตัวอย่างที่นี่สำหรับคำอธิบายโดยละเอียดเพิ่มเติมและแผนภูมิเชิงโต้ตอบที่ดี หมายเหตุ: เพื่อบันทึกไม่กี่ตัวอักษรและหลีกเลี่ยงข้อผิดพลาด DIV0 เราจะคำนวณทางลัดไปยังuและvและการทดสอบแก้ไข ( min(u*k,v*k,k-u-v)>0)

เพียงดำเนินการทางคณิตศาสตร์ที่ใช้กันอยู่+, -, ,*min()>0

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.