Linguagem de descrição de pintura Mondrian

16

Esse desafio consiste em codificar um intérprete para uma linguagem de descrição de pintura Mondrian (MPDL).

Definição de idioma

A linguagem opera em uma pilha de retângulos. Um retângulo é definido por sua coordenada superior esquerda e inferior direita. As coordenadas devem ser números inteiros. A pilha é inicializada com um único retângulo com atributos(1,1,254,254)

Cada comando tem o seguinte formato: <character><integer>

Existem três comandos:

v<integer>: faça uma divisão vertical no último retângulo da pilha, na posição indicada pelo parâmetro (como porcentagem). O retângulo de origem é removido da pilha e substituído pelos dois novos retângulos resultantes da divisão. O retângulo esquerdo é pressionado na pilha e o retângulo direito. Como as coordenadas retangulares são números inteiros, as frações devem ser arredondadas para o maior número menor menor.

h<integer>: divisão horizontal. O retângulo superior é pressionado na pilha e o retângulo inferior.

c<integer>: remove o último retângulo da pilha e o pinta na cor fornecida como parâmetro. 1 = branco, 2 = vermelho, 3 = azul, 4 = amarelo

Desafio

Escreva um programa que tome como parâmetro uma descrição de pintura e crie uma representação de bitmap de 256x256 dos retângulos pintados. Os retângulos devem ser separados por uma linha preta de 3 pixels. Um retângulo de um ou dois pixels deve ter seus pixels não pretos ocultos pelos pixels pretos da borda.

A entrada pode ser lida como um parâmetro ou como um arquivo, até você. Os comandos devem ser separados por um espaço. Você pode assumir que o arquivo de entrada possui sintaxe correta e não possui espaços à esquerda ou à esquerda, guias, etc. A saída pode ser exibida diretamente na tela ou salva em um arquivo, até você.

O código mais curto vence.

Teste

A seguinte fonte:

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

Deve produzir a composição II em vermelho, azul e amarelo :

insira a descrição da imagem aqui

Arnaud
fonte
11
A linguagem não é ótima. ve hargumentos devem estar em pixels
John Dvorak
Além disso, não sei ao certo qual é o objetivo de girar a pilha em vez de estourar.
John Dvorak
Usando percentagens permite-lhe escolher o tamanho para o bitmap de saída - o resultado será a mesma (só que será escalado)
Arnaud
11
Sim, algo assim, mas observe que você ainda pode ficar sem elementos extras de sintaxe, pois todos os operadores têm um número constante de parâmetros. Portanto, o acima pode ainda ser analisado quando representado como v30 v50 c1 c5 h70 v50 c1 c3 c2.
nutki
3
Realmente esperando que alguém escreva uma solução em Piet !
Skyler #

Respostas:

6

Perl 5 + ImageMagick - 297

Algo para começar:

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"

Pega entrada na linha de comando e gera a.gif.

nutki
fonte
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

O programa lê as instruções como uma linha do stdin , se isso for inaceitável, me avise.

Compila em um programa que recebe sinalizadores -w width -h height -o outputfile . Produz um arquivo "a.svg", se isso não estiver imediatamente claro no código. Como a saída é uma imagem vetorial, não é 'pixel perfeito'.

Esta é minha primeira vez trabalhando com o pacote de diagramas, sinta-se à vontade para apontar os erros que cometi. Especialmente qualquer back-end que me permitisse produzir com menos código seria bom.

Você pode ver algumas das primeiras etapas que tomei ao desenvolver o código em http://paste.hskll.org/get/1737 . Ele difere do código acima em importações e não possui main, pois o paste.hskll.org fornece seu próprio ambiente principal e de desenho.

shiona
fonte
2

Python - 434 405 377 364 361

Meu primeiro golfe python. Provavelmente isso pode ser melhorado MUITO, então qualquer feedback é apreciado.

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
fonte
11
Você pode salvar um caracter mesclando as linhas 4, 5 com um ponto e vírgula. Também em a+=[x]vez de a.append(x). E split não precisa de argumento se estiver separado por espaços em branco.
Sp3000
1

HTML + JavaScript ES6 (407)

Testado com 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
fonte
11
Muito mais jogável! x.charAt(0)-> x[0]; x.substr-> x.slice; white yellow-> #fff #ff0; document.getElementById("c")-> c... e mais #
edc65
@ edc65 Obrigado! Vou melhorar ainda mais amanhã.
Mika Lammi
Obrigado pela resposta, mas tento testá-lo e tenho uma tela branca?
Arnaud #
@SuperChafouin Qual navegador você está usando? Eu não acho que as funções de seta (e outras coisas do ES6) sejam realmente suportadas, exceto no Firefox.
Mika Lammi #
1

HTML + JavaScript (ES6) 335

Muito semelhante à resposta @mika - marcação CW.

  • substituir por função em vez de dividir ... mapa
  • operador de propagação
  • pressione 2 valores de uma só vez
  • operador ternário em vez de propriedades da função

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

edc65
fonte