tło
Trójkąt pitagorejski to trójkąt prostokątny, w którym każda długość boku jest liczbą całkowitą (to znaczy długości boku tworzą potrójną pitagorejską trójkę ):
Używając boków tego trójkąta, możemy dołączyć dwa kolejne niespójne trójkąty pitagorejskie w następujący sposób:
Możemy kontynuować ten wzór według własnego uznania, o ile dwa trójkąty nie zachodzą na siebie, a boki łączące mają równą długość:
Pytanie brzmi: ile nie przystających pitagorejskich trójkątów możemy zmieścić w danej przestrzeni?
Wejście
Otrzymasz dwie liczby całkowite jako dane wejściowe W
i H
, poprzez argumenty funkcji, STDIN, ciągi znaków lub cokolwiek zechcesz. Liczby całkowite mogą być odbierane jako dziesiętne, szesnastkowe, binarne, jednoargumentowe (powodzenia, siatkówki ) lub dowolne inne liczby całkowite. Możesz to założyćmax(W, H) <= 2^15 - 1
.
Wyjście
Twój program lub funkcja powinna obliczyć listę nie nakładających się połączonych niespójnych trójkątów pitagorejskich i wygenerować listę zestawów trzech współrzędnych, gdzie współrzędne w zestawie tworzą jeden z trójkątów pitagorejskich, gdy są połączone liniami. Współrzędne muszą być liczbami rzeczywistymi w naszej przestrzeni ( x
muszą znajdować się w przedziale [0, W]
i y
muszą znajdować się w przedziale[0, H]
), a odległość powinna być dokładna z dokładnością do maszyny. Kolejność trójkątów i dokładny format każdej współrzędnej nie jest ważny.
Musi istnieć możliwość „przejścia” z jednego trójkąta do innego, tylko przekraczając połączone granice.
Korzystając z powyższego diagramu jako przykładu, niech nasze dane wejściowe będą W = 60
,H = 60
.
Naszym wynikiem może być następująca lista współrzędnych:
(0, 15), (0, 21), (8, 15)
(0, 21), (14.4, 40.2), (8, 15)
(0, 15), (8, 0), (8, 15)
(8, 0), (8, 15), (28, 15)
(8, 15), (28, 15), (28, 36)
(28, 15), (28, 36), (56, 36)
Teraz 6 trójkątów z pewnością nie jest najlepszym, co możemy zrobić, biorąc pod uwagę naszą przestrzeń. Czy potrafisz lepiej?
Zasady i punktacja
Twój wynik w tym wyzwaniu to liczba trójkątów wygenerowanych przez Twój program na podstawie danych wejściowych
W = 1000, H = 1000
. Zastrzegam sobie prawo do zmiany tego wejścia, jeśli podejrzewam, że ktoś na stałe zakodował tę sprawę.Nie możesz używać wbudowanych funkcji, które obliczają tróje pitagorejskie, i nie możesz zakodować na stałe listy więcej niż 2 trójek pitagorejskich (jeśli na stałe zakodujesz program, aby zawsze zaczynał się od trójkąta (3, 4, 5) lub w podobnych okolicznościach początkowych, które jest ok).
Możesz napisać swoje zgłoszenie w dowolnym języku. Zachęcamy do czytelności i komentowania.
Możesz znaleźć listę trójek pitagorejskich tutaj .
Standardowe luki są niedozwolone.
źródło
Odpowiedzi:
Python 3, 109
Było to z pewnością trudne wyzwanie. Wiele razy pisałem kod, w którym zastanawiałem się nad moimi podstawowymi umiejętnościami w zakresie geometrii. Biorąc to pod uwagę, jestem całkiem zadowolony z wyniku. Nie starałem się wymyślić skomplikowanego algorytmu umieszczania trójkątów, a zamiast tego mój kod po prostu mylnie, zawsze umieszczając najmniejsze, jakie może znaleźć. Mam nadzieję, że uda mi się to później poprawić, w przeciwnym razie moja odpowiedź skłoni innych do znalezienia lepszego algorytmu! Podsumowując, jest to bardzo zabawny problem, który daje ciekawe zdjęcia.
Oto kod:
Oto wykres wyjście do
W = 1000
iH = 1000
z 109 trójkątów:Oto
W = 10000
iH = 10000
ze 724 trójkątów:Wywołaj
matplotlib_graph()
funkcję pobuild_all_triangles()
aby narysować wykres trójkątów.Myślę, że kod działa dość szybko: o
W = 1000
iH = 1000
zajmuje 0,66 sekundy, a oW = 10000
iH = 10000
zajmuje 45 sekund przy użyciu mojego kiepskiego laptopa.źródło
C ++, 146 trójkątów (część 1/2)
Wynik jako obraz
Opis algorytmu
Wykorzystuje to pierwsze wyszukiwanie przestrzeni rozwiązania. Na każdym etapie rozpoczyna się od wszystkich unikalnych konfiguracji
k
trójkątów pasujących do pudełka i tworzy wszystkie unikalne konfiguracjek + 1
trójkątów, wyliczając wszystkie opcje dodania nieużywanego trójkąta do dowolnej konfiguracji.Algorytm jest skonfigurowany tak, aby znaleźć absolutne maksimum przy wyczerpującym BFS. I robi to z powodzeniem w przypadku mniejszych rozmiarów. Na przykład w przypadku pudełka o wymiarach 50 x 50 maksimum znajduje się po około 1 minucie. Ale dla 1000x1000 przestrzeń rozwiązania jest zdecydowanie za duża. Aby umożliwić zakończenie, przycinam listę rozwiązań po każdym kroku. Liczba zachowanych rozwiązań jest podana w argumencie wiersza poleceń. Dla powyższego rozwiązania zastosowano wartość 50. Spowodowało to czas działania około 10 minut.
Zarys głównych kroków wygląda następująco:
Jednym z kluczowych aspektów całego schematu jest to, że konfiguracje będą generowane wielokrotnie, a interesują nas tylko unikalne konfiguracje. Potrzebujemy więc unikalnego klucza, który definiuje rozwiązanie, które musi być niezależne od kolejności trójkątów używanych podczas generowania rozwiązania. Na przykład użycie współrzędnych dla klucza w ogóle nie zadziałałoby, ponieważ mogą one być zupełnie inne, jeśli dojdziemy do tego samego rozwiązania w wielu zamówieniach. Użyłem zestawu wskaźników trójkątów na liście globalnej oraz zestawu obiektów „łączników”, które określają sposób łączenia trójkątów. Tak więc klucz koduje tylko topologię, niezależnie od kolejności budowy i położenia w przestrzeni 2D.
Chociaż bardziej aspekt implementacji, kolejna część, która nie jest całkowicie trywialna, decyduje, czy i jak całość pasuje do danego pudełka. Jeśli naprawdę chcesz przesunąć granice, oczywiście konieczne jest umożliwienie obrotu w celu dopasowania do ramki.
Spróbuję dodać komentarze do kodu w części 2 później, na wypadek, gdyby ktoś chciał zagłębić się w szczegóły tego, jak to wszystko działa.
Wynik w oficjalnym formacie tekstowym
Kod
Kod zawiera część 2. Zostało to podzielone na 2 części, aby obejść limity wielkości słupków.
Kod jest również dostępny na PasteBin .
źródło
C ++, 146 trójkątów (część 2/2)
Ciąg dalszy od części 1. Został on podzielony na 2 części, aby obejść limity wielkości słupków.
Kod
Komentarze do dodania.
źródło