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


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.


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.


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

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>


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>

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.