Lenguaje de descripción de pintura Mondrian

16

Este desafío consiste en codificar un intérprete para un lenguaje de descripción de pintura Mondrian (MPDL).

Definición del lenguaje

El lenguaje opera en una pila de rectángulos. Un rectángulo se define por su coordenada superior izquierda y su coordenada inferior derecha. Las coordenadas deben ser enteros. La pila se inicializa con un solo rectángulo con atributos(1,1,254,254)

Cada comando tiene el siguiente formato: <character><integer>

Hay tres comandos:

v<integer>: realice una división vertical en el último rectángulo de la pila, en la posición indicada por el parámetro (como porcentaje). El rectángulo de origen se elimina de la pila y se reemplaza con los dos nuevos rectángulos que resultan de la división. El rectángulo izquierdo se empuja sobre la pila, luego el rectángulo derecho. Como las coordenadas del rectángulo son enteros, las fracciones deben redondearse al mayor entero más pequeño.

h<integer>: división horizontal. El rectángulo superior se empuja sobre la pila, luego el rectángulo inferior.

c<integer>: elimina el último rectángulo de la pila y lo pinta al color dado como parámetro. 1 = blanco, 2 = rojo, 3 = azul, 4 = amarillo

Desafío

Escriba un programa que tome como parámetro una descripción de pintura y cree una representación de mapa de bits de 256x256 de los rectángulos pintados. Los rectángulos se deben separar con una línea negra de 3 píxeles. Un rectángulo de uno o dos píxeles debe tener sus píxeles no negros ocultos por los píxeles negros del borde.

La entrada se puede leer como un parámetro o como un archivo, depende de usted. Los comandos deben estar separados por un espacio. Puede suponer que el archivo de entrada tiene la sintaxis correcta y no tiene espacios finales o iniciales, pestañas, etc. El resultado puede mostrarse directamente en la pantalla o guardarse en un archivo.

El código más corto gana.

Prueba

La siguiente fuente:

v25 h71 v93 h50 c4 c1 c1 c2 h71 c3 h44 c1 c1

Debe producir la Composición II en rojo, azul y amarillo :

ingrese la descripción de la imagen aquí

Arnaud
fuente
1
El idioma no es genial. vy los hargumentos deben estar en píxeles
John Dvorak
Además, no estoy seguro de cuál es el punto de girar la pila en lugar de hacer estallar.
John Dvorak
El uso de porcentajes le permite elegir cualquier tamaño para el mapa de bits de salida: el resultado será el mismo (solo se escalará)
Arnaud
1
Sí, algo así, pero tenga en cuenta que aún puede prescindir de elementos de sintaxis adicionales, ya que todos los operadores tienen un número constante de parámetros. Por lo tanto, lo anterior aún se puede analizar cuando se representa como v30 v50 c1 c5 h70 v50 c1 c3 c2.
nutki
3
¡Realmente espero que alguien escriba una solución en Piet !
Skyler

Respuestas:

6

Perl 5 + ImageMagick - 297

Algo para comenzar:

