Osadzone sześciokąty!

18

Twoje zadanie: biorąc pod uwagę liczbę całkowitą n, wygeneruj osadzony wzorzec sześciokąta zgodnie z poniższymi zasadami do n-tej głębokości.

Osadzony sześciokąt ma podstawowy kształt: ( n=0)

 __      
/  \
\__/

Osadzone sześciokąty n=1i n=2:

  ____    
 /  \ \
/\__/  \
\      /
 \____/

    ________    
   /  \ \   \
  /\__/  \   \
 /\      /    \
/  \____/      \
\              /
 \            /
  \          /
   \________/

Długość każdej strony jest 2 razy większa niż długość tego samego boku w poprzedniej głębokości razy dwa. Górna i dolna strona mają długość 2 znaków, n=0a reszta zaczyna się od 1 znaku. Długości boków innych niż góra-dół powinny być 2^ndługie ( OEIS: A000079 ), a boki górny i dolny powinny być zgodne z 2^(n+1)tą samą zasadą (ten sam OEIS).

Bieżące sześciokąty mają indeks 0, możesz zdecydować o użyciu indeksowania 1, jeśli chcesz.

To jest , więc wygrywa najkrótsza odpowiedź!

Towarzyszu SparklePony
źródło
@LuisMendo Dobra, zmienię nazwę.
Towarzysz SparklePony,
Duże wejście może być trudne (np. 64). Czy istnieje limit n?
Matthew Roh,
@SIGSEGV Nie ma ograniczenia do n.
Towarzysz SparklePony,
1
Byłbym rozbawiony, widząc odpowiedź w Hexagony :))
Pan Xcoder
1
Heh, żółwia grafika mojego przesłania krzywej Kocha też może to zrobić (zmieniono tylko pierwszą funkcję). Zdecydowanie za długo jednak na to :)
Ørjan Johansen

Odpowiedzi:

10

Węgiel drzewny , 40 29 bajtów

11 bajtów zapisanych dzięki @Neil, zmieniając pętlę while na pętlę for między innymi sztuczkami

FN«AX²ιβ×__β↓↘β←↙β↑←×__β↖β→↗β

Wypróbuj online!

Wyjaśnienie (nieaktualne)

Ten program rozpoczyna się od wygenerowania największego sześciokąta, a następnie wykonuje mniejsze po kolei w pętli while (indeksowane 1). Dla odniesienia, αjest liczbą wejściową, βjest zmienną, która zawiera 2^(α-1)i ιjest zmienną iteracyjną w pętli.

Nα                        # Take input and store in α
Wα«                       # While α do:
 ×_X²ι                    #  Write "_"*(2**ι); this forms the top edge of the hexagon
 ↓                         #  Go down
 AX²⁻ι¹β                 #  Assign 2**(ι-1) to β
 ↘β←                       #  Write \ β times in a SE direction (top right edge) and then go left
 ↙β↑                       #  Write / β times in a SW direction (bottom right edge) and then go up
 ←×_X²ι                   #  Write the bottom edge
 ↖β→↗β                    #  Just like before, write the top and bottom left edges
 A⁻α¹α                    #  Decrement α
                          # Now the pointer is at the top left corner of the hexagon,
                          # from where the other smaller hexagons will soon be generated
Kritixi Lithos
źródło
Zauważyłem, że nie ma „Witaj, świecie!” program na węgiel drzewny jeszcze. Powinieneś to dodać.
mbomb007,
@ mbomb007 Czy nie byłby to po prostu duplikat trywialnej odpowiedzi „ten język drukuje plik źródłowy, jeśli nie zawiera poleceń”?
Neil
Zapisałem kilka bajtów, kiedy zdałem sobie sprawę, że ×_X²ιjest to to samo ×__β, i kilka innych bajtów, przekształcając twój w , co również pozwala uniknąć konieczności przechowywania numeru wejściowego. Wypróbuj online! .
Neil,
@Neil Dzięki, to jest całkiem
fajne
5

Haskell , 230 217 207 bajtów

EDYTOWAĆ:

  • -13 bajtów: @xnor widział, że mój #może być sprawiedliwy max.
  • -10 bajtów: A także to zipWithi pmoże zostać połączone w ?operatora, i że (jakoś!) Ponownie go wdrożyłem replicate.

mbierze Integeri zwraca a String.

m n=unlines.foldr1 o$((2^n)&).(2^)<$>[0..n]
l&t|a<-c[l,2*t]" _",b<-[c[l-i,1,2*t+2*i-2,1,l-i]" / \\ "|i<-[1..t]]=a:b++r(r<$>o[a]b)
c=(concat.).z replicate
o=max?' '?""
f?e=z f.(++repeat e)
r=reverse
z=zipWith

Wypróbuj online!

