Martin Ender niedawno osiągnął 100 000 i wymyślił kilka niesamowitych języków . Będziemy się dobrze bawić z jednym z nich, Hexagony (i trochę wyrażenia regularnego dla Retina )
Krótko mówiąc, musisz napisać program, który wprowadza siatkę sześciokątną i określa, czy na tej siatce jest ścieżka, która pasuje do ciągu tekstu
Generowanie
Sześciokąt generuje sześciokąty z ciągu tekstowego, wykonując następujące kroki:
- Oblicz minimalny rozmiar sześciokąta (weź długość łańcucha i zaokrąglij w górę do najbliższej liczby szesnastkowej )
- Zawijanie tekstu w sześciokąt o powyższym rozmiarze
- Wypełnianie pozostałych lokalizacji
.
.
Na przykład ciąg tekstu abcdefghijklm
wymaga sześciokąta o długości 3 i dlatego staje się:
a b c
d e f g
h i j k l
m . . .
. . .
Teraz zauważ, że istnieje 6 możliwych kierunków, którymi możesz podróżować w sześciokącie. Na przykład w powyższym sześciokącie e
sąsiaduje z abfjid
.
Zawijanie
Ponadto w Hexagony, sześciokąty zawijają:
. . . . . a . . . . f . . a . .
a b c d e . . b . . . . g . . . b . . f
. . . . . . g . . c . . . . h . . a . c . . g .
. . . . . . . . h . . d . . . . u . . b . . d . . h . .
f g h i j k . i . . e . . j . . c . e . . i . .
. . . . . . j . . f k . . d . . . j . .
. . . . . k . . . . e . . k . .
Jeśli spojrzysz na drugi i czwarty przykład, zauważ, jak a
i k
jesteś w tych samych miejscach, mimo że owijasz się w różnych kierunkach. Z tego powodu miejsca te sąsiadują tylko z 5 innymi lokalizacjami .
Aby to wyjaśnić:
a b c d
e f g h i
j k l m n o
p q r s t u v
w x y z A B
C D E F G
H I J K
- Krawędzie owijają się na swoich przeciwnych sąsiadach (
b->I
iG->j
). - Górne / dolne rogi zawijają się w przeciwległym środkowym rogu oraz w górę / w dół (
d->K,p
iH->a,v
). - Środkowe narożniki są zawijane zarówno do górnego, jak i dolnego rogu (
v->a,H
)
Ścieżki
Ścieżka się sekwencję sąsiednich pozycjach, nie powraca do tej samej lokalizacji.
a b c
d e f g
h i f k l
m . . .
. . .
W powyższym sześciokącie aefkgm
jest poprawna ścieżka. Nie abfd
jest to jednak poprawna ścieżka ( f
i d
nie sąsiadują) i abea
nie jest poprawna (wraca do a
lokalizacji).
Możemy użyć tych ścieżek do dopasowania tekstu (np. Regex) . Znak alfanumeryczny pasuje do siebie (i tylko do siebie), a .
dopasowuje dowolny znak. Na przykład, ścieżka aej..lgm
będzie pasować aej..lgm
, aejAAlgm
, aeja.lgm
, lub aej^%gm
.
Wejście wyjście
Twój program powinien przyjąć dwa ciągi (w dowolnej kolejności). Pierwszy ciąg będzie niepusty i będzie się składał wyłącznie ze znaków alfanumerycznych [a-zA-Z0-9]
. Będzie to reprezentowało sześciokąt, na którym operujesz. Drugi ciąg znaków będzie się składał ze znaków do wydrukowania.
Musisz zwrócić prawdziwą wartość, jeśli w sześciokącie znajduje się ścieżka pasująca do podanego ciągu tekstu, w przeciwnym razie wartość fałszowania.
Przypadki testowe
Prawda:
"a","a"
"ab","a"
"ab","b"
"ab","ba"
"ab","aba"
"ab","&"
"ab","#7.J!"
"ab","aaaaaa"
"ab","bgjneta"
"ab","cebtmaa"
"abcdefg","dfabcg"
"AbCDeFG","GCbAeFD"
"aaaabbb","aaababb"
"abcdefghijklmnopqrs","alq"
"abcdefghijklmnopqrs","aqnmiedh"
"abcdefghijklmnopqrs","adhcgkorbefjimnqlps"
"11122233344455","12341345123245"
"abcdefgh","h%a"
"abcdefghijklm","a)(@#.*b"
"abcdefghijklm","a)(@#.*i"
"abcdefghij","ja"
"abcdefghijklmno","kgfeia"
"abcdefghijklmno","mmmmmiea"
"abcdefghijklmno","mmmmmlae"
"abcdefghijklmno","ja"
"abcdefghijklmnopqrs","eijfbadhmnokgcsrql"
Falsy:
"a","b"
"a","%"
"a","."
"a","aa"
"a","a."
"ab","#7.J!*"
"ab","aaaaaaa"
"ab","aaaabaaa"
"ab","123456"
"abcdefg","bfgedac"
"abcdefg","gecafdb"
"abcdefg","GCbaeFD"
"aaaabbb","aaaaabb"
"abcdefghijklmnopqrs","aqrcgf"
"abcdefghijklmnopqrs","adhlcgknbeifjm"
"abcdefghijklmnopqrs","ja"
"abcdefghijklm","a)(@#.*&"
"abcdefghijklmno","a)(@bfeijk"
"abcdefghijklmno","kgfeic"
"abcdefghijklmno","mmmmmmiea"
To jest gra w golfa , więc udziel odpowiedzi tak krótko, jak to możliwe, w swoim ulubionym języku.
źródło
Odpowiedzi:
Retina , 744 bajty
Przepraszam, tym razem brak heksagonii ...
Liczba bajtów zakłada kodowanie ISO 8859-1.
Oczekuje ciągu docelowego w pierwszym wierszu i sześciokąta w drugim wierszu danych wejściowych. Drukuje
0
lub1
odpowiednio.Wypróbuj online! (Pierwszy wiersz włącza zestaw testowy, gdzie każdy wiersz jest przypadkiem testowym, używającym
¦
do separacji zamiast podawania linii).Właściwym sposobem rozwiązania tego problemu jest oczywiście wyrażenie regularne. ;) A gdyby nie to, że wyzwanie to obejmuje również procedurę rozwijania sześciokąta , odpowiedź ta składałaby się tylko z jednego ~ 600-bajtowego wyrażenia regularnego.
Nie jest to jeszcze optymalnie zoptymalizowane, ale jestem bardzo zadowolony z wyniku (moja pierwsza działająca wersja, po usunięciu nazwanych grup i innych rzeczy wymaganych dla zdrowia psychicznego, miała około 1000 bajtów). Myślę, że mógłbym zaoszczędzić około 10 bajtów, zamieniając kolejność łańcucha i sześciokąta, ale wymagałoby to całkowitego przepisania wyrażenia regularnego na końcu, czego nie czuję teraz. Istnieje również 2-bajtowa oszczędność poprzez pominięcie
G
sceny, ale znacznie spowalnia to rozwiązanie, więc poczekam z wprowadzeniem tej zmiany, dopóki nie upewnię się, że grałem w nią najlepiej, jak potrafię.Wyjaśnienie
Główna część tego rozwiązania w szerokim zakresie wykorzystuje grupy równoważące , więc polecam je przeczytać, jeśli chcesz zrozumieć, jak to działa w szczegółach (nie obwiniam cię, jeśli nie ...).
Pierwsza część rozwiązania (tj. Wszystko oprócz dwóch ostatnich wierszy) to zmodyfikowana wersja mojej odpowiedzi na Unfolding the Hexagony code source . Konstruuje sześciokąt, pozostawiając nietknięty ciąg docelowy (i faktycznie tworzy sześciokąt przed ciągiem docelowym). Wprowadziłem pewne zmiany w poprzednim kodzie, aby zapisać bajty:
×
zamiast spacji, aby nie powodował konfliktu z potencjalnymi spacjami na wejściu._
Zamiast tego występuje znak „brak operacji / symbol wieloznaczny”.
, dzięki czemu komórki siatki mogą być niezawodnie identyfikowane jako znaki słowne.Oto przykład. Dla następującego przypadku testowego:
Otrzymujemy:
Porównaj to ze zwykłym układem sześciokąta:
Widzimy, że sąsiedzi są teraz zwykłymi 8 sąsiadami Moore, z wyjątkiem północno-zachodnich i południowo-wschodnich sąsiadów. Musimy więc sprawdzić przyleganie poziome, pionowe i południowo-zachodnie / północno-wschodnie (dobrze, a potem są krawędzie owijania). Korzystanie z tego bardziej zwartego układu ma również tę zaletę, że będziemy mogli wykorzystać je
××
na końcu, aby określić rozmiar sześciokąta w locie, gdy go potrzebujemy.Po zbudowaniu tego formularza wprowadzamy jeszcze jedną zmianę do całego łańcucha:
Zastępuje to cyfry rozszerzonymi literami ASCII
Ponieważ są one zastępowane zarówno w sześciokącie, jak i w ciągu docelowym, nie wpłynie to na to, czy ciąg zostanie dopasowany, czy nie. Ponadto, ponieważ są to litery
\w
i\b
nadal identyfikują je jako komórki sześciokąta. Zaletą wykonania tej zamiany jest to, że możemy teraz użyć\D
w nadchodzącym wyrażeniu regularnym, aby dopasować dowolny znak (w szczególności znaki linefeed, a także znaki non-linefeed). Nie możemy skorzystać zs
opcji, aby to osiągnąć, ponieważ.
w wielu miejscach będziemy musieli dopasować znaki nieciągłe.Teraz ostatni bit: ustalenie, czy jakakolwiek ścieżka pasuje do naszego podanego ciągu. Odbywa się to za pomocą jednego monstrualnego wyrażenia regularnego. Możesz zadać sobie pytanie, dlaczego?!?! Cóż, jest to zasadniczo problem z cofaniem się: zaczynasz gdzieś i próbujesz ścieżki, dopóki pasuje ona do łańcucha, a kiedy już nie, wycofujesz się i próbujesz innego sąsiada od ostatniej działającej postaci. Jednoktóre otrzymujesz za darmo podczas pracy z regexem jest cofanie się. To dosłownie jedyna rzecz, którą robi silnik regex. Jeśli więc znajdziemy sposób na opisanie prawidłowej ścieżki (co jest dość skomplikowane dla tego rodzaju problemu, ale z pewnością możliwe w przypadku grup równoważących), wówczas silnik wyrażenia regularnego wyszuka znalezienie tej ścieżki wśród wszystkich możliwych dla nas. Z pewnością byłoby możliwe ręczne zaimplementowanie wyszukiwania na wielu etapach ( a robiłem to w przeszłości ), ale wątpię, aby w tym konkretnym przypadku było ono krótsze.
Jednym z problemów związanych z implementacją tego z wyrażeniem regularnym jest to, że nie możemy arbitralnie przecinać kursora silnika wyrażenia regularnego w przód iw tył przez łańcuch podczas cofania (co byłoby nam potrzebne, ponieważ ścieżka może iść w górę lub w dół). Zamiast tego śledzimy własnego „kursora” w grupie przechwytywania i aktualizujemy go na każdym kroku (możemy tymczasowo przejść do pozycji kursora za pomocą obejrzenia). Dzięki temu możemy również przechowywać wszystkie poprzednie pozycje, których użyjemy, aby sprawdzić, czy nie odwiedziliśmy poprzedniej pozycji.
Przejdźmy więc do tego. Oto nieco rozsądniejsza wersja wyrażenia regularnego, z nazwanymi grupami, wcięciami, mniej losową kolejnością sąsiadów i kilkoma komentarzami:
Mam nadzieję, że ogólna idea jest w przybliżeniu jasna z tego. Jako przykład działania jednego z tych ruchów wzdłuż ścieżki, spójrzmy na bit, który przesuwa kursor na południe:
Pamiętaj, że spojrzenia powinny być odczytywane od prawej do lewej (lub od dołu do góry), ponieważ w takiej kolejności są wykonywane:
Zauważ, że nie jest konieczne umieszczanie kotwicy przed,
\k<pos>
aby upewnić się, że faktycznie osiągnie początek łańcucha.<pos>
zawsze zaczyna się od ilości×
, której nie można znaleźć nigdzie indziej, więc działa to już jako ukryta kotwica.Nie chcę przesadzać z tym postem bardziej niż to konieczne, więc nie będę szczegółowo omawiał pozostałych 11 przypadków, ale w zasadzie wszystkie działają podobnie. Sprawdzamy,
<next>
czy można znaleźć w jakimś określonym (dopuszczalnym) kierunku od starej pozycji kursora za pomocą grup równoważących, a następnie przechowujemy ciąg znaków do tego dopasowania jako nową pozycję kursora w<pos>
.źródło
Python 3,
990943770709 bajtówPierwsza odpowiedź, tak!
EDYCJA: Tworzenie listy sąsiadów golfowych. Teraz używam nieco innej formuły
EDYCJA 2: Usunąłem niepotrzebny puch, grałem w golfa o wiele więcej.
EDYCJA 3: Skrócono kod konwersji z indeksu na liście do współrzędnych, grałem w golfa jeszcze kilka rzeczy.
Większość bajtów dotyczy tworzenia listy sąsiadów (ma ona największy potencjał do gry w golfa). Odtąd jest to prosta sprawa brutalnego wymuszania rozwiązania (co może być w stanie zrobić w mniejszej liczbie bajtów).
Gra w golfa:
Ungolfed z wyjaśnieniem:
Tak blisko Retina! :(Tak, pokonaj Retinę!źródło
JavaScript (ES6),
511500496 bajtówNie golfił i skomentował
Przypadki testowe
Poniższy fragment omówi wszystkie przypadki testowe zgodne z prawdą i fałszem.
Pokaż fragment kodu
źródło