Ulepszenie domu dla Minotaura

42

Ulepszenie domu dla Minotaura

Labirynt kreteński jest dość łatwy do narysowania. Po prostu zacznij od symetrycznego kształtu (tutaj na czerwono). Nazwijmy wszystkie punkty końcowe tych linii „węzłami”. Następnie zaczynasz rysować łuki (czarny): Pierwszy zawsze zaczyna się w górnym środkowym węźle i łączy się z węzłem obok niego po prawej stronie, a następnie dwa węzły znajdujące się najbliżej poprzedniego łuku są połączone. Jest to powtarzane do momentu objęcia wszystkich węzłów.

gif

Teraz możemy uogólnić tę koncepcję: Możemy łatwo generować nowe początkowe wzory, dodając więcej Lkształtów. Początkowe kształty wyliczyłem w następujący sposób:

stopień

Najbardziej lewy wzór wytworzy kreteński labirynt stopnia 0 . Następny stworzy kreteński labirynt stopnia 1 (oryginalny) itp.

Zadanie

Biorąc pod uwagę nieujemną liczbę całkowitą n, twój program powinien wypisywać reprezentację ascii labiryntu kreteńskiego stopnia n, co pokazano w poniższych przykładach. Spacje końcowe / znaki nowej linii nie mają znaczenia. Musisz podać krótkie wyjaśnienie działania kodu.

Przykłady

Dane wyjściowe dla pierwotnego labiryntu kreteńskiego (stopień 1) są następujące:

+-----------------------------+
| +-------------------------+ |
| | +---------------------+ | |
| | | +-----------------+ | | |
| | | | +-------------+ | | | |
| | | | | +---------+ | | | | |
| | | | | | +-----+ | | | | | |
| | | | | | | +-+ | | | | | | |
| | | | | + | | | + | | | | | |
| | | | +---+ | +---+ | | | | |
| | | +-------+-------+ | | | |
| | +-------+ | +-------+ | | |
| +-------+ | | | +-------+ | |
+-----------+ | +-----------+ |
              +---------------+

Początkowy wzór:

+ | | | +
--+ | +--
----+----
--+ | +--
+ | | | +

Kreteński labirynt stopnia 0 powinien wyglądać tak:

+-------------+ 
| +---------+ | 
| | +-----+ | | 
| | | +-+ | | | 
| | + | + | | | 
| +---+---+ | | 
+---+ | +---+ | 
      +-------+ 

Początkowy wzór:

+ | +
--+--
+ | +
wada
źródło

Odpowiedzi:

10

Perl 5, 349 bajtów

say$p="| "x$_,"+","-"x(16*$n-4*$_+13),"+ $p"for 0..4*($n=pop)+3;say$p="| "x(3*$n+2),"+ | ","| "x2x$n,"+ $p|";$p=~s/..//,$q="-"x(4*$_-1),say"$p+$q+ ","| "x(2*$n-2*$_+1),"+$q+ $p|"for 1..$n;$p=~s/..//;say$p,("+---"."-"x4x$n)x2,"+ $p|";$p=~s/..//,$q="-"x(4*$n+3)."-"x4x$_,say"$p+$q+ | ","| "x2x($n-abs$_),"+$q+ $p|"for-$n..$n;say" "x(8*$n+6),"+----$q+"

(Podaj n jako argument wiersza poleceń.)

Oblicza labirynt linia po linii w sześciu sekcjach:

  • pierwsze 4n + 4 linie,
  • następny wiersz (jedyny wiersz bez -),
  • kolejne n wierszy,
  • następna linia (linia na środku początkowego wzoru),
  • kolejne 2n + 1 linii,
  • ostatnia linia (linia z wiodącymi spacjami).
Anders Kaseorg
źródło
6

Python 3.5, 703 695 676 648 587 581 542 535 500 486 462 431 423 411 bajtów:

( Podziękowania dla @flawr za porady dotyczące oszczędzania 55 bajtów (486 -> 431)! )

def j(r):R=range;Z=zip;B=r+r+2;P,M='+-';X='| ';q=[*Z(R(0,B-1,2),R(B-1,0,-2))];L=r+1;A=2+r;print('\n'.join([X*w+P+M*v+P+' |'*w for v,w in Z(R(4*L*4-3,0,-4),R(4*L))]+[X*g+P*o+M*k+u+M*k+P*o+' |'*-~g for g,o,k,u in Z([*R(4*L-A,0,-1),*R(4*L-A)],[0]+[1]*(3*r+2),[0,*R(1,4*L,2),*R(4*L+1,11*r,2)],[M*y+'+ '+X*b+P+M*y for y,b in q]+[M*B+P+M*B]+[M*y+'+ '+X*b+P+M*y for y,b in q[::-1]+q[1:]])]+[' '*(8*r+6)+P+M*(8*r+7)+P]))

Nie bardzo pretendent do tytułu, ale wciąż dałem mu szansę i działa idealnie. Z czasem będę starał się go skracać, ale na razie kocham to i nie mogę być szczęśliwszy.

Wypróbuj online! (Ideone) (Może wyglądać nieco inaczej z powodu widocznych ograniczeń kompilatora online. Jednak nadal jest bardzo podobny).

Wyjaśnienie:

