Contare il numero di lati su un poligono


18

Contare il numero di lati su un poligono

Il robot conteggio dei poligoni ha deciso di viaggiare per il mondo senza dirlo a nessuno prima, ma è fondamentale che il processo di conteggio dei poligoni non si fermi troppo a lungo. Quindi hai il seguente compito: Data un'immagine in bianco e nero di un poligono, il tuo programma / funzione dovrebbe restituire il numero di lati.

Il programma verrà inviato a un vecchio computer con schede perforate e poiché le schede perforate sono molto costose al giorno d'oggi, è meglio cercare di rendere il programma il più breve possibile.

I bordi sono lunghi almeno 10 pixel e gli angoli formati da due bordi adiacenti sono almeno 10 ° ma non più di 170 ° (o di nuovo maggiori di 190 °). Il poligono è completamente contenuto nell'immagine e il poligono e il suo complemento sono collegati (non ci sono isole isolate) quindi questo input non sarebbe valido:

inserisci qui la descrizione dell'immagine

punteggio

Questo è codegolf, il che significa che l'invio più breve in byte vince, l'invio deve trovare il numero corretto di fronti per ogni caso di test. (E l'invio dovrebbe funzionare anche per altri casi, l'ottimizzazione solo per quei casi di test non è consentita.)

Se si desidera inviare una soluzione che non trova il numero corretto ogni volta, è possibile inviare anche quella, ma verrà classificata in base a tutti gli invii con prestazioni migliori.

Si prega di includere il numero totale nel titolo di presentazione. (L'errore totale è la somma delle differenze assolute tra il numero reale di lati e ciascun output).

Casi test

n = 10

inserisci qui la descrizione dell'immagineinserisci qui la descrizione dell'immagine

n = 36

inserisci qui la descrizione dell'immagineinserisci qui la descrizione dell'immagine

n = 7

inserisci qui la descrizione dell'immagineinserisci qui la descrizione dell'immagine

n = 5

inserisci qui la descrizione dell'immagineinserisci qui la descrizione dell'immagine

Questo non è un caso di prova, solo per curiosità: quanti spigoli ottieni per questo input?

inserisci qui la descrizione dell'immagine


Vedo molti angoli nei tuoi casi di test che sono maggiori di 170 °. Ad esempio, tutti gli angoli "non punti" (quelli più vicini al centro) nella tua stella.
Maniglia della porta

@Doorknob È l'angolo più piccolo che dovrebbe essere inferiore a 170 °.
lirtosiast

Sì, ma sono di nuovo superiori a 190 °. Il punto di questa restrizione è eliminare esempi in cui i due lati adiacenti sono difficili da distinguere.
flawr

2
Di che colore è l'interno del poligono?
feersum

1
Il programma verrà alimentato su un vecchio computer con schede perforate e poiché le schede perforate sono molto costose al giorno d'oggi, è meglio provare a rendere il programma il più breve possibile :-)
Luis Mendo,

Risposte:


12

Python 2 + PIL, nessun errore, 313 307 byte

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

Prende il nome di un file immagine dalla riga di comando e stampa il risultato su STDOUT.

Fornisce il risultato corretto per tutti i test e n = 28 per il cerchio.

Spiegazione

L'algoritmo funziona camminando lungo il perimetro del poligono e contando il numero di vertici rilevati (rilevati come cambiamenti di direzione). Iniziamo dal pixel più lontano dall'origine, oche è garantito per essere un vertice, e quindi, per essere adiacente ad un bordo (cioè un confine tra un pixel di primo piano e un pixel di sfondo). Teniamo traccia della nostra posizione, pil vertice più recente ve il "checkpoint" più recente q, che inizialmente sono tutti uguali o. Teniamo anche traccia della direzione del bordo d, rispetto al pixel corrente; dinizialmente punta ad est, che è una direzione sicura, poiché sappiamo che c'è un bordo ad est dio, altrimenti non sarebbe più lontano dall'origine. Ci muoviamo lungo il bordo, in una direzione perpendicolare a d, tale che dpunta alla nostra sinistra, cioè in senso orario. Ogni volta che "cadiamo dal bordo", cioè in qualsiasi situazione pal di fuori del poligono o in cui il pixel alla nostra sinistra (cioè nella direzione di d) si trova all'interno del poligono, ci adeguiamo pe di dconseguenza prima di riprendere.

Ogni volta che la distanza tra pe l'ultimo punto di controllo, qdiventa maggiore di 5, proviamo a determinare se abbiamo superato un vertice tra qe p: confrontiamo l'angolo tra vq(cioè il vettore da va q), che è la direzione generale del lato del poligono che stavamo percorrendo quando abbiamo raggiunto l'ultimo checkpoint e qplo spostamento tra l'ultimo checkpoint e la posizione corrente. Se l'angolo è maggiore di circa 10 °, concludiamo che stiamo camminando lungo un lato diverso del poligono, aumentiamo il conteggio dei vertici e impostiamo vil vertice corrente su p. Ad ogni checkpoint, indipendentemente dal fatto che abbiamo rilevato un vertice o meno, aggiorniamo q, l'ultimo checkpoint, ap. Continuiamo in questo modo fino a quando non arriviamo al opunto di partenza e restituiamo il numero di vertici trovati (si noti che il conteggio dei vertici è inizialmente 1, poiché il punto di partenza o, è esso stesso un vertice).

Le immagini seguenti mostrano i vertici rilevati. Si noti che prendendo p, la posizione corrente in ciascun checkpoint, poiché la posizione del nuovo vertice non è ottimale, poiché il vertice reale è probabilmente da qualche parte tra l'ultimo checkpoint qe p, lungo il perimetro. Come puoi vedere, tutti i vertici diversi dal primo (generalmente il vertice in basso a destra) sono un po 'spenti. La correzione di questo costerebbe più byte, ma sembra funzionare abbastanza bene così com'è. Detto questo, è un po 'difficile non esagerare con solo quattro casi di test.

n = 10 n = 36 n = 7 n = 5 Cerchio


Grazie per questa spiegazione dettagliata! Adoro le tue illustrazioni!
Flawr,

Se c'è un limite ad est di o, l'altra estremità non sarebbe ancora più lontana dall'origine?
aditsu,

1
@aditsu Penso che la terminologia potrebbe essere un po 'confusa qui. Parliamo dei lati del poligono, in senso geometrico, e dei bordi del (poligono di pixel comprendente il) poligono, come un grafico raster. oè il pixel di primo piano più lontano dall'origine, quindi il pixel a est deve essere un pixel di sfondo, quindi diciamo che c'è un bordo a est di o.
Ell
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.