W tym wyzwaniu będziesz liczyć „stwory” w grze Palago.
Stworzenie to dowolny zamknięty kształt, który można uformować z płytek Palago w tym samym kolorze w sześciokątnej siatce.
Gra Palago składa się z takich płytek:
Płytki te można obracać o , lub wcale, i umieszczać w dowolnym miejscu na sześciokątnej siatce. Na przykład tutaj jest (czerwone) stworzenie, które wymaga 12 płytek.
Wyzwanie
Celem tego wyzwania jest napisanie programu, który przyjmuje liczbę całkowitą n
jako dane wejściowe i oblicza liczbę stworzeń (do obrotu i odbicia), które wymagają n
płytek. Program powinien być w stanie obsłużyć maksymalnie n=10
na TIO . To jest golf golfowy , więc wygrywa najmniej bajtów.
Przykładowe dane
Wartości powinny odpowiadać danym znajdującym się w sekcji „Obliczenia i oszacowania stworów” na stronie internetowej twórcy . Mianowicie
n | output
---+-------
1 | 0
2 | 0
3 | 1
4 | 0
5 | 1
6 | 1
7 | 2
8 | 2
9 | 9
10 | 13
11 | 37
12 | 81
źródło
n=10
TIO”. - jeśli jest to wymaganie dotyczące szybkości wykonywania, zamiast kodu golfowego należy użyć code-challenge , który odnosi się do zadania optymalizacji bajtów.Odpowiedzi:
JavaScript (Node.js) ,
480417 bajtów-63 bajty dzięki @Arnauld. Łał.
Wypróbuj online!
Po pierwsze, uszanuj Arnaulda, którego odpowiedź zainspirowała mnie do głębszego kopania. Starałem się być oryginalny w swoich algorytmach, chociaż celowo zmieniłem część mojego kodu, aby używał tych samych zmiennych, co Arnauld, aby kod był łatwiejszy do porównania.
Wyszukiwanie pustych heksów
Poszukiwanie stworzeń to:
Poszukiwanie pustych heksów odkryło interesującą symetrię. Arnauld odkrył, że jeden z sześciu kierunków można zignorować, ale w rzeczywistości trzy z sześciu można zignorować!
Oto oryginalny kierunek i kafelek Arnaulda:
Wyobraźmy sobie, że zaczynamy od płytki A typu 1 w niebieskiej kropce. Wygląda na to, że musimy powtórzyć się d = 0 id = 5. Jednak niezależnie od tego, który kafelek zostanie umieszczony w d = 0, na pewno będzie miał wyjście w d = 4, które odwiedzi ten sam hex, co wyjście z płytki A w d = 5. To odkrycie Arnaulda i to właśnie sprawiło, że zacząłem myśleć.
Zauważ, że:
Każdy kafelek, który ma wyjście d = 4, ma wyjście id = 3
Każdy kafelek, który można wprowadzić z d = 0, ma wyjście d = 4
Oznacza to, że musimy brać pod uwagę tylko kierunki 0,2,4. Wszelkie wyjścia w kierunkach 1,3,5 można zignorować, ponieważ heksy osiągalne w kierunkach 1,3,5 można zamiast tego dotrzeć z sąsiedniego heksa, używając kierunków 0,2 lub 4.
Jakie to jest świetne!?
Przeprojektowane kierunki
Ponownie opisuję wskazówki i kafelki w ten sposób (edytowany obraz Arnaulda):
Teraz mamy następujący związek między kafelkami, wejściami i wyjściami:
Wyjścia to: d + t == 2? (4-t)% 3: 2-t i 2 * t% 3
Obroty i odbicia sześciokątne
W przypadku obrotów i odbić postanowiłem wypróbować sześciokątne współrzędne osi x, y zamiast współrzędnych sześcianu x, y, z.
W tym systemie rotacja i odbicie były prostsze niż się spodziewałem:
Aby uzyskać wszystkie kombinacje, które wykonałem: gnij, gnij, gnij, odbijaj, gnij, gnij
Kod (oryginalny 480 bajtów)
Kod (bajt Arnauld 417)
Arnauld uprzejmie podał 63-bajtową oszczędność, która wykorzystywała sztuczki, które zajęły mi sporo czasu, aby owinąć głowę. Ponieważ zawiera wiele interesujących zmian, pomyślałem, że umieszczę jego kod poniżej (dodałem swoje komentarze), aby można go było kontrastować z moją wersją.
źródło
JavaScript (Node.js) ,
578 ... 433431 bajtówW jaki sposób?
Wskazówki i kafelki
Używamy następujących kodów dla 6-kierunkowego kompasu i kafelków:
Zakładamy, że stworzenie jest niebieskie.
Znajomości
Potrzebujemy tabeli, aby wiedzieć, które części stworzenia muszą być połączone z innymi płytkami, gdy wejdziemy na dany kafelek w danym kierunku:
Przykład:
Po spłaszczeniu daje to:
Współrzędne
Kredyty: www.redblobgames.com
Ułatwi to przetwarzanie obrotów i odbić na ostatnim etapie algorytmu.
Kodowanie kafelków
Kafelki są przechowywane na liście, bez określonej kolejności. Oznacza to, że nie musimy się martwić o dynamiczną alokację 2D i możemy z łatwością iterować na istniejących kafelkach. Minusem jest to, że przy określonych współrzędnych potrzebujemy
find()
odpowiedniego kafelka na liście.Algorytm
Dlatego ten kafelek jest zakodowany jako
[0,0,0,1,1]
.Przy każdej iteracji szukamy:
Płytki z brakującymi połączeniami: w tym przypadku sukcesywnie próbujemy zakończyć połączenie z każdym rodzajem płytki.
Kafelki, które są już połączone, ale do których należy dodać nowe połączenia, ponieważ zostały osiągnięte w innym kierunku: w tym przypadku aktualizujemy maskę kierunku (z bitowym OR) i wymuszamy nową iterację.
Jeśli wszystkie połączenia są prawidłowe i osiągnęliśmy żądaną liczbę kafelków, nadal musimy sprawdzić, czy jest to nowe stworzenie, czy tylko zmodyfikowana wersja istniejącego:
Stosujemy następujące przekształcenia:
Wykonujemy 3 odpowiednie odbicia, zastępując( x , y) z ( y, x ) , ( z, y) lub ( x , z) i odpowiednio aktualizując typy kafelków.
Dla każdej transformacji tłumaczymy wszystkie płytki tak, aby zawsze znajdował się w prawym dolnym rogu( 0 , 0 ) . (Znaki współrzędnych są odwracane w procesie, co technicznie prowadzi do kolejnego odbicia, ale jest to nieszkodliwe).
Sortujemy płytki według ich współrzędnych i typów. (Ten rodzaj jest przetwarzany w porządku leksykograficznym, co jest w porządku.)
W końcu zmuszamy wynikową listę do klucza, który można porównać z innymi kluczami.
Przerywamy, gdy tylko dopasowany zostanie znany klucz, lub przechowujemy nowy klucz i zwiększamy końcowy wynik, jeśli żadna z transformacji nie prowadzi do znanego klucza.
Skomentował
źródło