Dla celów tego wyjaśnienia załóżmy, że powyższa funkcja została wykonana z wejściem r, będąc równa 1. To powiedziawszy, w zasadzie to, co się dzieje, krok po kroku, to ...

  1. q=[*Z(R(0,B-1,2),R(B-1,0,-2))]

    Obiekt zip qjest tworzony z 2 obiektami zakresu, z których jeden składa się z co drugiej liczby całkowitej w zakresie, 0=>r+r+1a drugi z co drugiej liczby całkowitej w zakresie r+r+1=>0. Jest tak, ponieważ każdy początkowy wzór kreteńskiego labiryntu określonego stopnia zawsze będzie miał parzystą liczbę -w każdej linii. Na przykład, w przypadku cretan labiryntu stopnia 1, r+r+1równa 3, a tym samym jego wzór będzie zawsze zaczynają 0kreskami, a następnie zgodnie z innym 4(2 + 2) kresek. Ten obiekt zip zostanie użyty do pierwszych r+1linii wzoru labiryntu.

    Uwaga: tylko powodem qjest lista i oddzielone od reszty jest ponieważ qodwołuje się kilka razy i indeksowaną oraz zaoszczędzić dużo powtórzeń i pozwalają na indeksowanie, ja po prostu stworzony obiekt zip qw formie listy.

  2. print('\n'.join([X*w+P+M*v+P+' |'*w for v,w in Z(R(4*L*4-3,0,-4),R(4*L))]+[X*g+P*o+M*k+u+M*k+P*o+' |'*-~g for g,o,k,u in Z([*R(4*L-A,0,-1),*R(4*L-A)],[0]+[1]*(3*r+2),[0,*R(1,4*L,2),*R(4*L+1,11*r,2)],[M*y+'+ '+X*b+P+M*y for y,b in q]+[M*B+P+M*B]+[M*y+'+ '+X*b+P+M*y for y,b in q[::-1]+q[1:]])]+[' '*(8*r+6)+P+M*(8*r+7)+P]))

    To ostatni krok, w którym labirynt jest zbudowany i złożony. Tutaj trzy listy, pierwsza składająca się z górnych 4*r+1linii labiryntu, druga składająca się ze środkowych 3*r+3linii labiryntu, a ostatnia lista składająca się z ostatniej linii labiryntu są połączone razem, z podziałem linii ( \n) na jeden długi sznurek. Na koniec wydrukowano ten jeden wielki sznurek składający się z całego labiryntu. Przyjrzyjmy się dokładniej, co faktycznie zawierają te dwie listy i 1 ciąg:

    • Pierwsza lista, w której inny obiekt spakowany jest używany do interpretacji listy, aby utworzyć każdą linię jeden po drugim, z wiodącymi |lub +symbolami, nieparzystą liczbą myślników w zakresie 0=>4*(r+1), końcowymi |lub +symbolami, a następnie nową linię ( \n). W przypadku 1labiryntu stopni ta lista zwraca:

      +-----------------------------+
      | +-------------------------+ |
      | | +---------------------+ | |
      | | | +-----------------+ | | |
      | | | | +-------------+ | | | |
      | | | | | +---------+ | | | | |
      | | | | | | +-----+ | | | | | |
      | | | | | | | +-+ | | | | | | |
      
    • Druga lista, która składa się z obiektu zip zawierającego 4 listy, a każda lista odpowiada liczbie |symboli wiodących / końcowych , liczbie +symboli, liczbie myślników i wreszcie ostatniej liście, która zawiera pierwsze r+1wiersze wzór utworzony według obiektu zip q, linia pośrodku wzoru (ta bez |) i ostatnie r+2linie wzoru symetrycznego. W tym konkretnym przypadku ostatnia lista użyta w obiekcie zip tej listy zwróciłaby:

      + | | | +
      --+ | +--
      ----+----
      --+ | +-- 
      + | | | + 
      --+ | +--  <- Last line created especially for use in the middle of the labyrinth itself.
      

      A zatem, w przypadku labiryntu 1 stopnia, cała lista powróciłaby:

      | | | | | + | | | + | | | | | |
      | | | | +---+ | +---+ | | | | |
      | | | +-------+-------+ | | | |
      | | +-------+ | +-------+ | | |
      | +-------+ | | | +-------+ | |
      +-----------+ | +-----------+ | <- Here is where the extra line of the pattern is used.
      
    • Ta ostateczna lista, w której tworzony jest ostatni wiersz. Tutaj Ptworzony jest pierwszy segment (ten przed pierwszym spacją) długość ostatniego wiersza listy liczba spacji. Następnie dodaje się długość ostatniego segmentu (segmentu końcowego) tej samej linii + 4 liczby myślników, z których wszystkie są poprzedzone i poprzedzone pojedynczym +symbolem. W przypadku labiryntu stopnia 1 ta ostatnia lista zwraca:

                    +---------------+
      

    Po połączeniu tego wszystkiego razem ten krok w końcu zwraca ukończony labirynt. W przypadku labiryntu 1 stopnia w końcu zwróciłoby to:

    +-----------------------------+
    | +-------------------------+ |
    | | +---------------------+ | |
    | | | +-----------------+ | | |
    | | | | +-------------+ | | | |
    | | | | | +---------+ | | | | |
    | | | | | | +-----+ | | | | | |
    | | | | | | | +-+ | | | | | | |
    | | | | | + | | | + | | | | | |
    | | | | +---+ | +---+ | | | | |
    | | | +-------+-------+ | | | |
    | | +-------+ | +-------+ | | |
    | +-------+ | | | +-------+ | |
    +-----------+ | +-----------+ |
                  +---------------+
    
R. Kap
źródło
1
Czy możesz najpierw zdefiniować R=rangeczy coś takiego? To samo dotyczy P='+'?
flawr 26.04.16
1
Myślę, że powinieneś skorzystać ze złotej okazji, aby powiedziećfor g,o,k,u in Z
Sherlock9
@ Sherlock9 Haha! Dobry pomysł! Dodany. :)
R. Kap