Le drapeau des États-Unis d'Amérique contient, dans son canton, 50 étoiles, représentant les 50 États.
Dans le passé, quand il y avait moins d'états, il y avait bien sûr moins d'étoiles et elles étaient disposées différemment. Par exemple, de 1912 à 1959 (après l'admission du Nouveau-Mexique et de l'Arizona mais avant l'Alaska), il y avait 48 étoiles dans un arrangement rectangulaire 6 × 8.
Le drapeau à 37 étoiles utilisé de 1867 à 1877 (après l'admission du Nebraska mais avant le Colorado) avait un motif d'étoile asymétrique.
Dans le cas où un 51e État serait ajouté à l'avenir, l'Army Institute of Heraldry a déjà développé une conception préliminaire pour un nouveau drapeau.
Mais il n'y a pas d' algorithme général pour organiser les étoiles, alors faisons-en un!
Le défi
Écrivez un programme qui, pour un nombre donné d'étoiles à placer dans le canton (partie bleue) d'un drapeau américain, produira des coordonnées optimales auxquelles placer ces étoiles. Le système de coordonnées est défini avec le canton [ pas le drapeau dans son ensemble] avec 0≤x≤W et 0≤y≤H.
Aux fins de ce défi, un arrangement «optimal» est défini comme un arrangement qui minimise la distance moyenne (euclidienne) entre un point du canton et le centre de l'étoile la plus proche.
Un algorithme simple (si peut-être sous-optimal) pour approximer cette valeur est:
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)
Votre programme doit prendre trois arguments de ligne de commande (sans compter le nom du programme lui-même):
- Le nombre d'étoiles à mettre dans le canton.
- La largeur du canton. (Doit accepter des valeurs à virgule flottante.)
- La hauteur du canton. (Doit accepter des valeurs à virgule flottante.)
(Si votre langage de programmation préféré ne prend pas en charge les arguments de ligne de commande, faites quelque chose d'assez équivalent et documentez-le dans votre réponse.)
La sortie doit être constituée de valeurs X et Y séparées par des virgules, une par ligne. (L'ordre des points n'a pas d'importance.)
Par exemple:
~$ 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
Règles et notes supplémentaires
- J'ai le droit de combler à tout moment les lacunes dans les règles.
La date limite de réponse est le vendredi 4 juillet à 24h00 CDT (UTC-05: 00).Faute de réponses, le délai a été prolongé. TBA.- Incluez dans votre réponse:
- Le code de votre programme
- Une explication de son fonctionnement
- Sa sortie avec les arguments de ligne de commande
50 1.4 1.0
- Votre programme doit s'exécuter dans un délai raisonnable: au maximum 5 min sur un PC type. Je ne serai pas ultra-strict à ce sujet, mais disqualifierai votre programme si cela prend des heures .
- Votre programme doit être déterministe, c'est-à-dire toujours donner exactement la même sortie pour les mêmes arguments. Donc, ne dépendez pas de
time()
ourand()
. Les méthodes de Monte Carlo sont OK tant que vous lancez votre propre PRNG. - Seuls les points centraux des étoiles comptent. Ne vous inquiétez pas d'essayer d'éviter le chevauchement ou quelque chose comme ça.
Notation
- Minimisez la distance moyenne d'un point du canton à l'étoile la plus proche. (Voir au dessus.)
- Vous pouvez être noté sur la base de n'importe quel drapeau américain historique, entre 13 et 50 étoiles. L'algorithme exact de pondération des scores dans un seul classement sera publié ultérieurement.
- En cas d'égalité, le gagnant sera choisi en fonction du nombre de votes positifs.
- Je publierai probablement mon propre programme, mais je m'exclurai d'être éligible à la coche.
la source
Réponses:
Javascript - déplace les étoiles vers le point le plus isolé
(avec une animation du processus)
L'approche est très simple:
Ce processus est répété un grand nombre de fois, diminuant progressivement la quantité de déplacement des étoiles. Cela réduit la distance maximale d'un point à l'étoile la plus proche, réduisant indirectement la distance moyenne d'un point à l'étoile la plus proche.
Comme l'exige la question, cela n'utilise pas la fonction aléatoire intégrée, mais plutôt xorshift .
Une grande partie du code couvre la configuration et l'animation - la partie qui applique l'algorithme est la fonction
adjustStars
.Code
Vous pouvez voir le processus en cours dans l'extrait de pile ci-dessous.
Sortie pour 50 étoiles
(largeur = 1,4, hauteur = 1,0)
Distance moyenne estimée à 0,0655106697162357.
Coordonnées:
la source
Voici un exemple simple. Il organise toujours les étoiles dans une grille rectangulaire et l'optimise en choisissant la factorisation dans laquelle les cellules de la grille sont aussi proches que possible du carré. Cela fonctionne très bien lorsque le nombre d'étoiles a un diviseur proche de sa racine carrée, et pessimement lorsque le nombre d'étoiles est premier.
Sortie pour 50 étoiles
(largeur = 1,4, hauteur = 1,0)
Un rectangle 10 × 5.
la source
Javascript - déplacez une étoile au hasard si la distance moyenne est réduite
(avec une animation du processus)
Cela ne donne pas une animation aussi chargée que ma première réponse, ayant de longues périodes sans mouvement car les réarrangements potentiels sont testés et rejetés. Cependant, le résultat final a une distance moyenne inférieure, donc cette méthode est une amélioration.
L'approche est toujours très simple:
Ce processus est répété un grand nombre de fois, diminuant progressivement la quantité de déplacement des étoiles. Le choix aléatoire de la distance à parcourir est biaisé vers des distances plus petites, de sorte que la progression se fait par petites altérations entrecoupées de sauts occasionnels plus importants. Chaque étape prend plus de temps que dans ma première réponse, car la mesure de la distance moyenne est un processus lent qui nécessite l'échantillonnage de tout le canton.
Comme l'exige la question, cela n'utilise pas la fonction aléatoire intégrée, mais plutôt xorshift .
Une grande partie du code couvre la configuration et l'animation - la partie qui applique l'algorithme est la fonction
adjustStars
.Code
Vous pouvez voir le processus en cours dans l'extrait de pile ci-dessous.
Sortie pour 50 étoiles
(largeur = 1,4, hauteur = 1,0)
Distance moyenne estimée à 0,06402754713808706.
Coordonnées:
la source