A bandeira dos Estados Unidos da América contém, em seu cantão, 50 estrelas, representando os 50 estados.
No passado, quando havia menos estados, obviamente havia menos estrelas, e elas eram organizadas de maneira diferente. Por exemplo, de 1912 a 1959 (após a admissão do Novo México e Arizona, mas antes do Alasca), havia 48 estrelas em um arranjo retangular 6 × 8.
A bandeira de 37 estrelas usada de 1867 a 1877 (após a admissão de Nebraska, mas antes do Colorado) tinha um padrão de estrela assimétrico.
Caso um 51º estado seja adicionado no futuro, o Instituto de Heráldica do Exército já desenvolveu um projeto preliminar para uma nova bandeira.
Mas não há algoritmo geral para organizar as estrelas, então vamos criar uma!
O desafio
Escreva um programa que, para um determinado número de estrelas no cantão (parte azul) de uma bandeira dos EUA, produza coordenadas ótimas nas quais as estrelas serão colocadas. O sistema de coordenadas é definido com o cantão [ não a bandeira como um todo] com 0≤x≤W e 0≤y≤H.
Para o objetivo deste desafio, um arranjo “ótimo” é definido como aquele que minimiza a distância média (euclidiana) entre um ponto no cantão e o centro da estrela mais próxima.
Um algoritmo direto (se talvez subótimo) para aproximar esse valor é:
def mean_distance_to_nearest_star(stars, width, height, point_density=100):
"""
Approximate the mean distance between a point in the rectangle
0 < x < width and 0 < y < height, and the nearest point in stars.
stars -- list of (x, y) points
width, height -- dimensions of the canton
"""
total = 0.0
nx = round(width * point_density)
ny = round(height * point_density)
for ix in range(nx):
x = (ix + 0.5) * width / nx
for iy in range(ny):
y = (iy + 0.5) * width / ny
min_dist = float('inf')
for sx, sy in stars:
min_dist = min(min_dist, math.hypot(x - sx, y - sy))
total += min_dist
return total / (nx * ny)
Seu programa deve aceitar três argumentos de linha de comando (sem contar o nome do programa):
- O número de estrelas para colocar no cantão.
- A largura do cantão. (Deve aceitar valores de ponto flutuante.)
- A altura do cantão. (Deve aceitar valores de ponto flutuante.)
(Se sua linguagem de programação preferida não suportar argumentos de linha de comando, faça algo razoavelmente equivalente e documente-o em sua resposta.)
A saída deve consistir em valores X e Y separados por vírgula, um para uma linha. (A ordem dos pontos não importa.)
Por exemplo:
~$ flagstar 5 1.4 1.0
0.20,0.20
0.20,0.80
0.70,0.50
1.20,0.20
1.20,0.80
Regras e notas adicionais
- Eu tenho o direito de fechar brechas nas regras a qualquer momento.
O prazo para resposta é sexta - feira, 4 de julho às 24:00 CDT (UTC-05: 00).Devido à falta de respostas, o prazo foi prorrogado. TBA.- Inclua na sua resposta:
- O código do seu programa
- Uma explicação de como funciona
- Sua saída com os argumentos da linha de comando
50 1.4 1.0
- Seu programa deve ser executado dentro de um período de tempo razoável: no máximo 5 minutos em um PC comum. Não vou ser rigoroso quanto a isso, mas desqualificarei seu programa se demorar horas .
- Seu programa deve ser determinístico, ou seja, sempre dê exatamente a mesma saída para os mesmos argumentos. Portanto, não dependa de
time()
ourand()
. Os métodos de Monte Carlo são válidos desde que você faça seu próprio PRNG. - Apenas os pontos centrais das estrelas são importantes. Não se preocupe em tentar evitar sobreposição ou algo assim.
Pontuação
- Minimize a distância média de um ponto no cantão até a estrela mais próxima. (Veja acima.)
- Você pode ser pontuado com base em qualquer bandeira histórica dos EUA, entre 13 e 50 estrelas. O algoritmo exato para ponderar pontuações em um único ranking será publicado posteriormente.
- Em caso de empate, o vencedor será escolhido pelo número de votos líquidos.
- Provavelmente postarei um programa próprio, mas me excluirei de ser elegível para a marca de seleção.
fonte
Respostas:
Javascript - mova estrelas para o ponto mais isolado
(com uma animação do processo)
A abordagem é muito simples:
Esse processo é repetido várias vezes, diminuindo gradualmente a quantidade pela qual as estrelas são movidas. Isso reduz a distância máxima de um ponto à estrela mais próxima, reduzindo indiretamente a distância média de um ponto à estrela mais próxima.
Conforme exigido pela pergunta, isso não usa a função aleatória incorporada, mas sim o xorshift .
Grande parte do código abrange configuração e animação - a parte que aplica o algoritmo é a função
adjustStars
.Código
Você pode assistir ao processo em andamento no snippet de pilha abaixo.
Saída para 50 estrelas
(largura = 1,4, altura = 1,0)
Distância média estimada em 0.0655106697162357.
Coordenadas:
fonte
Aqui está um exemplo simples. Ele sempre organiza as estrelas em uma grade retangular e a otimiza escolhendo a fatoração na qual as células da grade estão o mais próximo possível do quadrado. Funciona muito bem quando o número de estrelas tem um divisor próximo à raiz quadrada e pessimalmente quando o número de estrelas é primo.
Saída para 50 estrelas
(largura = 1,4, altura = 1,0)
Um retângulo 10 × 5.
fonte
Javascript - move uma estrela aleatoriamente se a distância média for reduzida
(com uma animação do processo)
Isso não dá uma animação tão ocupada como a minha primeira resposta, tendo longos períodos sem movimento, pois os rearranjos em potencial são testados e rejeitados. No entanto, o resultado final tem uma distância média mais baixa, portanto esse método é uma melhoria.
A abordagem ainda é muito simples:
Esse processo é repetido várias vezes, diminuindo gradualmente a quantidade pela qual as estrelas são movidas. A escolha aleatória da distância a ser movida é enviesada em direção a distâncias menores, de modo que o progresso ocorre em pequenas alterações intercaladas com um salto maior ocasional. Cada passo leva mais tempo do que na minha primeira resposta, pois medir a distância média é um processo lento que exige amostragem de todo o cantão.
Conforme exigido pela pergunta, isso não usa a função aleatória incorporada, mas sim o xorshift .
Grande parte do código abrange configuração e animação - a parte que aplica o algoritmo é a função
adjustStars
.Código
Você pode assistir ao processo em andamento no snippet de pilha abaixo.
Saída para 50 estrelas
(largura = 1,4, altura = 1,0)
Distância média estimada em 0,06402754713808706.
Coordenadas:
fonte