Flaga Stanów Zjednoczonych Ameryki zawiera w swoim kantonie 50 gwiazd, reprezentujących 50 stanów.
W przeszłości, kiedy było mniej stanów, było oczywiście mniej gwiazd i były one ułożone inaczej. Na przykład w latach 1912–1959 (po przyjęciu Nowego Meksyku i Arizony, ale przed Alaską) było 48 gwiazd w układzie prostokątnym 6 × 8.
37-gwiazdkowa flaga używana w latach 1867–1877 (po przyjęciu Nebraski, ale przed Kolorado) miała asymetryczny wzór gwiazdy.
W przypadku dodania 51. stanu w przyszłości, Army Institute of Heraldry opracował już wstępny projekt nowej flagi.
Ale nie ma ogólnego algorytmu układania gwiazd, więc stwórzmy jeden!
Wyzwanie
Napisz program, który dla danej liczby gwiazd umieszczonych w kantonie (niebieska część) flagi USA wygeneruje optymalne współrzędne, w których te gwiazdy zostaną umieszczone. Układ współrzędnych jest definiowany za pomocą kantonu [ nie flagi jako całości] z 0≤x≤W i 0≤y≤H.
Na potrzeby tego wyzwania „optymalne” ustawienie jest zdefiniowane jako takie, które minimalizuje średnią (euklidesową) odległość między punktem w kantonie a środkiem najbliższej gwiazdy.
Prostym (jeśli nie suboptymalnym) algorytmem do przybliżenia tej wartości jest:
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)
Twój program pobierze trzy argumenty wiersza poleceń (nie licząc samej nazwy programu):
- Liczba gwiazdek do umieszczenia w kantonie.
- Szerokość kantonu. (Należy zaakceptować wartości zmiennoprzecinkowe.)
- Wysokość kantonu. (Należy zaakceptować wartości zmiennoprzecinkowe.)
(Jeśli preferowany język programowania nie obsługuje argumentów wiersza polecenia, zrób coś rozsądnie równoważnego i udokumentuj to w odpowiedzi.)
Dane wyjściowe powinny składać się z rozdzielonych przecinkami wartości X i Y, od jednej do linii. (Kolejność punktów nie ma znaczenia.)
Na przykład:
~$ 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
Dodatkowe zasady i uwagi
- Mam prawo do usunięcia luk w regulaminie w dowolnym momencie.
Ostateczny termin udzielania odpowiedzi upływa w piątek, 4 lipca o 24:00 CDT (UTC-05: 00).Z powodu braku odpowiedzi termin został przedłużony. TBA.- Uwzględnij w swojej odpowiedzi:
- Kod twojego programu
- Wyjaśnienie, jak to działa
- Dane wyjściowe z argumentami wiersza polecenia
50 1.4 1.0
- Twój program musi zostać uruchomiony w rozsądnym czasie: maksymalnie 5 minut na typowym komputerze. Nie będę bardzo surowa w tej kwestii, ale zdyskwalifikuje twój program, jeśli zajmie to wiele godzin .
- Twój program musi być deterministyczny, tzn. Zawsze dawać dokładnie to samo wyjście dla tych samych argumentów. Więc nie polegaj na
time()
lubrand()
. Metody Monte Carlo są OK, o ile wykonasz własne PRNG. - Liczą się tylko środkowe punkty gwiazd. Nie martw się, próbując uniknąć nakładania się lub czegoś podobnego.
Punktacja
- Zminimalizuj średnią odległość od punktu w kantonie do najbliższej gwiazdy. (Patrz wyżej.)
- Możesz zostać oceniony na podstawie dowolnych historycznych flag USA, od 13 do 50 gwiazdek. Dokładny algorytm ważenia wyników w jednym rankingu zostanie opublikowany później.
- W przypadku remisu zwycięzca zostanie wybrany na podstawie liczby zwycięstw netto.
- Prawdopodobnie opublikuję własny program, ale wykluczę się z możliwości wyboru.
źródło
Odpowiedzi:
JavaScript - przesuń gwiazdy w kierunku najbardziej izolowanego punktu
(z animacją procesu)
Podejście jest bardzo proste:
Proces ten powtarza się wiele razy, stopniowo zmniejszając ilość ruchu gwiazd. Zmniejsza to maksymalną odległość od punktu do najbliższej gwiazdy, pośrednio zmniejszając średnią odległość od punktu do najbliższej gwiazdy.
Jak wymaga tego pytanie, nie używa wbudowanej funkcji losowej, zamiast tego używa xorshift .
Znaczna część kodu obejmuje konfigurację i animację - częścią stosującą algorytm jest funkcja
adjustStars
.Kod
Możesz obserwować trwający proces w poniższym fragmencie stosu.
Wyjście dla 50 gwiazdek
(szerokość = 1,4, wysokość = 1,0)
Średnia odległość oszacowana na 0,0655106697162357.
Współrzędne:
źródło
Oto prosty przykład. Zawsze układa gwiazdy w prostokątną siatkę i optymalizuje ją, wybierając rozkład na czynniki, w którym komórki siatki są jak najbardziej zbliżone do kwadratu. Działa świetnie, gdy liczba gwiazd ma dzielnik zbliżony do pierwiastka kwadratowego i pesymalnie, gdy liczba gwiazd jest liczbą pierwszą.
Wyjście dla 50 gwiazdek
(szerokość = 1,4, wysokość = 1,0)
Prostokąt 10 × 5.
źródło
JavaScript - przesuń gwiazdę losowo, jeśli zmniejszy się średni dystans
(z animacją procesu)
Nie daje to tak zajętej animacji jak moja pierwsza odpowiedź, mając długie okresy bez ruchu, ponieważ potencjalne zmiany są testowane i odrzucane. Jednak końcowy wynik ma mniejszy średni dystans, więc ta metoda jest poprawą.
Podejście jest nadal bardzo proste:
Proces ten powtarza się wiele razy, stopniowo zmniejszając ilość ruchu gwiazd. Losowy wybór odległości do przesunięcia jest ukierunkowany na mniejsze odległości, więc postęp jest w niewielkich zmianach przerywanych sporadycznie większym skokiem. Każdy krok trwa dłużej niż w mojej pierwszej odpowiedzi, ponieważ pomiar średniej odległości jest powolnym procesem wymagającym próbkowania całego kantonu.
Jak wymaga tego pytanie, nie używa wbudowanej funkcji losowej, zamiast tego używa xorshift .
Znaczna część kodu obejmuje konfigurację i animację - częścią stosującą algorytm jest funkcja
adjustStars
.Kod
Możesz obserwować trwający proces w poniższym fragmencie stosu.
Wyjście dla 50 gwiazdek
(szerokość = 1,4, wysokość = 1,0)
Średnia odległość oszacowana na 0,06402754713808706.
Współrzędne:
źródło