Melhoria da casa para o Minotauro

42

Melhoria da casa para o Minotauro

O labirinto de Creta é bastante fácil de desenhar. Comece com uma forma simétrica (aqui em vermelho). Vamos chamar todos os pontos finais dessas linhas de 'nós'. Em seguida, você começa a desenhar os arcos (preto): o primeiro começa sempre no nó do meio superior e se conecta ao nó próximo a ele no lado direito, e os dois nós mais próximos ao arco anterior são conectados. Isso é repetido até que todos os nós sejam cobertos.

gif

Agora podemos generalizar esse conceito: podemos facilmente gerar novos padrões iniciais adicionando mais Lformas. Enumerei as formas iniciais da seguinte maneira:

grau

O padrão mais à esquerda produzirá um labirinto cretense de grau 0 . O próximo criará um labirinto cretense de grau 1 (o original) etc.

Tarefa

Dado um número inteiro não negativo n, seu programa deve gerar a representação ascii de um labirinto de graus de Creta n, mostrado nos exemplos a seguir. Espaços à direita / novas linhas não importam. Você precisa incluir uma breve explicação de como seu código funciona.

Exemplos

A saída para o labirinto de creta original (grau 1) é a seguinte:

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

Padrão inicial:

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

O labirinto cretense de grau 0 deve ter a seguinte aparência:

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

Padrão inicial:

+ | +
--+--
+ | +
flawr
fonte

Respostas:

10

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

(Passe n como argumento da linha de comando.)

Calcula o labirinto linha por linha em seis seções:

  • primeiras 4n + 4 linhas,
  • próxima linha (a única linha sem -),
  • próximas n linhas,
  • próxima linha (a linha no meio do padrão inicial),
  • próximas 2n + 1 linhas,
  • linha final (a linha com espaços à esquerda).
Anders Kaseorg
fonte
6

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

( Obrigado a @flawr pelo conselho sobre como salvar 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]))

Não é um grande candidato ao título, mas ainda tentei, e funciona perfeitamente. Vou tentar reduzi-lo mais com o tempo, sempre que puder, mas por enquanto, adoro e não poderia ser mais feliz.

Experimente online! (Ideone) (Pode parecer um pouco diferente aqui por causa das limitações aparentes do compilador on-line. No entanto, ainda é praticamente o mesmo.)

Explicação:

Para os fins desta explicação, vamos supor que a função acima foi executada com a entrada r, sendo igual a 1. Dito isto, basicamente o que está acontecendo, passo a passo, é ...

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

    Um objeto zip,, qé criado com 2 objetos de intervalo, um consistindo em cada segundo número inteiro no intervalo 0=>r+r+1e outro consistindo em cada segundo número inteiro no intervalo r+r+1=>0. Isso ocorre porque todo padrão inicial de um labirinto de Creta de um grau específico sempre terá um número par -em cada linha. Por exemplo, para um labirinto cretense de grau 1, r+r+1é igual 3e, portanto, seu padrão sempre começa com 0traços, seguido por outra linha com 4(2 + 2) traços. Este objeto zip será usado para as primeiras r+1linhas do padrão do labirinto.

    Nota: O único motivo qé uma lista e separada do restante é porque qé referenciada algumas vezes e inscrita e, para economizar muitas repetições e permitir a inscrição, eu simplesmente criei um objeto zip qna forma de uma lista.

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

    Este é o último passo, no qual o labirinto é construído e montado. Aqui, três listas, a primeira consistindo nas 4*r+1linhas superiores do labirinto, a segunda consistindo nas 3*r+3linhas médias do labirinto e a última lista consistindo na última linha do labirinto são unidas, com quebras de linha ( \n) em uma corda longa. Finalmente, é impressa esta enorme corda composta por todo o labirinto. Vamos aprofundar o que essas 2 listas e 1 string realmente contêm:

    • A primeira lista, na qual outro objeto compactado é usado na compreensão da lista para criar cada linha uma por uma, com iniciais |ou +símbolos, um número ímpar de traços no intervalo 0=>4*(r+1), final |ou +símbolos e, em seguida, uma nova linha ( \n). No caso de um 1labirinto de graus , esta lista retorna:

      +-----------------------------+
      | +-------------------------+ |
      | | +---------------------+ | |
      | | | +-----------------+ | | |
      | | | | +-------------+ | | | |
      | | | | | +---------+ | | | | |
      | | | | | | +-----+ | | | | | |
      | | | | | | | +-+ | | | | | | |
      
    • A segunda lista, que consiste em um objeto zip contendo 4 listas, e cada lista corresponde ao número de |símbolos iniciais / finais , o número de +símbolos, o número de traços e, finalmente, a última lista, que contém as primeiras r+1linhas de o padrão criado de acordo com o objeto zip q, a linha no meio do padrão (aquela sem |) e as últimas r+2linhas do padrão simétrico. Nesse caso específico, a última lista usada no objeto zip dessa lista retornaria:

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

      E, portanto, no caso de um labirinto de 1 grau, toda a lista retornaria:

      | | | | | + | | | + | | | | | |
      | | | | +---+ | +---+ | | | | |
      | | | +-------+-------+ | | | |
      | | +-------+ | +-------+ | | |
      | +-------+ | | | +-------+ | |
      +-----------+ | +-----------+ | <- Here is where the extra line of the pattern is used.
      
    • Esta lista final, na qual a última linha é criada. Aqui, o primeiro segmento (aquele antes do primeiro espaço) da última linha do Pnúmero de espaços da lista é criado. Em seguida, é adicionado o comprimento do último segmento (o segmento final) da mesma linha + 4 número de traços, todos precedidos e seguidos por um único +símbolo. No caso de um labirinto de grau 1, esta última lista retorna:

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

    Depois de juntar tudo isso, essa etapa finalmente retorna o labirinto concluído. No caso de um labirinto de 1 grau, ele finalmente retornaria isso:

    +-----------------------------+
    | +-------------------------+ |
    | | +---------------------+ | |
    | | | +-----------------+ | | |
    | | | | +-------------+ | | | |
    | | | | | +---------+ | | | | |
    | | | | | | +-----+ | | | | | |
    | | | | | | | +-+ | | | | | | |
    | | | | | + | | | + | | | | | |
    | | | | +---+ | +---+ | | | | |
    | | | +-------+-------+ | | | |
    | | +-------+ | +-------+ | | |
    | +-------+ | | | +-------+ | |
    +-----------+ | +-----------+ |
                  +---------------+
    
R. Kap
fonte
1
Você pode primeiro definir R=rangeou algo assim? O mesmo para P='+'?
flawr
1
Eu acho que você deve aproveitar a oportunidade de ouro para dizerfor g,o,k,u in Z
Sherlock9
@ Sherlock9 Haha! Boa ideia! Adicionado. :)
R. Kap