นับจำนวนข้างในรูปหลายเหลี่ยม


18

นับจำนวนข้างในรูปหลายเหลี่ยม

หุ่นยนต์นับด้านรูปหลายเหลี่ยมได้ตัดสินใจเดินทางไปทั่วโลกโดยไม่บอกใครมาก่อน แต่เป็นสิ่งสำคัญที่กระบวนการนับรูปหลายเหลี่ยมนั้นไม่ได้หยุดนานเกินไป ดังนั้นคุณมีงานดังต่อไปนี้: เมื่อกำหนดให้เป็นรูปหลายเหลี่ยมสีดำและสีขาวโปรแกรม / functoin ของคุณควรคืนค่าจำนวนด้าน

โปรแกรมจะถูกป้อนเข้ากับคอมพิวเตอร์ punch card เก่าและเนื่องจาก punchcards มีราคาแพงมากในปัจจุบันคุณควรพยายามทำให้โปรแกรมของคุณสั้นที่สุด

ขอบมีความยาวอย่างน้อย 10 พิกเซลและมุมที่เกิดจากขอบสองส่วนคืออย่างน้อย 10 ° แต่ไม่เกิน 170 ° (หรือมากกว่า 190 °) รูปหลายเหลี่ยมมีอยู่ในรูปภาพอย่างสมบูรณ์และรูปหลายเหลี่ยมรวมถึงส่วนประกอบนั้นเชื่อมต่อกัน (ไม่มีเกาะที่แยกได้) ดังนั้นข้อมูลนี้จะไม่ถูกต้อง:

ป้อนคำอธิบายรูปภาพที่นี่

เกณฑ์การให้คะแนน

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

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

โปรดระบุจำนวนรวมในชื่อการส่งของคุณ (ข้อผิดพลาดทั้งหมดคือผลรวมของความแตกต่างแบบสัมบูรณ์ระหว่างจำนวนจริงของด้านและแต่ละเอาต์พุต)

กรณีทดสอบ

n = 10

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

n = 36

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

n = 7

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

n = 5

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

นี่ไม่ใช่กรณีทดสอบเพิ่งเกิดจากความอยากรู้: คุณมีขอบจำนวนเท่าใดสำหรับข้อมูลนี้

ป้อนคำอธิบายรูปภาพที่นี่


ฉันเห็นหลายมุมในกรณีทดสอบของคุณที่มากกว่า 170 ° ตัวอย่างเช่นมุม "ไม่ใช่จุด" ทั้งหมด (มุมที่อยู่ใกล้กับศูนย์กลางมาก) ในดาวของคุณ
Doorknob

@Doorknob เป็นมุมที่เล็กกว่าที่ควรจะน้อยกว่า 170 °
lirtosiast

ใช่ แต่พวกเขามากกว่า 190 °อีกครั้ง จุดประสงค์ของข้อ จำกัด นี้คือการกำจัดตัวอย่างที่ทั้งสองฝ่ายแยกออกจากกันได้ยาก
ข้อบกพร่อง

2
สีภายในของรูปหลายเหลี่ยมสีใด
feersum

1
โปรแกรมจะถูกป้อนเข้ากับคอมพิวเตอร์ punch card เก่าและเนื่องจาก punchcards มีราคาแพงมากในปัจจุบันคุณควรพยายามทำให้โปรแกรมของคุณสั้นที่สุดเท่าที่จะทำได้ :-)
Luis Mendo

คำตอบ:


12

Python 2 + PIL ไม่มีข้อผิดพลาด 313 307 ไบต์

from Image import*
I=open(sys.argv[1])
w,h=I.size;D=I.getdata()
B={i%w+i/w*1j for i in range(w*h)if D[i]!=D[0]}
n=d=1;o=v=q=p=max(B,key=abs)
while p-w:
 p+=d*1j;e=2*({p}<B)+({p+d}<B)
 if e!=2:e%=2;d*=1j-e*2j;p-=d/1j**e
 if abs(p-q)>5:
    t=(q-v)*(p-q).conjugate();q=p;w=o
    if.98*abs(t)>t.real:n+=1;v=p
print n

ใช้ชื่อไฟล์รูปภาพบนบรรทัดคำสั่งและพิมพ์ผลลัพธ์ไปที่ STDOUT

ให้ผลลัพธ์ที่ถูกต้องสำหรับการทดสอบทั้งหมดและn = 28 สำหรับวงกลม

คำอธิบาย

