Bir çokgendeki kenar sayısını sayma


18

Bir çokgendeki kenar sayısını sayma

Çokgen tarafı sayma robotu, daha önce kimseye söylemeden dünyayı dolaşmaya karar verdi, ancak çokgen sayma işleminin çok uzun süre durdurulmaması çok önemlidir. Bu nedenle aşağıdaki göreviniz var: Bir çokgenin siyah beyaz görüntüsü verildiğinde, programınız / functoin kenar sayısını döndürmelidir.

Program eski bir delikli kart bilgisayarına beslenecek ve günümüzde delikli kartlar çok pahalı olduğundan, programınızı mümkün olduğunca kısa tutmaya çalışsanız iyi olur.

Kenarlar en az 10 piksel uzunluğundadır ve iki bitişik kenarın oluşturduğu açılar en az 10 ° 'dir ancak 170 °' den fazla (veya yine 190 ° 'den fazla) değildir. Çokgen (hayır adalar orada izole edilmiştir) Bu giriş diye tamamen resmin içinde yer alır ve poligon yanı sıra 's tamamlayıcı bağlandığında değil geçerlidir:

resim açıklamasını buraya girin

puanlama

Bu kodgolf, yani bayt cinsinden en kısa gönderim kazanır, gönderiminiz her test durumu için doğru sayıda kenar bulmak zorundadır. (Ve gönderimin diğer durumlar için de çalışması gerekir, yalnızca bu test senaryoları için optimizasyona izin verilmez.)

Her seferinde doğru numarayı bulamayan bir çözüm göndermek istiyorsanız, bunu da gönderebilirsiniz, ancak daha iyi performans gösteren tüm gönderilerin arkasında sıralanır.

Lütfen toplam sayınızı gönderim başlığınıza ekleyin. (Toplam hata, gerçek kenar sayısı ve her çıktı arasındaki mutlak farkların toplamıdır).

Test senaryoları

n = 10

resim açıklamasını buraya girinresim açıklamasını buraya girin

n = 36

resim açıklamasını buraya girinresim açıklamasını buraya girin

n = 7

resim açıklamasını buraya girinresim açıklamasını buraya girin

n = 5

resim açıklamasını buraya girinresim açıklamasını buraya girin

Bu bir test durumu değil, sadece meraktan: Bu giriş için kaç kenar elde ediyorsunuz?

resim açıklamasını buraya girin


Test vakalarınızda 170 ° 'den büyük birçok açı görüyorum. Örneğin, yıldızınızdaki tüm "nokta olmayan" açılar (merkeze daha yakın olanlar).
Kapı tokmağı

@Doorknob 170 ° 'den daha az olması gereken daha küçük açıdır.
lirtosiast

Evet, ama yine 190 ° 'den daha büyükler. Bu kısıtlamanın amacı, iki iyi tarafın birbirinden ayrılmasının zor olduğu örnekleri ortadan kaldırmaktır.
flawr

2
Poligonun içi hangi renktir?
feersum

1
Program eski bir delikli kart bilgisayarına beslenecek ve günümüzde punchcards çok pahalı olduğundan, programınızı mümkün olduğunca kısa yapmaya çalışın :-)
Luis Mendo

Yanıtlar:


12

Python 2 + PIL, hata yok, 313 307 bayt

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

Komut satırında bir görüntü dosyası adı alır ve sonucu STDOUT'a yazdırır.

Tüm testler için doğru sonucu ve daire için n = 28 değerini verir.

açıklama

Algoritma, çokgenin çevresi boyunca yürüyerek ve karşılaşılan köşe noktalarının sayısını (yön değişiklikleri olarak algılanır) sayarak çalışır. Köşe noktası oolduğu ve bu nedenle bir kenara bitişik (yani, ön plan pikseli ile arka plan pikseli arasındaki bir sınır) olduğu garanti edilen, başlangıç ​​noktasından en uzak pikselden başlıyoruz . Başlangıçta hepsi eşit olan konumumuzu, pen son tepe noktasını vve en son "kontrol noktasını" takip qediyoruz o. Ayrıca d, mevcut piksele göre kenarın yönünü de izleriz; dbaşlangıçta doğuyu gösterir, bu güvenli bir yön, çünkü doğuda bir kenar olduğunu biliyoruzoya da başka bir deyişle, başlangıç ​​noktasından en uzakta olmazdı. Kenar boyunca, solumuzu gösterecek şekilde , yani saat yönünde hareket dedecek dşekilde hareket ediyoruz. "Kenardan düştüğümüzde", yani pçokgenin dışında veya solumuzdaki pikselin (yani yönünde d) çokgenin içinde olduğu herhangi bir durumda , ayarlamaya pve dbuna uygun olarak devam etmeden önce.

Her zaman arasındaki mesafe pve geçen kapısı olan q, 5'ten büyür, biz arasında bir köşe geçti olup olmadığını belirlemeye çalışır qve p: Biz arasındaki açıyı karşılaştırmak vq(yani gelen vektör viçin q) genel yönü olduğunu, son kontrol noktasına ulaştığımızda yürüdüğümüz çokgenin bir tarafı qpve son kontrol noktası ile mevcut konum arasındaki yer değiştirme. Açı yaklaşık 10 ° 'den büyükse, çokgenin farklı bir kenarı boyunca yürüdüğümüz, tepe noktası sayısını artırdığımız vve mevcut tepe noktasını olarak ayarladığımız sonucuna varıyoruz p. Her kontrol noktasında, bir tepe noktası tespit edip etmememizden bağımsız olarak q, son kontrol noktasınıp. Bu onoktaya, başlangıç ​​noktasına dönene ve bulunan köşe sayısını döndürene kadar devam ediyoruz (başlangıç ​​noktasından beri tepe noktası sayısının başlangıçta 1 olduğunu unutmayın o, kendisi bir tepe noktasıdır .)

Aşağıdaki resimler algılanan köşeleri göstermektedir. Alarak geldiğini hatırlatırız pgerçek tepe muhtemelen bir yerlerde son kontrol noktasında arasındadır, çünkü yeni tepe noktası konumunda olarak, her kontrol noktasında, mevcut konumu, optimum değildir qve pçevre boyunca. Gördüğünüz gibi, ilkinden başka tüm köşeler (genellikle sağ alt köşe) biraz kapalı. Bunu düzeltmek daha fazla bayta mal olabilir, ancak bu olduğu gibi yeterince iyi çalışıyor gibi görünüyor. Bununla birlikte, sadece dört test vakasına uymamak biraz zor.

n = 10 n = 36 n = 7 n = 5 Daire


Bu ayrıntılı açıklama için teşekkürler! Resimlerinizi seviyorum!
Kusur

Doğusunda bir kenar varsa o, diğer uç başlangıç ​​noktasından daha uzak olmaz mı?
aditsu

1
@aditsu Sanırım terminoloji biraz kafa karıştırıcı olabilir. Bu söz iki geometrik anlamda, poligon ve kenarları arasında bir raster grafik olarak, çokgen (ihtiva eden piksel ayarlanır). obaşlangıç ​​noktasından en uzak ön plan pikselidir, bu yüzden doğusundaki piksel bir arka plan pikseli olmalıdır, bu yüzden doğusunda bir kenar olduğunu söylüyoruz o.
Ell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.