sub a{my($x,$y,$X,$Y,$d)=@_;$_=shift@ARGV;
/v/?a($d=$x+($X-$x)*$'/100,$y,$X,$Y).a($x,$y,$d,$Y):
/h/?a($x,$d=$y+($Y-$y)*$'/100,$X,$Y).a($x,$y,$X,$d):
/c/&&"-fill ".qw/white red blue yellow/[$'-1]." -draw 'rectangle $x,$y $X,$Y' "}
system"convert -size 256x256 -stroke black xc: ".a(0,0,255,255)."a.gif"

Toma entrada en la línea de comando y genera a.gif.

nutki
fuente
2

Haskell - 335

import Diagrams.Prelude
import Diagrams.Backend.SVG
c=centerXY
d((x:n):i)|x=='v'=(b#scaleX s#c|||a#scaleX(1-s)#c,k)|x=='h'=(b#scaleY s#c===a#scaleY(1-s)#c,k)|x=='c'=(square 1#fc([white,red,blue,yellow]!!(read n-1)),i)where{s=(read n)/100;(a,j)=d i;(b,k)=d j}
main=getLine>>=renderSVG"a.svg"(Width 256).pad 1.02.c.lwG 0.012.fst.d.words

El programa lee las instrucciones como una línea de stdin , si esto es inaceptable, hágamelo saber.

Se compila en un programa que toma banderas -w ancho -h altura -o archivo de salida . Emite un archivo "a.svg", si eso no se borra inmediatamente del código. Dado que la salida es una imagen vectorial, no es 'píxel perfecto'.

Esta es la primera vez que trabajo con el paquete Diagramas, no dude en señalar cualquier error que haya cometido. Especialmente cualquier backend que me permita generar resultados con menos código sería bueno.

Puede ver algunos de los primeros pasos que tomé al desarrollar el código en http://paste.hskll.org/get/1737 . Se diferencia del código anterior en las importaciones y carece de main ya que paste.hskll.org proporciona su propio entorno principal y de dibujo.

shiona
fuente
2

Python - 434 405 377 364 361

Mi primer golf de pitón. Esto probablemente se puede mejorar MUCHO, por lo que se agradece cualquier comentario.

from turtle import*
a=[[1,1,254,254]]
for c in input().split():
 v,w,x,y=a.pop();p,b,f,g=int(c[1::1]),'hvc'.index(c[0]),x-v,y-w
 if b>1:goto(v,-w),color('#000',['#fff','red','#00f','#ff0'][p-1]),begin_fill(),[(fd(o),rt(90))for o in[f,g]*2],end_fill()
 else:a+=[[v,w,(x,v+(((x-v)/100)*p))[b],(w+(((y-w)/100)*p),y)[b]])],a+=[[[v,a[-1][2]][b],[a[-1][3],w][b],x,y]]
William Barbosa
fuente
1
Puede guardar un carácter combinando las líneas 4 y 5 con un punto y coma. También en a+=[x]lugar de a.append(x). Y split no necesita un argumento si se separa por espacios en blanco.
Sp3000
1

HTML + JavaScript ES6 (407)

Probado con Firefox 32.0.3

<canvas id=c width=256 height=256><script>r=[[1,1,253,253]]
p=x=>r.push(x)
o=c.getContext("2d")
o.lineWidth=3
prompt().split(" ").map(x=>{q=r.pop()
v=q[0]
b=q[1]
n=q[2]
m=q[3],{c:x=>{o.beginPath()
o.rect(v,b,n,m)
o.fillStyle=[,"#fff","red","blue","#ff0"][x]
o.fill()
o.stroke()},v:x=>{s=x/100*n|0
p([v,b,s,m])
p([v+s,b,n-s,m])},h:x=>{s=x/100*m|0
p([v,b,n,s])
p([v,b+s,n,m-s])}}[x[0]](+x.slice(1))})</script>

Mika lammi
fuente
1
¡Mucho más golfable! x.charAt(0)-> x[0]; x.substr-> x.slice; white yellow-> #fff #ff0; document.getElementById("c")-> c... y más
edc65
@ edc65 ¡Gracias! Lo mejoraré aún más mañana.
Mika Lammi
Gracias por la respuesta, pero trato de probarlo y tengo una pantalla en blanco.
Arnaud
@SuperChafouin ¿Qué navegador estás usando? No creo que las funciones de flecha (y otras cosas de ES6) sean realmente compatibles, excepto en Firefox.
Mika Lammi
1

HTML + JavaScript (ES6) 335

Demasiado similar a @mika answer - marcando CW.

  • reemplazar con función en lugar de dividir ... mapa
  • operador de propagación
  • empuje 2 valores a la vez
  • operador ternario en lugar de propiedades de función

<canvas id=c><script>
c.width=c.height=256,
s=[[1,1,253,253]],
o=c.getContext('2d'),
o.translate(0.5,0.5), // to avoid anti-alias on straight lines
o.lineWidth=3,
prompt().replace(/(\S)(\d+)/g,(_,c,n)=>(
p=s.pop(o.fillStyle=[,'#fff','red','#00f','#ff0'][n]),
c<'d'?(o.fillRect(...p),o.strokeRect(...p))
:(c=c<'i'|2,
 q=[...p],
 q[c]=r=q[c]*n/100|0,
 p[c]-=r,
 p[c-2]+=r,
 s.push(q,p))))
</script>

revs edc65
fuente