Desenhe a curva de Hilbert usando barras

30

A curva de Hilbert é um fractal de preenchimento de espaço que pode ser representado como um sistema Lindenmayer com gerações sucessivas assim:
Curva de Hilbert
Agradecemos a http://www.texample.net/tikz/examples/hilbert-curve/ pela imagem.

Objetivo

Escreva o programa mais curto possível (em bytes) que pega um número inteiro positivo n de stdin e desenha a curva de Hilbert de enésima ordem para stdout usando apenas barra invertida, barra invertida, espaço e nova linha.

Por exemplo, se a entrada for 1a saída, deve ser

 \
\/

Se a entrada for 2a saída deve ser

  /
  \/\
/\   \
 / /\/
 \ \
  \/

Se a entrada for 3a saída deve ser

       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/

E assim por diante. (Eles ficam mais agradáveis ​​se você os colar em algo com menos espaçamento entre linhas.)

A saída não deve conter novas linhas acima ou abaixo das extremidades da curva, nem espaços à direita em nenhuma linha.

Passatempos de Calvin
fonte

Respostas:

10

Ruby, 247 230 205 caracteres

r=?D
y=d=0
z=(1..2*x=2**gets.to_i.times{r.gsub!(/\w/){$&<?H?'-H~+D~D+~H-':'+D~-H~H-~D+'}}-1).map{' '*2*x}
r.bytes{|c|c>99?(z[y-=s=-~d/2%2][x-=1-d/2]='/\\'[d%2]
x+=d/2
y+=1-s):d-=c
d%=4}
puts z.map &:rstrip

Uma abordagem de tartaruga ASCII usando a representação Lindenmayer (tente aqui ).

Muito obrigado a @Ventero por mais golfe.

Howard
fonte
Joguei um pouco mais isso, espero que você não se importe: ideone.com/kvcPWT - .map(&:rstrip)foi necessário adicionar para atender ao requisito "sem espaços à direita".
Ventero
@Ventero Obrigado. Espero que você não se importe que eu tenha tomado sua solução - você pode até descartar as parênteses em torno do argumento do mapa.
224 Howard
Ah, claro! Também acabei de perceber que é possível alinhar a definição xe reduzir a tarefa para ye d, para um total de 205 caracteres (consulte o mesmo link de antes).
Ventero 22/07
12

Python, 282

from numpy import*
def r(n):
 x=2**n-2;b=3*x/2+1;c=x/2+1;a=zeros((x*2+2,)*2,int);a[x+1,x+1]=1;a[b,x/2]=a[x/2,b]=-1
 if n>1:s=r(n-1);a[:x,c:b]=rot90(s,3)*-1;a[c:b,:x]|=rot90(s)*-1;a[c:b,x+2:]|=s;a[x+2:,c:b]|=s
 return a
for l in r(input()):print''.join(' /\\'[c] for c in l).rstrip()

Isso utiliza uma abordagem recursiva para construir a curva de Hilbert de enésima ordem da curva anterior. As curvas são representadas como uma matriz numpy 2D para melhor fatiamento e manipulação.

aqui estão alguns exemplos:

$ python hilbert.py
2
  /
  \/\
/\   \
 / /\/
 \ \
  \/
$ python hilbert.py
3
       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/
$ python hilbert.py
4
              /
              \/\
            /\   \
           / / /\/
           \ \ \  /\
         /\/  \/  \ \
        /   /\  /\/ /
        \/\ \ \ \   \/\
      /\  / /  \ \/\   \
     / /  \/ /\/   / /\/
     \ \/\  /   /\/ /   /\
   /\/   /  \/\ \   \/\ \ \
  /   /\/ /\  / / /\  / / /
  \/\ \  / /  \/ / /  \/  \/\
/\   \ \ \ \/\   \ \/\  /\   \
 / /\/  \/   / /\/   / / / /\/
 \ \  /\  /\/  \  /\/ /  \ \
  \/  \ \ \  /\/  \   \/\ \/
    /\/ / / /   /\ \/\   \
    \   \/  \/\ \ \  / /\/
     \/\  /\  / / /  \ \
       / / /  \/  \/\ \/
       \ \ \/\  /\   \
        \/   / / / /\/
          /\/ /  \ \
          \   \/\ \/
           \/\   \
             / /\/
             \ \
              \/
grc
fonte
5

Malsys - 234 221 caracteres

Sinto o cheiro de alguns sistemas L aqui :) Malsys é um intérprete online do sistema L. Esta não é uma entrada realmente séria, mas senti que esta solução é um pouco interessante.

A sintaxe do Malsys não é muito boa para jogar golfe, pois contém muitas palavras-chave longas, mas ainda assim é bastante curta, legível e expressiva.

