Eu gosto de árvores pitagóricas


17

... então este é um desafio para me fazer uma árvore.

Produza um programa ou função chamado tree que utiliza um único argumento inteiro N e desenha uma árvore Pitagórica N níveis profundamente, onde o nível 0 é apenas o tronco.

Cada junção da árvore deve colocar o vértice do triângulo em um ponto aleatório no perímetro (este ponto deve ser distribuído uniformemente por pelo menos 5 pontos igualmente espaçados ou uniformemente por todo o semicírculo).

Opcionalmente, sua árvore pode ser 3d, colorida ou iluminada de acordo com a hora do dia. No entanto, isso é código-golfe, portanto o menor arquivo vence.

EDIT: Vou encerrar o concurso e aceitar a menor resposta quando tiver uma semana



Falso. Estou depois de um algoritmo diferente :)
alexander-Brett

Está bem. Justo. Você pode considerar voltar a enviar a sua "Árvore Pitagórica".
DavidC

Eu gosto de trens? :)
tomsmeding

Respostas:


15

Mathematica, 246 234 221 caracteres

g[n_,s_:1]:={p=RandomReal[q=Pi/2],r=##~Rotate~(o={0,0})&,t=Translate}~With~If[n<0,{},Join[#~t~{0,s}&/@(#~r~p&)/@g[n-1,s*Cos@p],t[#,s{Cos@p^2,1+Sin[2p]/2}]&/@(r[#,p-q]&)/@g[n-1,s*Sin@p],{Rectangle[o,o+s]}]]
f=Graphics@g@#&

Esta certamente não é a maneira mais elegante / mais curta de fazer isso.

Uso: f[8]

insira a descrição da imagem aqui

E aqui estão exemplos de saídas para f[6]e f[10]respectivamente.

insira a descrição da imagem aqui insira a descrição da imagem aqui

Um pouco não-destruído:

g[n_, s_:1] := With[{p},
  r = Rotate;
  t = Translate;
  p = RandomReal[q = Pi/2];
  If[n < 0, {},
   Join[
    (t[#, {0, s}] &) /@ (r[#, p, {0, 0}] &) /@ g[n - 1, s*Cos[p]],
    (t[#, s {Cos[p]^2, 1 + Sin[2 p]/2}] &) /@ (r[#, p - q, {0, 0}] &) /@
       g[n - 1, s*Sin[p]],
    {Rectangle[{0, 0}, {s, s}]}
    ]
   ]
  ]
f = Graphics@g[#] &

Isso é bastante impressionante. Pena que não tenho o mathematica para testá-lo - você poderia adicionar mais alguns exemplos de saídas?
alexander-Brett

@ ali0sha see edit #
Martin Ender

Você não precisa Showlá e Moduletambém é desnecessário.
swish

@swish Obrigado pela Showdica, mas como posso me livrar Module? Se eu não declarar plocal, ele será sobrescrito nas chamadas recursivas, então não poderia fazer as duas chamadas da mesma forma p, certo?
Martin Ender

@ m.buettner Talvez você possa usar Block, que é menor que Module.
alephalpha

20

CFDG, 134 caracteres

Este não é exatamente válido, porque você não pode limitar a profundidade da recursão. Mas o problema exige apenas uma solução nesse caso . :)

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5]t[trans 0 1 c(w) d(w)]t[trans c(w) d(w) 1 1]}

Os resultados são parecidos com este

insira a descrição da imagem aqui

Para outros 46 caracteres ( 180 caracteres no total), você pode até colorir:

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5 h 25 sat 1 b .2]t[trans 0 1 c(w) d(w) b .08 .8 h 2.2]t[trans c(w) d(w) 1 1 b .08 .8 h 2.2]}

insira a descrição da imagem aqui


Eu sei que isso não é totalmente ontopico, mas como seria uma versão se, em vez de "ruído branco", você usasse "ruído marrom" como ângulos?
ɐɔıʇǝɥʇuʎs

@ Síntese você quer dizer com mais ângulos em torno de 90 ° e menos em 0 e 180?
Martin Ender

@ Synthetica Semelhante a isso . Eu não conseguia implementar o ruído real de caminhada aleatória, porque isso requer pegar um parâmetro de entrada (o último valor aleatório), ajustá-lo e transmiti-lo. Isso tornaria a gramática sensível ao contexto e, portanto, não é suportada pelo CFDG. Fingi levemente, simplesmente empurrando os valores aleatórios um pouco mais para π / 2 usando uma função cúbica simples na amostra aleatória.
Martin Ender

Eu acho que o seu imgur ligação é interrompida, e também muito embora eu apreciar a cor ea forma, eu acho que tenho de desqualificar esta a razão para que você mencionou
alexander-Brett

@ ali0sha você está certo, aqui está o link fixo . Desqualificar esta é absolutamente justo, eu só queria compartilhar a Arte Livre de Contexto com algumas pessoas e parecia uma abordagem interessante para o problema. ;) ... Bem, eu ainda tenho a resposta do Mathematica ^^
Martin Ender

4

Postscript, 322 270

Editar: parece que realtimenão pode ser usado como semente geradora aleatória adequada. Portanto, usaremos a variável de ambiente para esse fim e executaremos o programa assim:

gs -c 20 $RANDOM -f tree.ps

ou

gswin32c -c 20 %RANDOM% -f tree.ps

Agora nossas árvores são menos previsíveis. 14 bytes são adicionados à contagem total. Outras alterações: 1) O argumento do programa agora é passado na linha de comando. 2) Nenhum contador explícito de iteração - o tamanho da pilha serve para esse propósito (o ângulo de rotação da ramificação esquerda é armazenado na pilha, para desenhar a ramificação direita posteriormente). 3) Não há variável nomeada para a profundidade necessária - o tamanho da pilha é seu deslocamento, na pilha. É deixado lá na saída, ou seja, não é consumido.

