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:
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
n = 36
n = 7
n = 5
Este no es un caso de prueba, solo por curiosidad: ¿Cuántos bordes obtienes para esta entrada?
fuente
Respuestas:
Python 2 + PIL, sin error,
313307 bytesToma 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,
o
que 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,p
el vértice más recientev
y el "punto de control" más recienteq
, todos los cuales son inicialmente iguales ao
. También hacemos un seguimiento de la dirección del borded
, en relación con el píxel actual;d
inicialmente apunta al este, que es una dirección segura, ya que sabemos que hay un borde al este deo
o de lo contrario no estaría más lejos del origen. Nos movemos a lo largo del borde, en una dirección perpendicular ad
, de modo qued
apunta 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 quep
está fuera del polígono, o donde el píxel a nuestra izquierda (es decir, en la dirección ded
) está dentro del polígono, nos ajustamosp
y, end
consecuencia, antes de continuar.Cada vez que la distancia entre
p
y el último punto de control,q
es mayor que 5, tratamos de determinar si pasamos por un vértice entreq
yp
: comparamos el ángulo entrevq
(es decir, el vector dev
aq
), que es la dirección general de lado del polígono que estábamos caminando cuando llegamos al último punto de control yqp
el 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 establecemosv
el vértice actual enp
. En cada punto de control, independientemente de si detectamos un vértice o no, actualizamosq
el último punto de control parap
. Continuamos de esta manera hasta que volvemos alo
punto 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 partidao
es en sí mismo un vértice).Las imágenes a continuación muestran los vértices detectados. Tenga en cuenta que tomar
p
la 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 controlq
, yp
, 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.fuente
o
, ¿el otro extremo no estaría aún más lejos del origen?o
es 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 deo
.