Me gustan los árboles pitagóricos

17

... así que este es un desafío para hacerme un árbol.

Produzca un programa o función llamado árbol que tome un solo argumento entero, N y dibuje un árbol de Pitágoras N niveles profundos, donde el nivel 0 es solo el tronco.

Cada unión del árbol debe colocar el vértice del triángulo en un punto aleatorio en el perímetro (este punto debe estar distribuido uniformemente en al menos 5 puntos igualmente espaciados, o uniformemente en todo el semicírculo).

Opcionalmente, su árbol puede ser 3d, ser colorido o estar iluminado según la hora del día. Sin embargo, este es el código de golf, por lo que gana el archivo más pequeño.

EDITAR: cerraré el concurso y aceptaré la respuesta más pequeña cuando tenga una semana

alexander-brett
fuente
Parece ser un duplicado: codegolf.stackexchange.com/questions/18785/…
DavidC
Falso. Estoy buscando un algoritmo diferente :)
alexander-brett
Okay. Lo suficientemente justo. Es posible que desee considerar volver a titular su envío al "Árbol de Pitágoras".
DavidC
¿Me gustan los trenes? :)
tomsmeding

Respuestas:

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@#&

Ciertamente, esta no es la forma más elegante / más corta de hacer esto.

Uso: f[8]

ingrese la descripción de la imagen aquí

Y aquí hay ejemplos de salidas para f[6]y f[10]respectivamente.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Algo descabellado:

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[#] &
Martin Ender
fuente
Eso es bastante impresionante. Es una pena que no tenga Mathica para probarlo, ¿podría agregar otro par de resultados de ejemplo?
alexander-brett
@ ali0sha ver edición
Martin Ender
No necesita Showallí, y Moduletambién es innecesario.
swish
@swish Gracias por la Showpista, pero ¿cómo puedo deshacerme de él Module? Si no declaro plocal, se sobrescribirá en las llamadas recursivas, por lo que no podría hacer ambas llamadas con el mismo p, ¿verdad?
Martin Ender
@ m.buettner Tal vez puedas usar Block, que es más corto que Module.
alephalpha
20

CFDG, 134 caracteres

Este no es exactamente válido, porque no puede limitar la profundidad de recursión. Pero el problema solo requiere una solución en este 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]}

Los resultados se parecen a esto

ingrese la descripción de la imagen aquí

Para otros 46 caracteres ( 180 caracteres en total), incluso puede colorearlo:

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

ingrese la descripción de la imagen aquí

Martin Ender
fuente
Sé que esto no es completamente onópico, pero ¿cómo se vería una versión si en lugar de "ruido blanco", usaras "ruido marrón" como ángulos?
Marıʇǝɥʇuʎs
@Synthetica te refieres con más ángulos alrededor de 90 ° y menos a 0 y 180?
Martin Ender
@Synthetica Similar a esto . No pude implementar el ruido de paseo aleatorio real, porque eso requiere tomar un parámetro de entrada (el último valor aleatorio), ajustarlo y transmitirlo. Esto haría que la gramática sea sensible al contexto y, por lo tanto, no es compatible con CFDG. Lo fingí un poco, simplemente empujando los valores aleatorios un poco más hacia π / 2 usando una función cúbica simple en la muestra aleatoria.
Martin Ender
Creo que su imgur vínculo se rompe, y también mucho aunque me gusta el color y la forma, creo que tengo para descalificar a éste por la razón que usted ha mencionado
Alexander-Brett
@ ali0sha tienes razón, aquí está el enlace fijo . Descalificar a este es absolutamente justo, solo quería compartir Context Free Art con algunas personas y parecía un enfoque ordenado para el problema. ;) ... Bueno, todavía tengo la respuesta de Mathematica ^^
Martin Ender
4

Postdata, 322 270

Editar: Parece que realtimeno se puede usar como semilla generadora aleatoria adecuada. Por lo tanto, utilizaremos la variable de entorno para este propósito y ejecutaremos el programa así:

gs -c 20 $RANDOM -f tree.ps

