42
\$\begingroup\$

Home improvement for the Minotaur

The cretan labyrinth is quite easy to draw. Just start with a symmetric shape (here in red). Let us call all the endpoints of those lines 'nodes'. Then you begin drawing the arches (black): The first one alway begins in the top middle node and connects to the node next to it on the right side, then the two nodes closest to the previous arch are connected. This is repeated untill all nodes are covered.

gif

Now we can generalize this concept: We can easily generate new initial patterns by adding more L shapes. I enumerated the initial shapes as follows:

degree

The most left pattern will produce a cretan labyrinth of degree 0. The next one will create a cretan labyrinth of degree 1 (the original one) etc.

Task

Given a nonnegative integer n, your program should output the ascii representation of a cretan labyrinth of degree n, that is shown in the following examples. Trailing spaces/newlines do not matter. You have to include a short explanation of how your code works.

Examples

The output for the original cretan labyrith (degree 1) is following:

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

Initial pattern:

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

The cretian labyrinth of degree 0 should look like so:

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

Initial pattern:

+ | +
--+--
+ | +
\$\endgroup\$
10
\$\begingroup\$

Perl 5, 349 bytes

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+"

(Pass n as a command line argument.)

Computes the maze line-by-line in six sections:

  • first 4n + 4 lines,
  • next line (the only line with no -),
  • next n lines,
  • next line (the line at the middle of the initial pattern),
  • next 2n + 1 lines,
  • final line (the line with leading spaces).
\$\endgroup\$
6
\$\begingroup\$

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

(Thanks to @flawr for advice on saving 55 bytes (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]))

Not very much of a contender for the title, but I still gave it a shot, and it works perfectly. I will try to shorten it more over time where I can, but for now, I love it and could not be happier.

Try it online! (Ideone) (May look a little bit different on here because of apparent online compiler limitations. However, it's still very much the same.)

Explanation:

For the purposes of this explanation, let's assume that the above function was executed with the input, r, being equal to 1. That being said, basically what's happening, step-by-step, is...

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

    A zip object, q, is created with 2 range objects, one consisting of every second integer in the range 0=>r+r+1 and another consisting of every second integer in the range r+r+1=>0. This is because every starting pattern of a cretan labyrinth of a specific degree will always have an even number of - in each line. For instance, for a cretan labyrinth of degree 1, r+r+1 equals 3, and thus, its pattern will always start with 0 dashes, followed by another line with 4 (2+2) dashes. This zip object will be used for the first r+1 lines of the labyrinth's pattern.

    Note: The only reason q is a list and separated from the rest is because q is referenced a few times and subscripted, and to save a lot of repetition and allow subscripting, I simply created a zip object q in the form of a list.

  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]))

    This is the last step, in which the labyrinth is built and put together. Here, three lists, the first consisting of the top 4*r+1 lines of the labyrinth, the second consisting of the middle 3*r+3 lines of the labyrinth, and the last list consisting of the very last line of the labyrinth are joined together, with line breaks (\n) into one long string. Finally, this one huge string consisting of the entire labyrinth is printed out. Let us go more in depth into what these 2 lists and 1 string actually contain:

    • The 1st list, in which another zipped object is used in list comprehension to create each line one by one, with leading |or + symbols, an odd number of dashes in the range 0=>4*(r+1), trailing | or + symbols, and then a newline (\n). In the case of a degree 1 labyrinth, this list returns:

      +-----------------------------+
      | +-------------------------+ |
      | | +---------------------+ | |
      | | | +-----------------+ | | |
      | | | | +-------------+ | | | |
      | | | | | +---------+ | | | | |
      | | | | | | +-----+ | | | | | |
      | | | | | | | +-+ | | | | | | |
      
    • The 2nd list, which consists of a zip object containing 4 lists, and each list corresponds to the number of leading/trailing | symbols, the number of + symbols, the number of dashes, and finally, the last list, which contains the first r+1 lines of the pattern created according to zip object q, the line in the middle of the pattern (the one with no |), and the last r+2 lines of the symmetrical pattern. In this specific case, the last list used in this list's zip object would return:

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

      And therefore, in the case of a 1 degree labyrinth, this entire list would return:

      | | | | | + | | | + | | | | | |
      | | | | +---+ | +---+ | | | | |
      | | | +-------+-------+ | | | |
      | | +-------+ | +-------+ | | |
      | +-------+ | | | +-------+ | |
      +-----------+ | +-----------+ | <- Here is where the extra line of the pattern is used.
      
    • This final list, in which the last line is created. Here, the first segment (the one before the first space) length of the last line of list P number of spaces are created. Then, the length of the last segment (the ending segment) of the same line + 4 number of dashes are added, all of which are preceded and followed by a single + symbol. In the case of a degree 1 labyrinth, this last list returns:

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

    After joining all this together, this step finally returns the completed labyrinth. In the case of a 1 degree labyrinth, it would finally return this:

    +-----------------------------+
    | +-------------------------+ |
    | | +---------------------+ | |
    | | | +-----------------+ | | |
    | | | | +-------------+ | | | |
    | | | | | +---------+ | | | | |
    | | | | | | +-----+ | | | | | |
    | | | | | | | +-+ | | | | | | |
    | | | | | + | | | + | | | | | |
    | | | | +---+ | +---+ | | | | |
    | | | +-------+-------+ | | | |
    | | +-------+ | +-------+ | | |
    | +-------+ | | | +-------+ | |
    +-----------+ | +-----------+ |
                  +---------------+
    
\$\endgroup\$
  • 1
    \$\begingroup\$ Can you perhaps first define R=range or something like that? The same for P='+'? \$\endgroup\$ – flawr Apr 26 '16 at 19:54
  • 1
    \$\begingroup\$ I think you should take the golden opportunity to say for g,o,k,u in Z \$\endgroup\$ – Sherlock9 Apr 27 '16 at 3:20
  • \$\begingroup\$ @Sherlock9 Haha! Good idea! Added. :) \$\endgroup\$ – R. Kap Apr 27 '16 at 3:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.