Cuenta el número de lados en un polígono

18

Cuenta el número de lados en un polígono

El robot de conteo de polígonos ha decidido viajar por el mundo sin avisarle a nadie antes, pero es crucial que el proceso de conteo de polígonos no se detenga por mucho tiempo. Entonces tiene la siguiente tarea: Dada una imagen en blanco y negro de un polígono, su programa / función debería devolver el número de lados.

El programa se enviará a una vieja computadora de tarjetas perforadas, y como las tarjetas perforadas son muy caras hoy en día, es mejor que intentes hacer que tu programa sea lo más corto posible.

Los bordes tienen al menos 10 píxeles de largo, y los ángulos formados por dos bordes adyacentes tienen al menos 10 ° pero no más de 170 ° (o nuevamente más de 190 °). El polígono está completamente contenido dentro de la imagen, y el polígono y su complemento están conectados (no hay islas aisladas), por lo que esta entrada no sería válida:

ingrese la descripción de la imagen aquí

Puntuación

Esto es codegolf, eso significa que gana el envío más corto en bytes, su envío tiene que encontrar el número correcto de bordes para cada caso de prueba. (Y el envío también debería funcionar para otros casos, no se permite la optimización solo para esos casos de prueba).

Si desea enviar una solución que no encuentra el número correcto cada vez, también puede enviarla, pero se clasificará detrás de todas las presentaciones que funcionen mejor.

Incluya el número total en el título de su envío. (El error total es la suma de las diferencias absolutas entre el número real de lados y cada salida).

Casos de prueba

n = 10

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

n = 36

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

n = 7

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

n = 5

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

Este no es un caso de prueba, solo por curiosidad: ¿Cuántos bordes obtienes para esta entrada?

ingrese la descripción de la imagen aquí

falla
fuente
Veo muchos ángulos en sus casos de prueba que son mayores de 170 °. Por ejemplo, todos los ángulos "no puntuales" (los más cercanos al centro) en su estrella.
Pomo de la puerta
@Pomo de la puerta Es el ángulo más pequeño que debe ser inferior a 170 °.
lirtosiast
Sí, pero nuevamente son mayores de 190 °. El objetivo de esta restricción es eliminar ejemplos donde los dos lados adyacentes son difíciles de distinguir.
falla
2
¿De qué color es el interior del polígono?
feersum
1
El programa se enviará a una vieja computadora de tarjetas perforadas, y como las tarjetas perforadas son muy caras hoy en día, es mejor que intentes hacer tu programa lo más corto posible :-)
Luis Mendo

Respuestas:

12

Python 2 + PIL, sin error, 313 307 bytes

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

Toma un nombre de archivo de imagen en la línea de comando e imprime el resultado en STDOUT.

Da el resultado correcto para todas las pruebas, y n = 28 para el círculo.

Explicación

El algoritmo funciona caminando a lo largo del perímetro del polígono y contando el número de vértices encontrados (detectados como cambios en la dirección). Comenzamos en el píxel más alejado del origen, oque se garantiza que es un vértice y, por lo tanto, adyacente a un borde (es decir, un límite entre un píxel de primer plano y un píxel de fondo). Llevamos un registro de nuestra posición, pel vértice más reciente vy el "punto de control" más reciente q, todos los cuales son inicialmente iguales a o. También hacemos un seguimiento de la dirección del borde d, en relación con el píxel actual; dinicialmente apunta al este, que es una dirección segura, ya que sabemos que hay un borde al este deoo de lo contrario no estaría más lejos del origen. Nos movemos a lo largo del borde, en una dirección perpendicular a d, de modo que dapunta a nuestra izquierda, es decir, en el sentido de las agujas del reloj. Cada vez que "nos caemos del borde", es decir, en cualquier situación en la que pestá fuera del polígono, o donde el píxel a nuestra izquierda (es decir, en la dirección de d) está dentro del polígono, nos ajustamos py, en dconsecuencia, antes de continuar.

Cada vez que la distancia entre py el último punto de control, qes mayor que 5, tratamos de determinar si pasamos por un vértice entre qy p: comparamos el ángulo entre vq(es decir, el vector de va q), que es la dirección general de lado del polígono que estábamos caminando cuando llegamos al último punto de control y qpel desplazamiento entre el último punto de control y la posición actual. Si el ángulo es mayor de aproximadamente 10 °, concluimos que estamos caminando a lo largo de un lado diferente del polígono, aumentamos el conteo de vértices y establecemos vel vértice actual en p. En cada punto de control, independientemente de si detectamos un vértice o no, actualizamos qel último punto de control parap. Continuamos de esta manera hasta que volvemos al opunto de partida y devolvemos el número de vértices encontrados (tenga en cuenta que el conteo de vértices es inicialmente 1, ya que el punto de partida oes en sí mismo un vértice).

Las imágenes a continuación muestran los vértices detectados. Tenga en cuenta que tomar pla posición actual en cada punto de control, ya que la posición del nuevo vértice no es óptima, ya que el vértice real probablemente esté en algún lugar entre el último punto de control q, y p, a lo largo del perímetro. Como puede ver, todos los vértices que no sean el primero (generalmente, el vértice inferior derecho) están un poco alejados. Arreglar esto costaría más bytes, pero parece estar funcionando lo suficientemente bien como está. Dicho esto, es un poco difícil no equiparse con solo cuatro casos de prueba.

n = 10 n = 36 n = 7 n = 5 Circulo

Ana
fuente
¡Gracias por esta explicación detallada! ¡Me encantan tus ilustraciones!
falla
Si hay un borde al este de o, ¿el otro extremo no estaría aún más lejos del origen?
Aditsu
1
@aditsu Creo que la terminología puede ser un poco confusa aquí. Hablamos sobre los lados del polígono, en sentido geométrico, y los bordes del (conjunto de píxeles que comprenden el) polígono, como un gráfico de trama. oes el píxel de primer plano más alejado desde el origen, por lo que el píxel hacia el este debe ser un píxel de fondo, por lo tanto, decimos que hay un borde al este de o.
Ell