Liczba bajtów zakłada kodowanie ISO 8859-1.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
Wiodące podawanie linii jest znaczące. Dane wejściowe i wyjściowe są zakończonymi podawaniem linii listami drukowalnych ciągów ASCII (zauważ, że oba mają jedno końcowe podawanie wiersza).
Wypróbuj online!
Przez jakiś czas wiedziałem, że transpozycja prostokątnych bloków byłaby uciążliwa dla siatkówki (podczas gdy transponowanie kwadratów nie jest takie złe), ale tak naprawdę nigdy nie próbowałem. Pierwsze rozwiązanie rzeczywiście miało aż 110 bajtów długości, ale po kilku istotnych zmianach w podejściu powstałe 45 bajtów nie jest tak złe, jak się spodziewałem (ale nadal ...). Wyjaśnienie nastąpi jutro.
Wyjaśnienie
Etap 1: Sortuj
O$#`.(?<=(.+))|¶
$.1
Wykonuje to główną pracę polegającą na zmianie kolejności znaków na wejściu, ale ostatecznie psuje podział na linie. Co ciekawe, jeśli usuniemy |¶, otrzymamy kod wymagany do transponowania kwadratowego wejścia.
Etapy sortowania (oznaczone przez O) działają w ten sposób: znajdują wszystkie dopasowania podanego wyrażenia regularnego (rzecz po `), a następnie sortują te dopasowania i umieszczają je ponownie w miejscach, w których znaleziono dopasowania. Tak się składa, że wyrażenie regularne dopasowuje każdy pojedynczy znak: nieliniowe poprzez .(?<=(.*))alternatywę i liniowe przez¶ . Dlatego sortuje wszystkie znaki na wejściu. Im bardziej interesujące jest to, co oni są klasyfikowane wg .
The $Opcja aktywuje „sortowania o trybie”, gdzie każda odpowiedź jest zastąpiony przez wzorzec podstawienia w drugiej linii, który jest następnie wykorzystywany do porównywania wyników. Ponadto #mówi Retinie, aby przekonwertowała wynik podstawienia na liczbę całkowitą i porównała te liczby całkowite (zamiast traktować je jak łańcuchy).
Wreszcie musimy przyjrzeć się wyrażeniu regularnemu i podstawieniu. Jeśli pierwsze alternatywne dopasowania (tzn. Dopasowaliśmy dowolny znak w jednej z linii), wówczas (?<=(.*))przechwytuje wszystko do tego znaku w tej linii w grupie 1. $.1We wzorcu podstawienia zastępuje to z długość grupy 1. Dlatego pierwszy znak w każdym ciągu staje1 , drugi staje się 2, trzeci staje się 3itd. Teraz powinno być jasne, jak to transponuje kwadratowe wejście: wszystkie pierwsze znaki linii są pierwsze i wszystkie kończą się na najwyższej linii, a następnie wszystkie drugie znaki kończą się w drugiej linii i tak dalej. Ale w przypadku tych prostokątnych danych wejściowych dopasowujemy również linie. Od grupy1nie jest używane w tym przypadku, podstawienie jest puste, ale dla celów #opcji jest to brane pod uwagę 0. Oznacza to, że wszystkie linie są sortowane do przodu.
Mamy teraz znaki w pierwszej kolejności (pierwszy znak każdego łańcucha, drugi znak każdego łańcucha itp.) I wszystkie linie na początku.
Etap 2: Mecz
!`(?<=(¶)+.*)(?<-1>.)+
Teraz musimy podzielić znaki na wiersze o odpowiedniej długości. Ta długość odpowiada liczbie linii na oryginalnym wejściu, co odpowiada liczbie linii, jakie mamy na początku łańcucha.
Podział odbywa się tutaj za pomocą etapu dopasowania, który po prostu wyszukuje wszystkie dopasowania podanego wyrażenia regularnego i używa !opcji drukowania tych dopasowań (domyślnie zamiast nich je policzymy). Zatem celem wyrażenia regularnego jest dopasowanie jednej linii na raz.
Zaczynamy od „liczenia” liczby za pomocą lookbehind (?<=(¶)*.*). Generuje jedno przechwytywanie w grupie 1dla każdego wysuwu linii z przodu.
Następnie dla każdego z tych ujęć dopasowujemy jedną postać (?<-1>.)+.