Wprowadzenie
Jeśli nie znasz Hexagony , jest to ezoteryczny język stworzony przez Martina Büttnera. Chodzi o to, że ten język akceptuje wiele formularzy dla programu. Następujące programy są równoważne:
abcdefg
i
a b
c d e
f g
Zasadniczo kod został zwinięty w zwykły sześciokąt. Należy jednak pamiętać, że dodanie nowego kodu do kodu, które abcdefgh
byłoby wynikiem w następującym programie:
a b c
d e f g
h . . . .
. . . .
. . .
Jak widać, pierwszym krokiem jest zrolowanie kodu do sześciokąta, a następnie sześciokąt zostaje wypełniony opcjami „no” ( .
) do następnej wyśrodkowanej liczby heksagonalnej .
Twoje zadanie jest proste, gdy otrzymasz ciąg znaków (kod źródłowy), wypisz pełny sześciokątny kod źródłowy.
Zasady
- Możesz podać program lub funkcję.
- Wiodące białe znaki są dozwolone, ale tylko wtedy, gdy sześciokąt nie wychodzi z kształtu
- Końcowe białe znaki są dozwolone.
- Zauważ, że białe znaki w programie są ignorowane . Więc
a b c
jest równyabc
32 - 126
Używane są tylko drukowalne znaki ASCII ( ), więcSpace
ignorowany jest tylko zwykły znak.- Załóżmy, że długość ciągu jest większa niż 0.
- To jest golf golfowy , więc wygrywanie z najmniejszą ilością bajtów wygrywa!
Przypadki testowe
Input: ?({{&2'2':{):!/)'*/
Output:
? ( {
{ & 2 '
2 ' : { )
: ! / )
' * /
Input: H;e;l;d;*;r;o;Wl;;o;*433;@.>;23<\4;*/
Output:
H ; e ;
l ; d ; *
; r ; o ; W
l ; ; o ; * 4
3 3 ; @ . >
; 2 3 < \
4 ; * /
Input: .?'.) .@@/'/ .!.> +=(<.!)} ( $>( <%
Output:
. ? ' .
) . @ @ /
' / . ! . >
+ = ( < . ! )
} ( $ > ( <
% . . . .
. . . .
abc`defg
naprawdę stałby się pastebin.com/ZrdJmHiR`
znaków)”.Odpowiedzi:
Pyth,
575450494846Pakiet testowy
Drukuje spację wiodącą w każdej linii.
Ta wersja wymaga dowodu, że 10 ^ n> = 3n (n - 1) + 1 dla wszystkich n> = 1 . Dzięki ANerdI i ErickWong za dostarczenie dowodów.
Po tych nierównościach: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 łatwo można zauważyć, że jest to poprawne dla n> = 2 . Badanie przypadku n = 1 jest dość trywialne, dając 10> 1 .
Alternatywnie, dwukrotne pobranie pochodnych tych równań pokazuje, że 10 ^ n ma większą drugą pochodną dla wszystkich n> = 1 , które można następnie kaskadowo obniżyć do pierwszych pochodnych, a na koniec do pierwotnych równań.
Wyjaśnienie
źródło
Sześciokąty , 271 bajtów
Przedstawiam wam, pierwsze 3% autopretera Hexagony ...
Wypróbuj online! Możesz także uruchomić go na sobie, ale zajmie to około 5-10 sekund.
Zasadniczo może się to zmieścić w boku o długości 9 (dla wyniku 217 lub mniej), ponieważ używa tylko 201 poleceń, a wersja bez golfa, którą napisałem jako pierwsza (na boku o długości 30), potrzebowała tylko 178 poleceń. Jestem jednak pewien, że wszystko zajmie wieczność, więc nie jestem pewien, czy spróbuję.
Powinno być także możliwe zagranie w golfa nieco w rozmiarze 10, unikając użycia ostatniego jednego lub dwóch rzędów, tak aby można było pominąć końcowe brakujące operacje, ale wymagałoby to znacznego przepisania, jako jednej z pierwszych ścieżek złączenia wykorzystuje lewy dolny róg.
Wyjaśnienie
Zacznijmy od rozwinięcia kodu i opatrzenia adnotacjami ścieżek kontroli:
To wciąż dość niechlujny, więc oto ten sam schemat dla kodu „nie golfowego”, który napisałem jako pierwszy (w rzeczywistości jest to długość boku 20 i pierwotnie napisałem kod na boku długości 30, ale był tak rzadki, że nie w ogóle nie poprawiają czytelności, więc trochę go skompaktowałem, aby rozmiar był bardziej rozsądny):
Kliknij, aby zobaczyć większą wersję.
Kolory są dokładnie takie same, z wyjątkiem kilku bardzo drobnych szczegółów, polecenia niekontrolowanego przepływu również są dokładnie takie same. Wyjaśnię więc, jak to działa w oparciu o wersję bez golfa, a jeśli naprawdę chcesz wiedzieć, jak działa gra w golfa, możesz sprawdzić, które części odpowiadają tym w większym sześciokącie. (Jedynym haczykiem jest to, że kod do gry w golfa zaczyna się od lustra, tak że rzeczywisty kod zaczyna się w prawym rogu, po lewej stronie.)
Podstawowy algorytm jest prawie identyczny z moją odpowiedzią CJam . Istnieją dwie różnice:
.
zamiast tego wypisuję polecenie .Oznacza to, że podstawowa idea sprowadza się do:
N
(i odpowiadającą jej wyśrodkowaną liczbę sześciokątnąhex(N)
), która może pomieścić całe dane wejściowe.2N-1
.2N-1
). Wydrukuj wcięcie, wydrukuj komórki (używając,.
jeśli dane wejściowe są już wyczerpane), wydrukuj linię.Zauważ, że nie ma żadnych operacji, więc rzeczywisty kod zaczyna się w lewym rogu (ten
$
, który przeskakuje nad>
, więc naprawdę zaczynamy od,
ciemnoszarej ścieżki).Oto początkowa siatka pamięci:
Wskaźnik pamięci zaczyna się od wejścia oznaczonego krawędziami , wskazując na północ.
,
czyta bajt ze STDIN lub a,-1
jeśli trafiliśmy EOF w tę krawędź. Dlatego<
zaraz po tym jest warunek, czy przeczytaliśmy wszystkie dane wejściowe. Pozostańmy na razie w pętli wejściowej. Następny kod, który wykonujemy, toSpowoduje to zapisanie 32 w przestrzeni oznaczonej krawędzią , a następnie odejmuje ją od wartości wejściowej w różnicy oznaczonej krawędzią . Zauważ, że to nigdy nie może być ujemne, ponieważ gwarantujemy, że dane wejściowe zawierają tylko drukowalne ASCII. Wyniesie zero, gdy wejście będzie spacją. (Jak wskazuje Timwi, nadal działałoby to, gdyby dane wejściowe mogły zawierać linie lub tabulatory, ale również usuwałyby wszystkie inne niedrukowalne znaki o kodach znaków mniejszych niż 32.) W takim przypadku
<
odchyla wskaźnik instrukcji (IP) w lewo i wybrano jasnoszarą ścieżkę. Ta ścieżka po prostu resetuje pozycję MP za pomocą,{=
a następnie odczytuje następny znak - w ten sposób spacje są pomijane. W przeciwnym razie, jeśli postać nie jest spacją, wykonujemyTo najpierw porusza się wokół sześciokąta przez krawędź długości, aż znajdzie się naprzeciwko krawędzi różnicy , przy pomocy
=}}}
. Następnie kopiuje wartość z naprzeciwko długości krawędzi do długości krawędzi i inkrementuje się)&'+'+)
. Zobaczymy za chwilę, dlaczego ma to sens. Wreszcie przenosimy nową przewagę dzięki=}
:(Konkretne wartości krawędzi pochodzą z ostatniego przypadku testowego podanego w wyzwaniu). W tym momencie pętla się powtarza, ale wszystko przesuwa się o jeden sześciokąt na północny wschód. Po przeczytaniu innej postaci otrzymujemy:
Teraz możesz zobaczyć, że stopniowo zapisujemy dane wejściowe (minus spacje) wzdłuż północno-wschodniej przekątnej, z znakami na każdej drugiej krawędzi, a długość do tego znaku jest przechowywana równolegle do długości oznaczonej krawędzi .
Kiedy skończymy z pętlą wejściową, pamięć będzie wyglądać następująco (gdzie już oznaczyłem kilka nowych krawędzi dla następnej części):
Jest
%
to ostatni znak, który czytamy,29
to liczba znaków spacji, które czytamy. Teraz chcemy znaleźć długość boku sześciokąta. Po pierwsze, na ciemnozielonej / szarej ścieżce znajduje się kod liniowej inicjalizacji:Tutaj
=&
skopiuj długość (29 w naszym przykładzie) na długość oznaczoną krawędzią . Następnie''3
przechodzi do krawędzi oznaczonej jako 3 i ustawia jego wartość na3
(której potrzebujemy po prostu jako stałej w obliczeniach). Na koniec{
przechodzi do krawędzi oznaczonej jako N (N-1) .Teraz wchodzimy w niebieską pętlę. Przyrosty pętli
N
(przechowywane w komórce oznaczonej jako N ) obliczają następnie wyśrodkowaną liczbę heksagonalną i odejmują ją od długości wejściowej. Kod liniowy, który to robi, to:Tutaj,
{)
przesuwa się i zwiększa N .')&(
przesuwa się do krawędzi oznaczonej jako N-1 , kopiujeN
tam i zmniejsza ją.{=*
oblicza swój produkt w N (N-1) .'*)
mnoży to przez stałą3
i inkrementuje wynik na krawędzi oznaczonej hex (N) . Zgodnie z oczekiwaniami jest to n-ta środkowa liczba heksagonalna. Na koniec'-
oblicza różnicę między tym a długością wejściową. Jeśli wynik jest dodatni, długość boku nie jest jeszcze wystarczająco duża, a pętla powtarza się (tam, gdzie}}
przesuwa się MP z powrotem do krawędzi oznaczonej N (N-1) ).Gdy długość boku będzie wystarczająco duża, różnica wyniesie zero lub będzie ujemna i otrzymamy to:
Po pierwsze, jest teraz naprawdę długa zielona liniowa ścieżka, która dokonuje niezbędnej inicjalizacji pętli wyjściowej:
Do
{=&
rozpoczyna kopiując wynik w diff krawędzi do długości krawędzi, bo później trzeba coś tam non-dodatnich.}}}32
zapisuje 32 w spacji oznaczonej krawędzią .'"2
zapisuje stałą 2 w nieoznakowanej krawędzi nad różnicą .'=&
kopiujeN-1
na drugą krawędź z tą samą etykietą.'*)
mnoży go przez 2 i zwiększa, aby uzyskać prawidłową wartość na krawędzi oznaczonej 2N-1 u góry. Jest to średnica sześciokąta.{=&')&
kopiuje średnicę na drugą krawędź oznaczoną 2N-1 . Na koniec}}
przesuwa się z powrotem do krawędzi oznaczonej 2N-1 u góry.Ponownie oznakuj krawędzie:
Krawędź, na której się obecnie znajdujemy (która nadal ma średnicę sześciokąta), zostanie wykorzystana do iteracji po liniach wyjścia. Wcięcie oznaczone krawędzią obliczy, ile spacji jest potrzebnych w bieżącym wierszu. Komórki oznaczone krawędzią zostaną użyte do iteracji po liczbie komórek w bieżącym wierszu.
Jesteśmy teraz na różowej ścieżce, która oblicza wcięcie .
('-
zmniejsza iterator linii i odejmuje go od N-1 (do krawędzi wcięcia ). Krótka niebieska / szara gałąź w kodzie po prostu oblicza moduł wyniku (~
neguje wartość, jeśli jest ujemna lub zero, i nic się nie dzieje, jeśli jest dodatnia). Reszta różowej ścieżki"-~{
odejmuje wcięcie od średnicy do krawędzi komórki, a następnie przesuwa się z powrotem do krawędzi wcięcia .Brudna żółta ścieżka drukuje teraz wcięcie. Zawartość pętli jest naprawdę sprawiedliwa
Gdzie
'"
przesuwa się do krawędzi przestrzeni ,;
drukuje ją,{}
wraca do wcięcia i(
zmniejsza.Kiedy skończymy, (druga) ciemnoszara ścieżka szuka następnego znaku do wydrukowania. W
=}
przesuwa się w pozycji (co oznacza, na komórki krawędzi, wskazujące na południu). Następnie mamy bardzo ciasną pętlę,{}
która po prostu przesuwa się w dół o dwie krawędzie w kierunku południowo-zachodnim, dopóki nie trafimy na koniec przechowywanego ciągu:Czy zauważyłeś, że ponownie oznakowałem jedną krawędź EOF? . Po przetworzeniu tego znaku zmienimy krawędź na ujemną, aby
{}
pętla zakończyła się tutaj zamiast następnej iteracji:W kodzie jesteśmy na końcu ciemnoszarej ścieżki, gdzie
'
cofamy się o jeden krok na znak wejściowy. Jeśli sytuacja jest jednym z dwóch ostatnich schematów (tzn. Z danych wejściowych, których jeszcze nie wydrukowaliśmy, jest jeszcze znak), to podążamy zieloną ścieżką (dolną, dla osób, które nie są dobre w zieleni i niebieski). To jest dość proste:;
drukuje samą postać.'
przesuwa się na odpowiednią krawędź spacji, która wciąż zawiera 32 z wcześniejszego miejsca i;
drukuje tę przestrzeń. To{~
sprawia, że nasz EOF? ujemny dla następnej iteracji,'
przesuwa się o krok wstecz, abyśmy mogli powrócić do północno-zachodniego końca struny za pomocą kolejnej ciasnej}{
pętli. Która kończy się na długościkomórka (nie dodatnia poniżej heksa (N) . W końcu}
przesuwa się z powrotem do krawędzi komórki .Jeśli jednak wyczerpaliśmy już dane wejściowe, to pętla, która szuka EOF? zakończy się tutaj:
W takim przypadku
'
przesuwa się na komórkę długości i zamiast tego bierzemy jasnoniebieską (górną) ścieżkę, która drukuje brak operacji. Kod w tej gałęzi jest liniowy:W
{*46;
zapisuje 46 do krawędzi oznaczony nie-op i drukuje (to znaczy okres). Następnie{{;
przesuwa się do krawędzi przestrzeni i drukuje to. W{{=
wraca do komórek krawędzi dla kolejnej iteracji.W tym momencie ścieżki łączą się ze sobą i
(
zmniejszają krawędź komórek . Jeśli iterator nie jest jeszcze zerowy, pójdziemy jasnoszarą ścieżką, która po prostu odwraca kierunek MP,=
a następnie szuka następnej postaci do wydrukowania.W przeciwnym razie dotarliśmy do końca bieżącej linii, a adres IP przejdzie purpurową ścieżką. Oto jak wygląda siatka pamięci w tym momencie:
Purpurowa ścieżka zawiera to:
=
Odwraca kierunek MP ponownie.M8
ustawia ustawia jego wartość na778
(ponieważ kod znakuM
jest,77
a cyfry dołączą się do bieżącej wartości). Tak się dzieje10 (mod 256)
, więc kiedy go wydrukujemy;
, otrzymujemy wysuw linii. Następnie ponownie~
powoduje, że krawędź jest ujemna,'"
wraca do krawędzi linii i ponownie=
odwraca MP.Teraz, jeśli krawędź linii wynosi zero, jesteśmy skończeni. Adres IP podąży (bardzo krótką) czerwoną ścieżką, gdzie
@
kończy program. W przeciwnym razie kontynuujemy fioletową ścieżkę, która zapętla się z powrotem do różowej, aby wydrukować kolejną linię.Kontroluj diagramy przepływu utworzone za pomocą HexagonyColorer firmy Timwi . Diagramy pamięci utworzone za pomocą wizualnego debuggera w jego Esoteric IDE .
źródło
CJam,
56525048 bajtówMoją pierwszą myślą było: „hej, mam już do tego kod!” Ale potem nie mogłem się martwić wyciągnięciem niezbędnych elementów z kodu Ruby, szczególnie dlatego, że nie nadawały się do gry w golfa. Więc zamiast tego spróbowałem czegoś innego w CJam ...
Sprawdź to tutaj.
Wyjaśnienie
Najpierw trochę matematyki na temat wyśrodkowanych liczb heksagonalnych. Jeśli zwykły sześciokąt ma długość boku
N
, wówczas będzie zawierać3N(N-1)+1
komórki, które muszą być równe długości kodu źródłowegok
. Możemy to rozwiązać,N
ponieważ jest to proste równanie kwadratowe:Możemy zignorować pierwiastek ujemny, ponieważ daje to ujemną N. Aby to rozwiązać, potrzebujemy pierwiastka kwadratowego z liczby całkowitej. Innymi słowy,
√(1 + 4(k-1)/3) = √((4k-1)/3)
musi być liczbą całkowitą (na szczęście ta liczba całkowita to średnicaD = 2N-1
sześciokąta, której i tak będziemy potrzebować). Możemy więc wielokrotnie dodawać jeden,.
dopóki ten warunek nie zostanie spełniony.Reszta to prosta pętla, która określa sześciokąt. Przydatną obserwacją dla tej części jest to, że spacje we wcięciu plus spacje w kodzie w każdej linii sumują się do średnicy.
Okazuje się, że wcale nie musimy stosować podwójnej arytmetyki (z wyjątkiem pierwiastka kwadratowego). Ze względu na mnożenie przez 4, nie ma kolizji podczas dzielenia przez 3, a pożądana
k
będzie pierwsza, która da pierwiastek kwadratowy z liczby całkowitej.źródło
Perl,
203200198zawiera + 1 dla
-p
Uruchom jako:
echo abc | perl -p file.pl
Bardzo naiwne podejście:
;
; sam kod poniżej 200 bajtów!$s=~/\S+/g
zamiastsplit/\n/,$s
źródło
JavaScript (ES6), 162
172Funkcja anonimowa
Znaleziono rozmiar sześciokąta rozwiązujący równanie z wikipedii
Formuła rozwiązywania jest w zasadzie
Z pewną algebrą i pewnym przybliżeniem (również dla @ user18655) staje się
Bardziej czytelny
Fragment testowy (lepsza pełna strona - czas działania ~ 1 minuta)
źródło
n=...+1-1e-9|0
zamiastn=Math.ceil(...)
zapisać 2 bajty. Możesz także użyć ES7 i używać**0.5
zamiast,Math.sqrt
ale to zależy od ciebie. Zwykle zachowuję swoje odpowiedzi ES6, ponieważ działają one w mojej przeglądarce haha!Pyth,
5251 bajtówWypróbuj online. Zestaw testowy.
Każda linia ma jedno dodatkowe pole wiodące, na co pozwala OP.
Wyjaśnienie
źródło
Retina , 161 bajtów
Dzięki FryAmTheEggman za zapisanie 2 bajtów.
Ta odpowiedź nie jest konkurencyjna. Retina widziała kilka aktualizacji od tego wyzwania i jestem prawie pewien, że korzystam z niektórych nowszych funkcji (chociaż nie sprawdziłem).
Liczba bajtów zakłada kodowanie ISO 8859-1. Pierwszy wiersz zawiera pojedynczą spację. Zauważ, że większość z nich
·
to w rzeczywistości kropki środkowe (0xB7).Wypróbuj online!
Dobrze...
Wyjaśnienie
Najłatwiej jest najpierw zbudować układ, używając tylko jednego znaku (
·
w tym przypadku), a następnie wypełnić wynikowy układ znakami wejściowymi. Głównymi tego przyczynami są to, że użycie pojedynczej postaci pozwala mi korzystać z odwołań wstecznych i powtarzania postaci, przy czym bezpośrednie wprowadzenie danych wymagałoby kosztownych grup równoważących.Chociaż nie wygląda to zbyt wiele, te pierwsze etapy usuwają spacje z wejścia.
Zaczynamy od przygotowania dodatkowej linii zawierającej
M
punkty środkowe, gdzieM
jest długość wejścia (po usunięciu spacji).Jeśli wprowadzony tekst był pojedynczym znakiem, ponownie usuwamy tę środkową kropkę. Jest to niefortunny przypadek specjalny, który nie jest objęty następnym etapem.
To oblicza wymaganą długość boku
N
minus 1. Oto jak to działa: wyśrodkowane liczby heksagonalne mają postać3*N*(N-1) + 1
. Ponieważ liczby trójkątne sąN*(N-1)/2
, oznacza to , że liczby heksagonalne są sześciokrotnie większe od liczby trójkątnej plus 1. Jest to wygodne, ponieważ dopasowanie liczb trójkątnych (które są naprawdę sprawiedliwe1 + 2 + 3 + ... + N
) w wyrażeniu regularnym jest dość łatwe z odniesieniami do przodu. Te(^·|\2·)*
mecze największa liczba trójkątna to możliwe. Jako niezły bonus,$2
będzie wtedy trzymał indeks tej trójkątnej liczby. Aby pomnożyć przez 6, przechwytujemy go do grupy1
i dopasowujemy kolejne 5 razy. Zapewniamy, że są jeszcze co najmniej dwa·
z·
i·+
. W ten sposób indeks znalezionej liczby trójkątnej nie wzrośnie, dopóki jeden znak nie będzie więcej niż wyśrodkowana liczba heksagonalna.Ostatecznie to dopasowanie daje nam dwa razy mniej niż długość boku wymaganego sześciokąta w grupie
$2
, więc piszemy to z powrotem razem z jeszcze jedną środkową kropką, aby uzyskaćN-1
.To zamienia nasz ciąg
N-1
środkowych kropek wN-1
spacje,2N-1
środkowe kropki i inneN-1
spacje. Zauważ, że jest to maksymalne wcięcie, po którym następuje średnica sześciokąta, a następnie ponownie wcięcie.Jest to nieprzyjemnie długie, ale w zasadzie daje nam tylko wszystkie nakładające się dopasowania, które są albo a)
2N-1
długimi znakami i w pierwszej linii lub b) drugą linią. To rozszerza wynik z poprzedniego etapu do pełnego, ale dziwnie wciętego sześciokąta. Np. Za dane wejściowe12345678
otrzymalibyśmy:Dlatego też musieliśmy dodać spacje również na poprzednim etapie.
To naprawia wcięcie linii po środku, poprzez wielokrotne wcięcie dowolnej linii, która jest krótsza niż poprzednia (ignorując końcowe spacje), więc otrzymujemy:
Teraz wstawiamy tylko spacje
Co daje nam:
Uff, gotowe.
Czas wypełnić łańcuch wejściowy w środkowe kropki. Odbywa się to za pomocą etapu sortowania. Dopasowujemy wszystkie środkowe kropki i każdy znak w ostatnim wierszu i sortujemy je według wyniku podanego podstawienia. To podstawienie jest puste dla znaków w ostatnim wierszu i
·
dla środkowych kropek, więc dzieje się tak, że środkowe kropki są po prostu sortowane do końca (ponieważ sortowanie jest stabilne). To przenosi znaki wejściowe na miejsce:Zostały tylko dwie rzeczy:
To zamienia środkowe kropki w regularne okresy.
I to odrzuca ostatnią linię.
źródło
JavaScript (ES6), 144 bajty
Gdzie
\n
reprezentuje dosłowny znak nowej linii. Wykorzystuje technikę tworzenia sześciokąta, którą wcześniej stosowałem w kilku innych odpowiedziach siatki sześciokątnej . W przypadku ES7 przyjmowanie pierwiastków kwadratowych jest nieco krótsze niż podejście rekurencyjne:źródło
Python 3 , 144 bajty
Wypróbuj online!
Wykorzystuje dość różną ilość wiodących białych znaków dla sześciokątów o różnych rozmiarach, ale ogólny kształt przetrwa.
źródło