Przez diabła Klatka jest wstęga podobny funkcji związanej zbioru Cantora.
Twoim zadaniem jest odtworzenie tej funky - w sztuce ASCII!
Wejście
Pojedyncza liczba całkowita n >= 0
wskazująca rozmiar wyjścia. Dane wejściowe można podać za pomocą STDIN, argumentu funkcji lub argumentu wiersza poleceń.
Wynik
Odbitka ASCII-art schodów diabła w rozmiarze n
, zwrócona w postaci łańcucha lub wydrukowana do STDOUT. Końcowe spacje na końcu każdego rzędu są w porządku, ale spacje wiodące nie. Możesz opcjonalnie wydrukować jedną końcową linię nowego wiersza.
W przypadku rozmiaru 0
wynik jest po prostu:
x
(Jeśli chcesz, możesz użyć dowolnego innego znaku ASCII do wydruku innego niż spacja, zamiast x
.)
Dla rozmiaru n > 0
:
- Weź wynik wielkości
n-1
i rozciągnij każdy rząd trzy razy - Riffle między rzędami pojedynczych
x
s - Przesuń rzędy w prawo, aby
x
w każdej kolumnie znajdował się dokładnie jeden , a pozycja pierwszegox
jest minimalna, a jednocześnie maleje wraz z rzędami
Na przykład dane wyjściowe dla n = 1
:
x
xxx
x
Aby uzyskać wynik n = 2
, rozciągamy każdy wiersz trzy razy:
xxx
xxxxxxxxx
xxx
Riffle między rzędami singli x
:
x
xxx
x
xxxxxxxxx
x
xxx
x
Przesuń w prawo:
x
xxx
x
xxxxxxxxx
x
xxx
x
Jako kolejny przykład tutaj jest n = 3
.
Punktacja
To jest golf golfowy, więc wygrywa rozwiązanie w najmniejszej liczbie bajtów.
(,],~3^#@~.)@]
zamiast(1,[:,1,"0~3*])
oszczędzać 1 bajt. A jeśli nie masz nic przeciwko!
jako wyjściowy znak char,u:32+
zamiast' #'{~
zapisywać inny.#\
zamiasti.@#
i wyprzedzasz APL! :)n-1
nie dlan
.Sześciokąty , 217 bajtów
To była niesamowita zabawa. Dziękujemy za opublikowanie tego wyzwania.
Pełne ujawnienie: język (heksagonia) nie istniał w momencie opublikowania tego wyzwania. Jednak nie wymyśliłem go, a język nie został zaprojektowany do tego wyzwania (ani żadnego innego konkretnego wyzwania).
Rozłożony sześciokątnie:
Program tak naprawdę nie korzysta z
#
instrukcji, więc użyłem tego znaku, aby pokazać, które komórki są rzeczywiście nieużywane.Jak działa ten program? To zależy. Chcesz krótką wersję, czy długą?
Krótkie wyjaśnienie
Aby zilustrować, co rozumiem przez „linię” i „segment” w poniższym wyjaśnieniu, rozważ ten podział zamierzonego wyniku:
Po wyjaśnieniu program odpowiada następującemu pseudokodowi:
Długie wyjaśnienie
Zapoznaj się z tym schematem ścieżki kodu zakodowanym kolorem
Realizacja rozpoczyna się w lewym górnym rogu. Sekwencja instrukcji
){2'"''3''"2}?)
jest wykonywana (plus kilka zbędnych anulowań,"{
itp.) Poprzez podążanie dość skomplikowaną ścieżką. Zaczynamy od wskaźnika instrukcji nr 0, zaznaczonego szkarłatem. W połowie przełączamy się na numer 1, zaczynając od prawego górnego rogu i pomalowany na zielono. Gdy IP # 2 zaczyna się od błękitu chabrowego (środkowy prawy), układ pamięci jest następujący:W całym programie krawędzie oznaczone 2a i 2b zawsze będą miały wartość
2
(używamy ich do obliczania odpowiednio 2ⁿ⁺¹ i dzielenia przez 2), a krawędź oznaczona 3 zawsze będzie3
(używamy tego do obliczania 3ⁱ).Wchodzimy do biznesu, wchodząc w naszą pierwszą pętlę, wyróżnioną kolorem chabrowym. Ta pętla wykonuje instrukcje,
(}*{=&}{=
aby obliczyć wartość 2ⁿ⁺¹. Kiedy pętla wychodzi, wybierana jest brązowa ścieżka siodła, która prowadzi nas do wskaźnika instrukcji nr 3. Ten adres IP jedynie przesuwa się wzdłuż dolnej krawędzi na zachód w żółtawo-złotym kolorze i wkrótce przechodzi kontrolę nad IP # 4.Ścieżka fuksji wskazuje, w jaki sposób IP # 4, zaczynając od lewego dolnego rogu, przechodzi szybko do linii zmniejszania , ustawia ch na
32
(znak spacji) i seg na (nowa wartość) linii . Jest to spowodowane wczesnym zmniejszeniem, że faktycznie zaczynamy od 2ⁿ⁺¹ − 1 i ostatecznie doświadczamy ostatniej iteracji z wartością 0. Następnie wchodzimy do pierwszej zagnieżdżonej pętli.Zwracamy uwagę na rozgałęziony indygo, w którym po krótkim zmniejszeniu seg widzimy, że ch jest aktualizowane
x
tylko wtedy, gdy seg wynosi teraz zero. Następnie n ustawia się na linii - seg, aby określić faktyczną liczbę segmentów, w których się znajdujemy. Natychmiast wchodzimy w kolejną pętlę, tym razem w jasnym kolorze pomidora.W tym miejscu ustalamy, ile razy n (bieżący numer segmentu) można podzielić przez 2. Tak długo, jak moduł daje nam zero, zwiększamy i dzielimy n przez 2. Gdy jesteśmy usatysfakcjonowani, n nie jest już podzielny , rozgałęziamy się na szary łupek, który zawiera dwie pętle: najpierw podnosi 3 do potęgi obliczonego przez nas i , a następnie wyprowadza ch tyle razy. Zauważ, że pierwsza z tych pętli zawiera
[
instrukcja, która przełącza sterowanie na IP # 3 - ta, która wcześniej tylko stawiała małe kroki wzdłuż dolnej krawędzi. Ciało pętli (pomnożenie przez 3 i zmniejszenie) jest wykonywane przez samotny adres IP # 3, uwięziony w nieskończonym cyklu ciemnozielonej zieleni wzdłuż dolnej krawędzi kodu. Podobnie, druga z tych łupkowych szarych pętli zawiera]
instrukcję, która aktywuje IP # 5 do wyjścia ch i dekrementacji, pokazane tutaj w ciemno indyjskiej czerwieni. W obu przypadkach wskaźniki instrukcji uwięzione w służebności posłusznie wykonują jedną iterację naraz i poddają kontrolę z powrotem do IP # 4, tylko po to, aby poczekać chwilę na ponowne wezwanie ich usługi. Tymczasem szary łupek powraca do braci w kolorze fuksji i indygo.Gdy seg nieuchronnie osiąga zero, pętla indygo wychodzi na zieloną ścieżkę trawnika, która jedynie wyprowadza znak nowej linii i natychmiast łączy się z powrotem w fuksję, aby kontynuować pętlę linii . Poza końcową iteracją pętli liniowej znajduje się krótka, ebonowa ścieżka ostatecznego zakończenia programu.
źródło
Python 2, 78
Zaczynając od listy
L=[1]
, kopiujemy ją i wstawiamy kolejną potęgę 3 na środku, w wyniku czego[1, 3, 1]
. Jest to powtarzanen
razy, aby podać nam długości rzędów schodów diabła. Następnie drukujemy każdy wiersz wypełniony spacjami.źródło
APL, 38
Przykład:
Wyjaśnienie:
źródło
GNU sed, 142
Nie najkrótsza odpowiedź, ale sed !:
Ponieważ jest to sed (brak natywnej arytmetyki), biorę swobody z regułą „Pojedyncza liczba całkowita n> = 0, wskazująca rozmiar wyniku” . W takim przypadku wejściowa liczba całkowita musi być ciągiem
1
s, którego długość wynosi n. Myślę, że to „wskazuje” rozmiar wyjścia, nawet jeśli nie jest to bezpośredni numeryczny odpowiednik n. Zatem dla n = 2 ciągiem wejściowym będzie11
:Wydaje się, że kończy się to wykładniczą złożonością czasową O ( cn ), gdzie c wynosi około 17. n = 8 zajęło mi około 45 minut.
Alternatywnie, jeśli wymagane jest, aby n było wpisane dokładnie numerycznie, możemy to zrobić:
sed, 274 bajty
Wynik:
źródło
Python 2, 81
Wersja programu (88)
Liczba x w
n
1 rzędzie z indeksowaniem wynosi 3 do potęgi (indeks pierwszego ustawionego bitun
, zaczynając od lsb).źródło
Python 2, 74
Podejście rekurencyjne. Schody diabła o wielkości $ n $ są podzielone na trzy części
n-1
, których długość wynosi3**n - 2**n
x
„długości3**n
n-1
, których długość wynosi3**n - 2**n
Zauważ, że całkowita długość trzech części wynosi
3*(3**n) - 2*(2**n)
lub3**(n+1) - 2**(n+1)
, co potwierdza indukcję.Opcjonalna zmienna
s
przechowuje przesunięcie bieżących części, które drukujemy. Najpierw cofamy się do lewej gałęzi z większym przesunięciem, następnie drukujemy linię środkową, a następnie wykonujemy prawą gałąź przy bieżącym przesunięciu.źródło
CJam,
363533 bajtówOto inne podejście do CJam (nie spojrzałem na kod Optimizera, więc nie wiem, czy tak naprawdę jest inaczej):
Wykorzystuje
0
to krzywą. Alternatywnie (przy użyciu sztuczki grc)który wykorzystuje
x
.Sprawdź to tutaj.
Wyjaśnienie
Podstawową ideą jest, aby najpierw utworzyć tablicę z wierszami, jak
Następnie przejrzyj tę listę, przygotowując odpowiednią ilość spacji.
Druga wersja działa podobnie, ale tworzy tablicę długości
A potem zamienia to w ciągi
x
s na ostatecznej mapie.źródło
Dyalog APL, 34 znaki
Korzystanie z podejścia grc. Rysuje schody za pomocą
⌹
znaków (domino) i pobiera dane wejściowe ze standardowego wejścia. Takie rozwiązanie zakłada⎕IO←0
.⎕
- pobrać dane wejściowe ze standardowego wejścia.⌽⍳1+⎕
- sekwencja liczb od⎕
0 do 0. (np.3 2 1 0
)3*⌽⍳1+⎕
- trzy do potęgi tego (np.27 9 3 1
)(⊢,,)/3*⌽⍳1+⎕
- poprzedni wynik złożony z prawej strony przez funkcję milczącą,⊢,,
która jest równa dfn,{⍵,⍺,⍵}
dająca długość kroku schodów diabła według podejścia grc.{⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
długości kroków przeliczane na kroki.(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕
że samo ogłoszenie, jak w moim roztworu J . Zauważ, że⊖
już poprawnie odwraca wynik.' ⌹'[(∪∘.=⊖){⍵/⍳≢⍵}⊃(⊢,,)/3*⌽⍳1+⎕]
liczby zastąpione spacjami i domino.źródło
Ruby, 99
Inna odpowiedź na moją drugą, inspirowana odpowiedzią FUZxxl
FUZxxl zauważa, że liczby x odpowiadają liczbie czynników 2 indeksu. na przykład dla n = 2 mamy następującą faktoryzację:
Używam raczej prostszego sposobu wyodrębnienia tych potęg 2:
i=m&-m
co daje sekwencję1 2 1 4 1 2 1
itp. Działa to w następujący sposób:m-1
jest taki sam, jakm
w najbardziej znaczących bitach, ale najmniej znaczący bit 1 staje się zerem, a wszystkie zera po prawej stają się 1.Aby móc ORAZ to z oryginałem, musimy odwrócić bity. Można to zrobić na różne sposoby. Jednym ze sposobów jest odjęcie go
-1
.Ogólna formuła jest więc tym,
m& (-1 -(m-1))
co upraszczam&(-m)
Przykład:
Oto kod: nowe linie są liczone, wcięcia są niepotrzebne i dlatego nie są liczone, jak moja inna odpowiedź. Jest nieco dłuższy niż moja inna odpowiedź z powodu niezdarnej konwersji z bazy 2:
1 2 1 4 1 2 1 etc
na bazę 3:1 3 1 9 1 3 1 etc
(czy istnieje sposób, aby tego uniknąćMath::
?)źródło
Ruby,
14099Mój drugi w historii kod Ruby i moje pierwsze nietrywialne użycie tego języka. Sugestie są mile widziane. Liczba bajtów wyklucza spacje wiodące dla wcięć, ale obejmuje znaki nowej linii (wydaje się, że większości nowych linii nie można usunąć, chyba że zostaną one zastąpione co najmniej spacją).
Dane wejściowe są wywoływane przez funkcję. Dane wyjściowe to tablica ciągów, które Ruby wygodnie zrzuca na standardowe wyjście jako listę oddzieloną znakiem nowej linii z pojedynczym
puts
.Algorytm to po prostu
new iteration
=previous iteration
+extra row of n**3 x's
+previous iteration
. Jednak istniejewielekwota fair kodu wystarczy, aby uzyskać spacje w prawym wyjściowego.Edycja: Ruby, 97
Wykorzystuje to podobne, ale inne podejście, do budowania tabeli liczbowej wszystkich liczb x wymaganych w tablicy
a
w sposób opisany powyżej, ale następnie do budowania tabeli ciągów znaków. Tabela ciągów jest budowana wstecz w tablicyc
przy użyciu raczej dziwnie nazwanejunshift
metody, aby dołączyć do istniejącej tablicy.Obecnie to podejście wygląda lepiej - ale tylko o 2 bajty :-)
źródło
for m in(0..n-1)do ... end
zn.times{|m|...}
.n.times
i na pewno to zapamiętam. To też eliminujeend
! Jednak przy tej okazji zastanawiałem się, czyfor m in (1..n)
może być lepiej, aby uniknąć(m+1)
. Czy istnieje krótszy sposób napisania tego?for
jest długi, głównie dlatego, że jesteś zmuszony do używaniaend
(możesz zastąpićdo
nowym znakiem lub znakiem;
). Do1..n
możesz użyć1.upto(n){|m|...}
. Podoba mi się wygląd,(1..n).each{|i|...}
ale jest nieco dłuższy niż używanieupto
. I zauważ, że iteracja przez dzwonienieeach
lubupto
nie jest po prostu krótsza, to także rozważ bardziej idiomatyczny Ruby.1.upto(n)
to jest! Po tym, gdy zniknęło kilka niepotrzebnych nawiasów, jestem już na poziomie 120. Myślę, że poniżej 100 jest możliwe, opublikuję poprawiony kod później.Haskell, 99 znaków
Funkcja to
d
:źródło
q
i robiącq x=x
w pustym przypadku listy. Ponadto wydaje się, że nawiasy wokółiterate...[1]
są niepotrzebne.PHP - 137 bajtów
Używam tutaj tej samej sztuczki, co grc . Oto wersja bez golfa:
źródło
3**$i
-> wygląda jak PHP 5.6. Powinieneś to określić. Jest to niezgodne z prawie każdą instalacją PHP. Aby zaoszczędzić kilka bajtów, powinieneś zacząć od,$r=str_repeat;
a gdzie masz tę funkcję, możesz ją zastąpić$r
, oszczędzając ci 2 bajty. Ponadto$r('x',$v)
może być$r(x,$v)
i będzie działać dobrze (zauważ, że nazwa funkcji została już zmieniona na zmienną). Ponadto uważam, że++$i<=$n
można to przepisać jako$n>++$i
oszczędność kolejnego bajtu.function f($n){$r=str_repeat;$a=[1];while($n>++$i)$a=array_merge($a,[3**$i],$a);foreach($a as$v){$o=$r(' ',$s).$r(x,$v)."\r$o";$s+=$v;}echo$o;}
(zamiast tej brzydkiej nowej linii, dodałem sekwencję zmiany znaczenia\r
w ciągu podwójnego cudzysłowu, ze zmienną w$o
środku. Zatem"\r$o"
ma taką samą liczbę bajtów jak ta''.$o
, z ostatnią linią poleconą w ostatnim i daje ten sam wynikwhile
musi być$n>$i++
poprawne działanie.$r=str_repeat
podstęp. Myślałem tylko o tym$r='str_repeat';
, co nie oszczędzało żadnego bajtu. Nieokreślona stała to także dobra sztuczka, dobrze zrobiona;). Nowy wiersz jest o jeden bajt mniejszy niż pisanie\n
, więc go zachowałem, ale użyłem podwójnych cudzysłowów, aby uniknąć konkatenacji$0
. Dzięki jeszcze raz !3 ** $i
, powiedziałbym, że masz straszną składnię. Możesz rozwiązać tę poprawkę. Mówię tylko o tym, a nie[1]
dlatego, że pochodzi on z PHP5.4, który jest dość „stary”. 1 rok temu poprosiłbym cię o określenie tego. Dzisiaj proszę was o proste określenie (w bardzo krótkim wierszu), które to określa. Mówiąc o kodzie, nadal++$i<=$n
możesz go zastąpić$n>$i++
. Musiałem przekonwertować cały kod na PHP5.3, aby go przetestować. Co było bolesne. Ale widzę, że do tej pory zjadłeś 7 bajtów.C, 165
Oto ten sam kod rozpakowany i lekko wyczyszczony:
Jest to oparte na tym samym pomyśle, co rozwiązanie FUZxxl, polegające na użyciu jawnej, a nie domyślnej formy wierszy. Deklaracja j ustawia ją na 2 ^ (n + 1), a pierwsza pętla while oblicza k = 3 ^ (n + 1); wtedy l = 3 ^ (n + 1) -2 ^ (n + 1) to całkowita szerokość schodów (nie jest to zbyt trudne do udowodnienia). Następnie przechodzimy przez wszystkie liczby r od 1 do 2 ^ (n + 1) -1; dla każdego, jeśli można podzielić przez (dokładnie) 2 ^ n, to planujemy wydrukować s = 3 ^ n 'X. l jest dostosowywany, aby mieć pewność, że zaczniemy od właściwego miejsca: piszemy l spacje i litery X, a następnie nową linię.
źródło
(*p)()=putchar;
na początku, aby zadzwonićputchar
jakop
. Myślę, że to powinno działać.CJam,
46 43 41 39 3635 bajtówAKTUALIZUJ, używając teraz innego podejścia.
Stare podejście:
Dość naiwny i długi, ale coś na początek.
Dodam wyjaśnienie, gdy zacznę grać w golfa.
Wypróbuj online tutaj
źródło
Java,
271269 bajtówUżywa metody grc.
Zębaty:
Wszelkie sugestie są mile widziane.
2 bajty dzięki mbomb007
źródło
b.size()>0
zamiast!b.isEmpty()
, oszczędzając 2 bajty.Perl, 62
Najpierw oblicza wynik iteracyjnie bez spacji wiodących. Następnie dodaje je przed każdym wierszem zgodnie z liczbą
x
znaków w pozostałej części ciągu.źródło
JavaScript (ES6) 104
106 118Edytuj Usunięto funkcję rekurencyjną, listę „*” dla każdej linii uzyskuje się iteracyjnie, bawiąc się bitami i potęgami 3 (jak w wielu innych odpowiedziach)
Wewnątrz pętli od dołu do góry jest budowany ciąg wielowierszowy, utrzymujący bieżącą liczbę wiodących spacji do dodania w każdej linii
Pierwsza próba została usunięta
Rekurencyjna funkcja R buduje tablicę z liczbą „*” dla każdej linii. Na przykład R (2) to
[1, 3, 1, 9, 1, 3, 1]
Ta tablica jest skanowana w celu zbudowania ciągu wielowierszowego od dołu do góry, zachowując bieżącą liczbę wiodących spacji do dodania w każdej linii
Przetestuj w konsoli Firefox / FireBug
Wynik
źródło
R - 111 znaków
Prosta implementacja, iteracyjne budowanie tablicy i niszczenie jej powoli.
Stosowanie:
źródło
n
n=scan()
.x
używania go jako kursora, ani nie potrzebujeszif(n)
. Również łamanie linii liczy się jako znak.x
. Nie jestemif(n)
jednak pewien . Dodałem tę część, aby zająć się sprawąn=0
.if(n)
Następnie powracaF
i tym samym zwraca pojedynczyx
. Jeśli gon=0
usunę , daje niechciane wyniki. Nowość tutaj, więc nie wiedziałem o łamaniu linii. Uwzględnione teraz!a=0
i uruchomisz pętlęx in 0:n
, działa to również dla n = 0. Następnie możesz pominąćif(n)
.Ruby, 93
Używa tego samego podejścia co grc.
źródło