lsystem HilbertCurveAscii {
    set symbols axiom = R;
    set iterations = 5;
    set rightAngleSlashMode = true;
    interpret F as DrawLine;
    interpret + as TurnLeft;
    interpret - as TurnRight;
    rewrite L to + R F - L F L - F R +;
    rewrite R to - L F + R F R + F L -;
}
process all with HexAsciiRenderer;

http://malsys.cz/g/3DcVFMWn

Intérprete: http://malsys.cz/Process

Versão Golfed:

lsystem H{set symbols axiom=R;set iterations=3;set
rightAngleSlashMode=1;interpret.as DrawLine;interpret+as
TurnLeft;interpret-as TurnRight;rewrite L to+R.-L.L-.R+;rewrite
R to-L.+R.R+.L-;}process H with HexAsciiRenderer;

E a curva hexagonal de Gosper da Ascii? :)

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

http://malsys.cz/g/ae5v5vGB

NightElfik
fonte
2

JavaScript (ES6) 313 340

Editar Algum caractere removido usando práticas muito ruins - como a variável global w em vez de um valor de retorno da função H

Convertendo a posição x, y na distância d (consulte a Wikipedia ) para cada x, y e verificando se as posições mais próximas estão conectadas,

Teste no console do FireFox. Entrada via pop-up, saída via console.log.

Não há espaços à direita nem novas linhas acima ou abaixo da imagem. Mas cada linha é finalizada com uma nova linha, acho que é a maneira correta de criar uma imagem artística Ascii.

n=1<<prompt(),d=n-1
H=(s,x,y)=>{for(w=0;s>>=1;)p=x&s,q=y&s,w+=s*s*(3*!!p^!!q),q||(p&&(x=s-1-x,y=s-1-y),[x,y]=[y,x])}
for(r=t='';++r<d+n;t+='\n')for(r>d?(x=r-d,f=x-1):(f=d-r,x=0),t+=' '.repeat(f),z=r-x;x<=z;)
h=H(n,y=r-x,x)|w,H(n,y,x-1),x?t+=' \\'[h-w<2&w-h<2]:0,H(n,y-1,x++),y?t+=' /'[h-w<2&w-h<2]:0
console.log(t)
edc65
fonte
Você pode salvar alguns caracteres usando em alertvez de console.log. Você também tem um espaço extra depois da forquarta linha e deve conseguir se livrar dessa última quebra de linha.
22414 Bob
@ Bob Sim, na verdade eu posso salvar mais 15 caracteres, eu desisti de ver que eu tenho mais de 300 de qualquer maneira. Eu não gosto de usar 'alerta' porque a imagem é completamente irreconhecível sem uma fonte de densidade fixa
edc65
2

Perl, 270 caracteres

Super golfed

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;eval's/A|B/$d{$&}/g;'x$n;s/A|B//g;map{if(/F/){if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}$s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]}else{($r+=2*/-/-1)%=4}}/./g;map{print map{$_||$"}@$_,$/}@s

Não é muito golfe

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;
eval's/A|B/$d{$&}/g;'x$n;
s/A|B//g;
map{if(/F/){
    if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}
        $s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]
    }else{
        ($r+=2*/-/-1)%=4
    }
}/./g;
map{print map{$_||$"}@$_,$/}@s

Provavelmente poderia diminuir mais se eu entendesse melhor Perl. Usa uma abordagem de sistema Lindenmayer usando regras de produção definidas na linha 1.

killmous
fonte
2

APL (Dyalog Unicode) , SBCS de 90 bytes

⎕∘←¨' +$'r''¨↓1↓∘⍉∘⌽⍣4' /\'[{3|(⊢+⍉)2@(¯1 0+3 1×s÷2)s⊢(¯.5×≢⍵)⊖(2×s←⍴⍵)↑⍵,⍨-⊖⍵}⍣⎕⊢2 2⍴0]

Experimente online!

2 2⍴0 uma matriz 2x2 de zeros

{ }⍣⎕ introduza N e aplique uma função N vezes

⍵,⍨-⊖⍵ concatenar à esquerda da matriz uma cópia invertida e negada verticalmente de si mesma

(2×s←⍴⍵)↑teclado com zeros para que as dimensões (lembradas como s) sejam duas vezes maiores que o argumento

¯.5×≢⍵ gire para baixo para centralizá-lo verticalmente, imprensado entre os zeros do preenchimento

2@(¯1 0+3 1×s÷2) coloque 2-s em locais específicos - essas são as barras de ligação entre instâncias menores do fractal

(⊢+⍉) adicione a matriz com sua auto transposta

3|módulo 3; usamos negação; portanto, observe que -1≡2 (mod 3) e -2≡1 (mod 3)

' /\'[ ] use os elementos da matriz como índices na sequência ' /\'

1↓∘⍉∘⌽⍣4 aparar a margem vazia de 1 elemento em todos os lados

dividido em linhas

' +$'⎕r''¨ remover espaços à direita de cada um (este desafio exige)

⎕∘←¨ saída cada

ngn
fonte