Perl, 92 90 89 84 bytes
Inclui +1 para -n
Dê altura em STDIN:
perl -M5.010 bolt.pl <<< 15
bolt.pl:
#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_
Explicação
Se você chamar o deslocamento do ponto inicial 0 (um ponto está no canto de uma caixa de caractere), na próxima linha você poderá ter ido para a esquerda ou direita (ou não) e poderá acabar com pontos em compensações -1,1. A próxima linha fornece os -2,0,2possíveis desvios, etc. Eles diferem por 2. Se você chamar o caractere para o canto inferior esquerdo de um ponto par e o caractere para o canto inferior direito, você poderá estender isso para atribuir pares ou ímpares a cada posição do personagem em uma fileira que alterna par e ímpar (na verdade, todo o plano é lado a lado em um padrão quadriculado). Uma posição par pode ter um /ou , uma posição ímpar pode ter \ou .
O personagem imediatamente antes de a /está em uma posição ímpar, de modo que pode ser um \ou outro , mas \/é proibido apenas para que seja possível. Da mesma forma, o caractere após a \ deve ser a (assumindo que a linha seja preenchida com espaços suficientes à esquerda e à direita, para que os limites da linha não sejam problema). Assim, um raio continua na próxima linha sempre diretamente abaixo de a \ou abaixo de a /. Em qualquer caso, o ponto mais baixo está no meio e a fileira seguinte pode ter um de , /, \ou /\directamente abaixo da parte superior 2 caracteres. Então, para gerar a próxima linha, posso simplesmente substituir qualquer \ou/por qualquer uma dessas 4 expansões com igual probabilidade (você também pode substituir independentemente o primeiro caractere por ou /e o segundo caractere por ou \). Em perl, você pode fazer isso com algo como:
s#\\ | /#(" "," \\","/ ","/\\")[rand 4]#eg
Se a linha resultante no entanto contém \/(proibido juntar-se) ou não /ou \em todos (dies parafuso e não chegar ao fundo), o resultado é inválido. Nesse caso, jogo fora toda a linha e simplesmente tento novamente. Sempre existe uma continuação válida e, se você tentar com frequência, será encontrada uma (por exemplo, tudo morre, exceto 1 fluxo). Essa é uma distribuição de probabilidade um pouco diferente do algoritmo anti-sobreposição sugerido, mas acho que isso é realmente melhor, pois não possui viés direcional. A validade pode ser testada de maneira golfista usando
m#\\|/#>m#\\/#
O problema aqui é que a substituição aleatória é muito lenta e todas essas \fugas também comem bytes. Por isso, decidi construir minhas linhas usando cadeias de dígitos e substituir os dígitos apropriados por , /e \pouco antes da impressão. A substituição aleatória básica é
53|16*rand
o que dá uma das 53, 55, 61ou 63com igual probabilidade. Eu então interpreto 5e 1como , 3como \e 6como /. Isso explica a impressão da linha:
say y|3615|\\/ |r
Em uma competição de golfe séria, eu começaria a explorar sistematicamente fórmulas mágicas alternativas, mas isso deve ser muito bom (a menos de 3 bytes do ideal)
O restante dos componentes do programa:
1x$_.6
Isso inicializa $_(veja o próximo mapa) para espaços de altura seguidos por a /. Esta é uma linha invisível acima da primeira que está sendo impressa e garante que o campo seja amplo o suficiente para que o parafuso nunca fique sem espaço à esquerda
map{ ... ; say ...}(1x$_.6)x$_
Eu processarei essa mesma altura inicial da string vezes imprimindo uma nova linha a cada vez
$_=$;until$;=$_,...
Salve a linha atual em $;. Se a substituição for uma restauração inválida $_de$;
s/.6|3.?/53|16*rand/eg
Faça a substituição real. Não preciso verificar o que é antes /ou depois, \pois deve ser um espaço. Isso é conveniente, pois o espaço pode ser representado por um 1ou por um 5. Como eu apenas coloquei a corda à esquerda, o espaço após a \continuação ainda pode estar ausente, portanto, torne esse caractere opcional
/3|6/>/36/
Verifique se a nova linha é válida
Stay safe and have fun golfing!Talvez também especifique que, se o EAS ocorrer, abandone tudo e siga as ordens! Código de golfe não é sua prioridade em tal situação.