srand
250 99 translate
50 50 scale
/f{
    count
    dup index div dup 1 le{
        0 exch 0 setrgbcolor
        0 0 1 1 rectfill
        0 1 translate
        rand 5 mod 1 add 15 mul
        gsave
        dup rotate
        dup cos dup scale
        f
        grestore
        dup cos dup dup mul
        exch 2 index sin mul translate
        dup 90 sub rotate
        sin dup scale 1
        f
        pop
    }{pop}ifelse
}def
f

Eu acho que é bastante óbvio - o estado dos gráficos é preparado e o fprocedimento é chamado recursivamente para cada nível consecutivo de profundidade, duas vezes - para os ramos 'esquerdo' e 'direito'. Trabalhar com retângulos de 1x1tamanho (consulte a escala original) evita o problema de multiplicar pelo comprimento lateral. O ângulo de rotação do ramo esquerdo é randomizado - uma das 5 divisões aleatórias igualmente espaçadas - é usada para evitar possíveis casos feios para uma aleatoriedade uniforme.

Pode ser lento para a profundidade necessária de mais de 20 ou mais.

A seguir, é apresentada a versão golf, usando tokens binários codificados em ASCII (consulte a resposta do luser droog no tópico vinculado). Note, cos, sin, randnão pode usar esta notação.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def srand 250 99<AD>$ 50 50<8B>$/f{count(8X68)$ 1 le{0(>)$ 0<9D>$ 0 0 1 1<80>$ 0 1<AD>$ rand 5 mod 1 add 15<~CecsG2u~>$ cos<388B>$ f(M8)$ cos(88l>)$ 2(X)$ sin<6CAD38>$ 90<A988>$ sin<388B>$ 1 f pop}{pop}(U)$}def f

.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def
srand
250 99<AD>$
50 50<8B>$
/f{
count(8X68)$
1 le{
0(>)$ 0<9D>$
0 0 1 1<80>$
0 1<AD>$
rand 5 mod 1 add 15 
<~CecsG2u~>$
cos<388B>$ 
f
(M8)$
cos(88l>)$
2(X)$ sin<6CAD38>$
90<A988>$ sin<388B>$
1
f
pop
}{pop}(U)$
}def
f

insira a descrição da imagem aqui


Eu acho que o estilo aqui é que os argumentos da linha de comando precisam ser adicionados, de modo que esse resultado seja 344 ... Devo dizer que mesmo pelos padrões do codegolf isso parece impressionantemente estrangeiro. Até onde você pode obtê-lo com tokens binários? Você não está longe Mathematica certamente
alexander-Brett

@ ali0sha, -dGraphicsAlphaBitsé um sinalizador para saída de anti-alias para evitar bordas irregulares de quadrados maiores, pode ser omitido (ou 'escondido' em, por exemplo, variável de ambiente). Algumas pessoas podem gostar mais sem essa bandeira (as folhas das árvores ficam mais "volume"). Bem, esses 20 bytes não são muito importantes. Eu diria que 20 a 25% de desconto usando tokens binários codificados em ASCII (a julgar pela resposta do tópico vinculado). Talvez 50% de desconto sem codificação ASCII, 2 bytes binários por token de nome do sistema. Será parecido com algumas linguagens normalmente vencedoras;)
user2846289

Eu acho que você deve fazê-lo - torná-lo um pouco mais competitivos aqui :)
alexander-Brett

3

Coffeescript 377B 352B

Sinto-me sujo escrevendo coffeescript, mas não consigo encontrar um pacote de desenho decente para python3: - /

Q=(n)->X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=400;M=Math;T=[[175,400,50,i=0]];S=M.sin;C=M.cos;while [x,y,l,a]=T[i++]
 X.save();X.translate x,y;X.rotate -a;X.fillRect 0,-l,l,l;X.restore();T.push [e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2] if i<2**n

Javascript 393B 385B

Um pouco mais bonito em javascript e estou muito mais feliz com o loop for, mas sem o [x, y, z] = Uma sintaxe que não posso ser curta o suficiente para superar o café

function Q(n){X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=600;M=Math;T=[[275,400,50,i=0]];while(A=T[i++]){X.save();X.translate(x=A[0],y=A[1]);X.rotate(-(a=A[3]));X.fillRect(0,-(l=A[2]),l,l);X.restore();S=M.sin;C=M.cos;i<M.pow(2,n)&&T.push([e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2])}}

Devo dizer que estou um pouco irritado, isso é quase o dobro da solução mathematica: - / veja em ação: http://jsfiddle.net/FK2NX/3/


Algumas sugestões: Você pode salvar pelo menos 16 caracteres usando ponto e vírgula em vez de quebras de linha no CoffeeScript. Nos dois casos, se algum dos métodos de Xretorno X, você pode encadeá-los. E você pode salvar outro bom grupo de caracteres salvando M.sine M.cosem variáveis ​​de um caractere.
Martin Ender

Infelizmente, as operações de contexto não retornam o contexto, o que me deixou bastante chateado. Além disso, você pode renomear M.sin como Ms, mas a linha Ms = M.sin ocupa mais caracteres do que salva ... Vou ver como remover os espaços.
Alexander-brett

Não, você pode apenas fazer s=M.sin.
Martin Ender

Como é que eu posso fazer S = M.sin, mas não R = X.rotate?
Alexander-brett #

Suponho que rotateusa this, e sinnão. Você precisaria fazer algo assim R=X.rotate.bind(X), mas provavelmente não vale mais a pena.
22868 Martin Ender #
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.