Compter le nombre de côtés sur un polygone

18

Compter le nombre de côtés sur un polygone

Le robot de comptage des polygones a décidé de parcourir le monde sans le dire à personne auparavant, mais il est crucial que le processus de comptage des polygones ne soit pas arrêté trop longtemps. Vous avez donc la tâche suivante: Étant donné une image en noir et blanc d'un polygone, votre programme / functoin devrait retourner le nombre de côtés.

Le programme sera alimenté sur un ancien ordinateur à cartes perforées, et comme les cartes perforées sont très chères de nos jours, il vaut mieux essayer de rendre votre programme aussi court que possible.

Les bords font au moins 10 pixels de long, et les angles formés par deux bords adjoints sont d'au moins 10 ° mais pas plus de 170 ° (ou encore plus de 190 °). Le polygone est complètement contenu dans l'image, et le polygone ainsi que son complément sont connectés (il n'y a pas d'îles isolées), donc cette entrée ne serait pas valide:

entrez la description de l'image ici

Notation

Il s'agit de codegolf, ce qui signifie que la soumission la plus courte en octets gagne, votre soumission doit trouver le nombre d'arêtes correct pour chaque cas de test. (Et la soumission devrait également fonctionner pour d'autres cas, l'optimisation uniquement pour ces cas de test n'est pas autorisée.)

Si vous souhaitez soumettre une solution qui ne trouve pas le numéro correct à chaque fois, vous pouvez également le soumettre, mais elle sera classée derrière toutes les soumissions qui fonctionnent mieux.

Veuillez inclure le nombre total dans le titre de votre soumission. (L'erreur totale est la somme des différences absolues entre le nombre réel de côtés et chaque sortie).

Cas de test

n = 10

entrez la description de l'image icientrez la description de l'image ici

n = 36

entrez la description de l'image icientrez la description de l'image ici

n = 7

entrez la description de l'image icientrez la description de l'image ici

n = 5

entrez la description de l'image icientrez la description de l'image ici

Ce n'est pas un cas de test, juste par curiosité: combien d'arêtes obtenez-vous pour cette entrée?

entrez la description de l'image ici

flawr
la source
Je vois dans vos scénarios de test de nombreux angles supérieurs à 170 °. Par exemple, tous les angles "non ponctuels" (ceux les plus proches du centre) de votre étoile.
Poignée de porte
@ Doorknob C'est le plus petit angle qui devrait être inférieur à 170 °.
lirtosiast
Oui, mais elles sont encore supérieures à 190 °. Le but de cette restriction est d'éliminer les exemples où les deux côtés adjacents sont difficiles à distinguer.
flawr
2
De quelle couleur est l'intérieur du polygone?
feersum
1
Le programme sera alimenté sur un ancien ordinateur à cartes perforées, et comme les cartes perforées sont très chères de nos jours, vous feriez mieux d'essayer de rendre votre programme aussi court que possible :-)
Luis Mendo

Réponses:

12

Python 2 + PIL, pas d'erreur, 313 307 octets

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

Prend un nom de fichier image sur la ligne de commande et imprime le résultat sur STDOUT.

Donne le résultat correct pour tous les tests et n = 28 pour le cercle.

Explication

L'algorithme fonctionne en marchant le long du périmètre du polygone et en comptant le nombre de sommets rencontrés (détectés comme des changements de direction). Nous partons du pixel le plus éloigné de l'origine, oqui est garanti d'être un sommet, et donc d'être adjacent à un bord (c'est-à-dire une frontière entre un pixel de premier plan et un pixel d'arrière-plan). Nous gardons une trace de notre position, pdu sommet le plus récent vet du "point de contrôle" le plus récent q, qui sont tous initialement égaux à o. Nous suivons également la direction du bord d,, par rapport au pixel actuel; dpointe d'abord vers l'est, ce qui est une direction sûre, car nous savons qu'il y a un bord à l'est deo, sinon il ne serait pas le plus éloigné de l'origine. Nous nous déplaçons le long du bord, dans une direction perpendiculaire à d, telle qu'elle dpointe vers notre gauche, c'est-à-dire dans le sens horaire. Chaque fois que nous «tombons du bord», c'est-à-dire dans toute situation où pest en dehors du polygone, ou où le pixel à notre gauche (c'est-à-dire dans la direction de d) est à l'intérieur du polygone, nous nous ajustons pet en dconséquence avant de reprendre.

Chaque fois que la distance entre pet le dernier point de contrôle, qdevient supérieure à 5, nous essayons de déterminer si nous avons dépassé un sommet entre qet p: Nous comparons l'angle entre vq(c'est-à-dire le vecteur de và q), qui est la direction générale de la côté du polygone que nous marchions lorsque nous avons atteint le dernier point de contrôle, et qp, le déplacement entre le dernier point de contrôle et la position actuelle. Si l'angle est supérieur à environ 10 °, nous concluons que nous marchons le long d'un côté différent du polygone, augmentons le nombre de sommets et définissons vle sommet actuel sur p. À chaque point de contrôle, que nous ayons détecté ou non un sommet, nous mettons à jour q, le dernier point de contrôle,p. Nous continuons de cette façon jusqu'à ce que nous arrivions au opoint de départ et retournions le nombre de sommets trouvés (notez que le nombre de sommets est initialement de 1, car le point de départ oest lui-même un sommet).

Les images ci-dessous montrent les sommets détectés. Notez que la prise p, la position actuelle à chaque point de contrôle, comme la position du nouveau sommet n'est pas optimale, car le sommet réel est probablement quelque part entre le dernier point de contrôle,, qet p, le long du périmètre. Comme vous pouvez le voir, tous les sommets autres que le premier (généralement le sommet en bas à droite) sont un peu décalés. Corriger cela coûterait plus d'octets, mais cela semble fonctionner assez bien tel quel. Cela étant dit, il est un peu difficile de ne pas surcharger avec seulement quatre cas de test.

n = 10 n = 36 n = 7 n = 5 Cercle

Aune
la source
Merci pour cette explication détaillée! J'adore tes illustrations!
flawr
S'il y a un bord à l'est de o, l'autre extrémité ne serait-elle pas encore plus éloignée de l'origine?
aditsu
1
@aditsu Je pense que la terminologie pourrait être un peu déroutante ici. Nous parlons des côtés du polygone, au sens géométrique, et des bords du (ensemble de pixels comprenant le) polygone, comme un graphique matriciel. oest le pixel de premier plan le plus éloigné de l'origine, donc le pixel à son est doit être un pixel d'arrière-plan, d'où nous disons qu'il y a un bord à l'est de o.
Ell