W tym wyzwaniu otrzymasz listę punktów. Punkty te leżą na obwodzie wyimaginowanego kwadratu . Twoim celem jest:
- Jeśli to możliwe, wydrukuj obrót kwadratu, który będzie wartością z [0, 90), gdzie 0 oznacza kwadrat z liniami pionowymi i poziomymi. Obrót należy podawać w stopniach liczonych w kierunku przeciwnym do ruchu wskazówek zegara.
- Jeśli obrót kwadratu jest niejednoznaczny (np. Otrzymanie tylko 2 punktów), wydrukuj „Nieznany”
- Jeśli utworzenie kwadratu z uwzględnieniem punktów jest niemożliwe, wydrukuj „Niemożliwe”
Punkty, które otrzymasz, są gwarantowane, że są unikalne i nie mają określonej kolejności. Możesz użyć dowolnego formatu, w którym chcesz wprowadzić listę, ale w moich przykładach moje punkty będą w formacie x,y
, a odstępy będą oddzielone. Liczby są liczbami zmiennoprzecinkowymi i można założyć, że mieszczą się w zakresie, który może obsługiwać Twój język. Wynik powinien być dokładny do co najmniej 3 miejsc po przecinku i założyć, że Twój język obsługuje liczby zmiennoprzecinkowe z doskonałą dokładnością.
Oto kilka przypadków testowych (większość z nich używałem liczb całkowitych do łatwej wizualizacji, ale twój program powinien obsługiwać zmiennoprzecinkowe):
Nieznany:
0,0
0,0 1,0
0,0 1,0 0,1
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2
Niemożliwy:
0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1
Możliwe (jeśli nie zostało określone, powinno zwrócić 0):
0,0 1,0 2,0
0,0 0.3,0.3 0.6,0.6 (should return 45)
0,0 0.1,0.2 0.2,0.4 (should return appx 63.435 (the real value is arctan(2)))
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3
Mogłem przegapić kilka interesujących przypadków testowych. Jeśli tak, prosimy o komentarz, aby je dodać.
To jest golf golfowy, więc wygrywa kod najkrótszy!
Odpowiedzi:
Rev 1: Ruby, 354 bajty
dalsza gra w golfa dzięki blutorange.
Rubinowy, 392 bajtów
Algorytm wygląda następująco:
- Wybierz dowolny punkt (pierwszy) i przenieś go do początku (odejmij współrzędne tego punktu od wszystkich punktów na liście).
- Spróbuj wszystkich obrotów kwadratu wokół początku w krokach co 0,001 stopnia, o 360 stopni.
- Dla danego obrotu, jeśli wszystkie punkty znajdują się powyżej osi y, narysuj możliwie najmniejszy kwadrat wokół wszystkich punktów, uwzględniając najniższy i najbardziej lewy punkt.
-Sprawdź, czy wszystkie punkty znajdują się na krawędzi. Odbywa się to za pomocą miękkiego obliczenia, które bierze każdy punkt, znajduje kwadratowe odległości od wszystkich krawędzi i mnoży je razem. Daje to dobre dopasowanie, a nie odpowiedź tak / nie. Interpretuje się, że rozwiązanie zostanie znalezione, jeśli ten iloczyn podzielony przez długość boczną ^ 8 jest mniejszy niż 1E-9. W praktyce jest to mniej niż stopień tolerancji.
- Najlepsze dopasowanie przyjmuje mod 90 stopni i podaje jako prawidłowy kąt.
Obecnie kod zwraca wartość niejednoznaczności, jeśli znaleziono ponad 100 rozwiązań (przy rozdzielczości 0,001 stopnia. To 0,1 stopnia tolerancji).
pierwsza w pełni działająca funkcja w programie testowym
Zostawiłem rozdzielczość na 1/10 wymaganej rozdzielczości, aby prędkość była rozsądna. Wystąpił błąd 0,01 degress na ostatnim przypadku testowym.
wersja golfowa, rozdzielczość zgodna ze specyfikacją, trwa około minuty na połączenie w programie testowym.
W ostatnim przypadku testowym nadal występuje nieznośny błąd 0,001 stopnia. Dalsze zwiększenie rozdzielczości prawdopodobnie go wyeliminuje.
Zauważ, że dla około 30% więcej kodu algorytm ten można dostosować do szybkiej pracy: oczywiste jest, że w przypadkach o skończonej liczbie rozwiązań jedna z krawędzi leży płasko wzdłuż sześcianu, więc naprawdę musimy spróbować tylko te kąty które odpowiadają każdej parze wierzchołków. Konieczne byłoby również trochę poruszenia, aby sprawdzić, czy nie ma nieskończenie wielu rozwiązań.
źródło
0,0 1,0 2,0 1,2
jest nadal możliwa dla kwadratu o przekątnej 0,0 ... 2,2. Próbowałem tego, a także0,0 1,0 2,0 1,1
(to drugie jest rzeczywiście niemożliwe). Kolejna kwestia: czy uważasz, że akceptowalny lub niedopuszczalny jest fakt, że mój kod zwraca niemożliwe, a nie nieznane, gdy podany jest tylko jeden punkt? Byłbym wdzięczny za odpowiedź, zanim zacznę grać w golfa.1,1
. Nie jestem pewien, jak1,2
się tam dostałeś. To nie do przyjęcia.if..end
s, ponieważ mam straszne problemy z zagnieżdżonymi operatorami trójskładnikowymi w Rubim. Widzę, że obejrzałeś to, używając&&
.Perl
Cześć, oto moje skromne południe. Przypadki testowe są umieszczane w strumieniu danych na dole pliku. Algorytm rozwinął się dzięki podejściu typu try-error.
Przyznaję, że jest to podejście zasadniczo heurystyczne, ale jest naprawdę szybkie: natychmiast rozwiązuje wszystkie sprawy .
Wiem, że będą pewne błędy, ale do tej pory daje poprawne odpowiedzi na wszystkie przypadki testowe.
Wiem również, że wygrywa najkrótszy kod, ale jestem pewien, że jest to jeden z najkrótszych w najszybszym znaczeniu tego terminu.
Oto algorytm
badaj kropki i dla każdego segmentu między dwoma kropkami zapisz nachylenie, długość, punkt przecięcia x, punkt przecięcia y
znajdź linie proste (tj. trzy kropki lub dwa sąsiednie segmenty) i wyraźne możliwe nachylenia (powiedzmy, że są obrotami). Śledź najdłuższy segment dostępny w każdej linii.
znajdź wszystkie odległości między segmentem a trzecim punktem (należy to wykorzystać w punkcie 4). Śledź minimalną niezerową odległość.
dla dowolnych czterech kropek (mniej więcej prostokąta) znajdź wewnętrzne kropki
Pokaż rozwiązania:
A. Powiedz „Niemożliwe”, jeśli jest jedna lub więcej kropek wewnętrznych.
B. Jedna linia:
W przypadku większości kropek w jednej linii bez kropek wewnętrznych, powiedz „Możliwe”
W przypadku kropek zbyt blisko linii powiedz „Niemożliwe”
C. Dwie linie:
Powiedz „Możliwe”, gdy istnieje tylko jeden możliwy obrót
Powiedz „Niemożliwe”, gdy występuje więcej niż jeden obrót
D. Brak linii: znajdź obrót, który pasuje do jego segmentu obrotu o 90 °
Powiedz „Możliwe”, jeśli tylko jedna pasuje lub tyle, ile pasuje kropek.
Powiedz „Niemożliwe”, jeśli pasuje więcej niż jeden, a nie tyle kropek
Powiedz „Nieznany”, jeśli tyle pasuje do obrotu.
Oto kod (wszystkie znane błędy zostały rozwiązane)
A oto jego ouptut
Pozdrowienia.
Matteo.
źródło