o

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

Ahora nuestros árboles son menos predecibles. Se agregan 14 bytes al recuento total. Otros cambios: 1) El argumento del programa ahora se pasa en la línea de comando. 2) No hay contador de iteraciones explícito: el tamaño de la pila sirve para este propósito (el ángulo de rotación de la rama izquierda se almacena en la pila, para dibujar la rama derecha, más adelante). 3) No hay una variable con nombre para la profundidad requerida: el tamaño de la pila es su desplazamiento, en la pila. Se deja allí en la salida, es decir, no se consume.

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

Creo que es bastante obvio: el estado de los gráficos está preparado y el fprocedimiento se llama recursivamente para cada nivel consecutivo de profundidad, dos veces, para las ramas 'izquierda' y 'derecha'. Trabajar con un rectángulo de 1x1tamaño (ver escala original) ahorra la molestia de multiplicar por la longitud del lado. El ángulo de rotación de la rama izquierda es aleatorio: se usa una de las 5 divisiones aleatorias equidistantes. Creo que evita posibles casos feos de aleatoriedad uniforme.

Puede ser lento para una profundidad requerida de más de 20 o menos.

La siguiente es la versión de golf, que utiliza tokens binarios codificados en ASCII (consulte la respuesta de luser droog del tema vinculado). Nota, cos, sin, randno puede utilizar esta notación.

/${{<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

ingrese la descripción de la imagen aquí

usuario2846289
fuente
Creo que el estilo aquí es que los argumentos de la línea de comando deben agregarse, por lo que este puntaje es 344 ... Tengo que decir que incluso para los estándares de codegolf esto es bastante impresionante. ¿Hasta dónde podría llegar con tokens binarios? Seguramente no estás lejos de Mathematica
alexander-brett
@ ali0sha, -dGraphicsAlphaBitses un indicador de salida anti-alias para evitar bordes irregulares de cuadrados más grandes, puede omitirse (u 'ocultarse' en, por ejemplo, la variable de entorno). A algunas personas les puede gustar más sin esta bandera (las hojas de los árboles obtienen más 'volumen'). Bueno, esos 20 bytes no son tan importantes. Yo diría que 20-25% de descuento usando tokens binarios codificados en ascii (a juzgar por la respuesta del tema vinculado). Tal vez 50% de descuento sin codificación ascii, 2 bytes binarios por token de nombre del sistema. Se verá como algunos idiomas generalmente ganadores;)
user2846289
Creo que deberías hacerlo, hazlo un poco más competitivo aquí :)
alexander-brett
3

Coffeescript 377B 352B

Me siento sucio escribiendo coffeescript pero no puedo encontrar un paquete de dibujo 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

Un poco más bonito en javascript y estoy mucho más feliz con el bucle for pero sin la sintaxis [x, y, z] = A, simplemente no puedo acortarlo lo suficiente como para superar el coffeescript

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

Tengo que decir que estoy un poco molesto, esto es casi el doble que la solución matemática: - / verlo en acción: http://jsfiddle.net/FK2NX/3/

alexander-brett
fuente
Algunas sugerencias: puede guardar al menos 16 caracteres utilizando punto y coma en lugar de saltos de línea en CoffeeScript. En ambos casos, si alguno de los métodos a Xcambio X, puede encadenarlos. Y puede guardar otro buen grupo de caracteres guardando M.siny M.cosen variables de un solo carácter.
Martin Ender
Desafortunadamente, las operaciones de contexto no devuelven el contexto, lo que me molestó bastante. Además, puede cambiar el nombre de M.sin a Ms, pero la línea Ms = M.sin ocupa más caracteres de los que guarda ... Voy a tratar de eliminar los espacios.
alexander-brett
No, solo puedes hacerlo s=M.sin.
Martin Ender
¿Cómo es que puedo hacer S = M.sin, pero no R = X.rotate?
alexander-brett
Supongo que rotateusa this, y sinno. Tendría que hacer algo como R=X.rotate.bind(X)eso, pero probablemente ya no valga la pena.
Martin Ender