Jak to działa

  • mjest główną funkcją. Używa &do generowania sześciokątów z odpowiednim wypełnieniem, a następnie składa je razem o.
  • l&tgeneruje mały sześciokąt o długości boku t, wypełniony wewnątrz dużego o boku długości l, jako lista Stringlinii.
    • a to górna linia sześciokąta z podkreśleniami.
    • bjest listą innych linii w górnej połowie sześciokąta. Linie bsą wyśrodkowane na prostokątnej wyściółce; pozwala to na kolejny krok do pracy.
    • Dolna połowa sześcioboku jest anakładany na górze bz o, a następnie odwrócony (zarówno kolejności linii oraz w każdej linii).
  • cpobiera dwa argumenty, listę długości i ciąg znaków i generuje ciąg znaków, który ma tyle kopii każdego znaku w oryginale, co odpowiadająca mu długość, np c[1,3,2]"abc" == "abbbcc". Służy &do generowania linii.
  • o pobiera dwa argumenty przedstawiające zdjęcia jako listy linii i nakłada pierwszy, mniejszy na drugi.
    • Służy zarówno do łączenia sześciokątów, jak i do dodawania dna do każdego sześciokąta.
    • Zasadniczo działa to za pomocą ?dwukrotnego wypełnienia pierwszego obrazu nieskończoną liczbą spacji zarówno w dół, jak i w prawo, a następnie skompresowania odpowiednich znaków za pomocą max, który wybiera znak spacji, jeśli taki istnieje.
  • (f?e)l mPodkładki listę lpoprzez dołączenie nieskończenie wiele elementów „e”, a następnie zamki otrzymanej listy i listy mz ffunkcji.
Ørjan Johansen
źródło
1
Fajne rozwiązanie! Myślę, że (#)może być max.
xnor
1
Zipping można łączyć ze paby zapisać bajtów: o=max?' '?"";f?e=z f.(++repeat e). Może być krótszy bez celu.
xnor
2
(\n->(<$[1..n]))jest replicate.
xnor
@xnor replicate? To po prostu kłopotliwe. Jestem po prostu zbyt przyzwyczajony <$[1..n]lub [1..n]>>prawie zawsze wygrywam. Nie wiem jednak, jak ?dalej skracać . Próbowałem już zrobić pbezcelowe, a to ++jest po prostu w niewłaściwym miejscu, wysadzając rzeczy flip.
Ørjan Johansen
3

JavaScript (ES6), 258 bajtów

f=(n,s=` `.repeat(1<<n),p=(n?f(n-1):`


`).replace(/(.*)\n/g,s+`$1 `+s)+s,t=`_`.repeat(2<<n))=>(s+t+s+`
`+s.replace(/ /g,"$'/$'$'  $`$`$`$`\\$'\n")).replace(/ /g,(c,i)=>p[i+(1<<n>>1)])+s.replace(/ /g,"$`\\$`$`  $'$'$'$'/$`\n").replace(/ +\/( *)\n$/,t+`/$1
`)
<input type=number min=0 oninput=o.textContent=f(+this.value)><pre id=o>

Objaśnienie: W przypadku sześciokątów po pierwszym poprzedni sześciokąt jest najpierw generowany i wypełniany z każdej strony (zależy to od tego, czy dane wyjściowe są prostokątem). (Dla pierwszego nagłówka tworzona jest część zastępcza.) Generowane są górne i górne strony sześciokąta, a wszystkie spacje zostały scalone z poprzednim sześciokątem. (Jest trochę sztuczek, aby ustawić sześciokąty w szeregu; byłoby łatwiej, gdyby dopuszczono dodatkowe marginesy.) Dolne boki sześciokąta są generowane analogicznie do górnych boków, a następnie dolna część sześciokąta jest wypełniana. Należy zwrócić uwagę, aby zwrócić prostokątny wynik, w tym znak nowej linii, aby rekurencja zadziałała.

Neil
źródło
Więc demonstrujesz, że ta, teflonowa i Deep Dish Pizza, są naprawdę podobną konstrukcją? To trochę miłe.
AdmBorkBork
1
@AdmBorkBork Mam kilka innych odpowiedzi, które to robią; te przekątne /są popularne w sztuce ASCII, a replacemetoda jest stosunkowo tanim sposobem ich generowania w JavaScript.
Neil,
1<<n>>1: Niezła symetria ;-)
Łukasz
@Luke Mógłbym zmienić zmienną na, powiedzmy, vale niestety 1nie jest symetryczna w żadnej z moich zwykłych czcionek.
Neil
2

PHP, 337 bajtów

0 Indeksowanie

$h=array_fill(0,1+2*$v=2**($c=$argn),str_pad("",4*$v));for(;1+$c;$c--)for($i=0;$i<$e=2**$c*2+1;$i++){$z=$e-$i<2;$y=$i&&$i<$e/2;$x=$i>=$e/2&$i<$e-1;$h[$i]=substr_replace($h[$i],$s=str_pad(!$y?$z|$x?"\\":"":"/",$e-1+$z-$y+$y*$i*2-$x+$x*2*($e-$i),$z|!$i?"_":" ").(!$y?$z|$x?"/":"":"\\"),$v-$z-$y*$i-$x*($e-$i),strlen($s));}echo join("\n",$h);

Wypróbuj online!

Rozszerzony

$h=array_fill(0,1+2*$v=2**($c=$argn),str_pad("",4*$v)); # fill array with maximal width
for(;1+$c;$c--)  # greatest hexagon to lowest
for($i=0;$i<$e=2**$c*2+1;$i++){ # loop through the rows
    $z=$e-$i<2;$y=$i&&$i<$e/2;$x=$i>=$e/2&$i<$e-1; # booleans last first ad second half
    $h[$i]=substr_replace($h[$i], # replace substring
    $s=str_pad(
        $z?"\\":($y?"/":($x?"\\":"")),
        $e-1+$z-$y+$y*$i*2-$x+$x*2*($e-$i),
        $z|!$i?"_":" "
        ).(!$z?!$y?$x?"/":"":"\\":"/"), # with string for smaller hexagon
    $v-$z-$y*$i-$x*($e-$i), # at offset
    strlen($s));
}
echo join("\n",$h); # Output
Jörg Hülsermann
źródło