Contar o número de lados em um polígono
O robô de contagem de polígonos decidiu viajar pelo mundo sem avisar ninguém antes, mas é crucial que o processo de contagem de polígonos não pare por muito tempo. Portanto, você tem a seguinte tarefa: Dada uma imagem em preto e branco de um polígono, seu programa / função deve retornar o número de lados.
O programa será enviado a um computador antigo de cartões perfurados e, como os cartões perfurados são muito caros hoje em dia, é melhor tentar tornar o programa o mais curto possível.
As arestas têm pelo menos 10 pixels de comprimento e os ângulos formados por duas arestas adjetivas são de pelo menos 10 °, mas não mais que 170 ° (ou novamente maiores que 190 °). O polígono está completamente contido na imagem, e o polígono e seu complemento estão conectados (não há ilhas isoladas), portanto essa entrada não seria válida:
Pontuação
Este é o codegolf, o que significa que o menor envio em bytes vence; o seu envio precisa encontrar o número correto de arestas para cada caso de teste. (E o envio também deve funcionar para outros casos, a otimização apenas para esses casos de teste não é permitida.)
Se você deseja enviar uma solução que não encontre o número correto a cada vez, também poderá enviá-lo, mas ele ficará atrás de todos os envios com melhor desempenho.
Inclua o número total no seu título de envio. (O erro total é a soma das diferenças absolutas entre o número real de lados e cada saída).
Casos de teste
n = 10
n = 36
n = 7
n = 5
Este não é um caso de teste, apenas por curiosidade: quantas arestas você obtém para esta entrada?
fonte
Respostas:
Python 2 + PIL, sem erro,
313307 bytesPega um nome de arquivo de imagem na linha de comando e imprime o resultado em STDOUT.
Dá o resultado correto para todos os testes en = 28 para o círculo.
Explicação
O algoritmo funciona caminhando ao longo do perímetro do polígono e contando o número de vértices encontrados (detectados como alterações na direção). Começamos no pixel mais distante da origem,
o
que é garantidamente um vértice e, portanto, adjacente a uma aresta (ou seja, um limite entre um pixel em primeiro plano e um pixel em segundo plano). Nós controlamos nossa posição,p
o vértice mais recentev
e o "ponto de verificação" mais recenteq
, todos inicialmente iguais ao
. Também acompanhamos a direção da bordad
, em relação ao pixel atual;d
inicialmente aponta para leste, o que é uma direção segura, pois sabemos que há uma borda a leste deo
, ou não seria o mais distante da origem. Nós nos movemos ao longo da borda, em uma direção perpendicular ad
, de modo qued
aponte para a esquerda, ou seja, no sentido horário. Sempre que "caímos da aresta", ou seja, em qualquer situaçãop
fora do polígono, ou onde o pixel à nossa esquerda (na direção ded
) esteja dentro do polígono, ajustamosp
e ded
acordo antes de continuar.Toda vez que a distância entre
p
e o último ponto de verificaçãoq
fica maior que 5, tentamos determinar se passamos por um vértice entreq
ep
: Comparamos o ângulo entrevq
(ou seja, o vetor dev
paraq
), que é a direção geral do lado do polígono em que estávamos caminhando quando alcançamos o último ponto de verificação eqp
o deslocamento entre o último ponto de verificação e a posição atual. Se o ângulo for maior que cerca de 10 °, concluímos que estamos andando por um lado diferente do polígono, aumentamos a contagem de vértices e ajustamosv
o vértice atual parap
. Em cada ponto de verificação, independentemente de detectarmos um vértice ou não, atualizamosq
o último ponto de verificação parap
. Continuamos dessa maneira até chegarmoso
ao ponto de partida e retornar o número de vértices encontrados (observe que a contagem de vértices é inicialmente 1, pois o ponto de partidao
é um vértice).As imagens abaixo mostram os vértices detectados. Observe que
p
, assumindo , a posição atual em cada ponto de verificação, como a posição do novo vértice, não é ideal, pois o vértice real provavelmente está em algum lugar entre o último ponto de verificaçãoq
ep
ao longo do perímetro. Como você pode ver, todos os vértices que não sejam o primeiro (geralmente, o vértice inferior direito) estão um pouco fora. Corrigir isso custaria mais bytes, mas parece estar funcionando bem o suficiente. Dito isto, é um pouco difícil não se ajustar demais com apenas quatro casos de teste.fonte
o
, o outro extremo não estaria mais longe da origem?o
é o pixel de primeiro plano mais distante da origem; portanto, o pixel a leste deve ser um pixel de fundo; portanto, dizemos que há uma borda a leste deo
.