อัลกอริธึมทำงานด้วยการเดินไปตามเส้นรอบวงของรูปหลายเหลี่ยมและนับจำนวนจุดยอดที่พบ (ตรวจพบว่ามีการเปลี่ยนแปลงในทิศทาง) เราเริ่มต้นที่จุดที่ห่างจากจุดเริ่มต้นมากoที่สุดซึ่งรับประกันว่าจะเป็นจุดสุดยอดดังนั้นจึงจะอยู่ติดกับขอบ (กล่าวคือขอบเขตระหว่างพิกเซลพื้นหน้าและพิกเซลพื้นหลัง) เราติดตามตำแหน่งของเราp, จุดสุดยอดล่าสุดvและล่าสุด "ด่าน" ซึ่งทั้งหมดจะเท่ากับแรกq oเรายังติดตามทิศทางของขอบd,, สัมพันธ์กับพิกเซลปัจจุบัน; dตอนแรกชี้ไปทางทิศตะวันออกซึ่งเป็นทิศทางที่ปลอดภัยเนื่องจากเรารู้ว่ามีขอบไปทางทิศตะวันออกของoมิฉะนั้นมันจะไม่ห่างจากจุดกำเนิดมากที่สุด เราเคลื่อนที่ไปตามขอบในทิศทางที่ตั้งฉากกับdซึ่งdชี้ไปทางซ้ายของเราเช่นในทิศทางตามเข็มนาฬิกา เมื่อใดก็ตามที่เรา "หลุดขอบ" คือในสถานการณ์ใด ๆ ที่pอยู่นอกรูปหลายเหลี่ยมหรือที่พิกเซลทางซ้ายของเรา (เช่นในทิศทางของd) อยู่ภายในรูปหลายเหลี่ยมเราปรับpและdตามก่อนที่จะกลับมาทำงานอีกครั้ง

ทุกครั้งที่ระยะห่างระหว่างpและจุดตรวจสุดท้ายqได้รับมากกว่า 5 เราพยายามตรวจสอบว่าเราผ่านจุดยอดระหว่างqและp: เราเปรียบเทียบมุมระหว่างvq(เช่นเวกเตอร์จากvถึงq) ซึ่งเป็นทิศทางทั่วไปของ ด้านข้างของรูปหลายเหลี่ยมที่เรากำลังเดินไปเมื่อเราไปถึงด่านสุดท้ายและqpการกระจัดระหว่างจุดตรวจสุดท้ายกับตำแหน่งปัจจุบัน ถ้ามุมมากกว่าประมาณ 10 องศาเราสรุปว่าเราสามารถเดินกำลังพร้อมด้านที่แตกต่างของรูปหลายเหลี่ยม, เพิ่มจำนวนจุดสุดยอดและชุดv, pจุดสุดยอดในปัจจุบันจะ ที่จุดตรวจแต่ละจุดโดยไม่คำนึงว่าเราตรวจพบจุดสุดยอดหรือไม่เราอัปเดตqจุดตรวจสุดท้ายเป็นp. เราดำเนินการต่อในรูปแบบนี้จนกว่าเราจะกลับมาที่oจุดเริ่มต้นและคืนจำนวนจุดยอดที่พบ (โปรดทราบว่าการนับจุดยอดคือ 1 ในขั้นต้นตั้งแต่จุดเริ่มต้นoเป็นจุดสุดยอด)

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

n = 10 n = 36 n = 7 n = 5 วงกลม


ขอบคุณสำหรับคำอธิบายโดยละเอียด! ฉันรักภาพประกอบของคุณ!
ข้อบกพร่อง

หากมีขอบไปทางทิศตะวันออกoปลายอื่น ๆ จะไม่ได้ไกลจากแหล่งกำเนิด?
aditsu

1
@aditsu ฉันคิดว่าคำศัพท์อาจจะสับสนเล็กน้อยที่นี่ เราพูดถึงด้านของรูปหลายเหลี่ยมในแง่เรขาคณิตและขอบของ (ชุดของพิกเซลที่ประกอบด้วย) รูปหลายเหลี่ยมเป็นกราฟิกแรสเตอร์ เป็นพิกเซลเบื้องหน้าไกลที่สุดจากแหล่งกำเนิดดังนั้นพิกเซลไปทางทิศตะวันออกของมันจะต้องเป็นพิกเซลพื้นหลังด้วยเหตุนี้เราบอกว่ามีขอบไปทางทิศตะวันออกของo o
Ell
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.