Langage de description de peinture Mondrian

16

Ce défi consiste à coder un interpréteur pour un langage de description de peinture Mondrian (MPDL).

Définition du langage

Le langage fonctionne sur une pile de rectangles. Un rectangle est défini par sa coordonnée supérieure gauche et sa coordonnée inférieure droite. Les coordonnées doivent être des entiers. La pile est initialisée avec un seul rectangle avec des attributs(1,1,254,254)

Chaque commande a le format suivant: <character><integer>

Il existe trois commandes:

v<integer>: effectuer un fractionnement vertical sur le dernier rectangle de la pile, à la position indiquée par le paramètre (en pourcentage). Le rectangle source est supprimé de la pile et remplacé par les deux nouveaux rectangles résultant du fractionnement. Le rectangle gauche est poussé sur la pile, puis le rectangle droit. Comme les coordonnées rectangulaires sont des entiers, les fractions doivent être arrondies au plus grand entier le plus petit.

h<integer>: fente horizontale. Le rectangle supérieur est poussé sur la pile, puis le rectangle inférieur.

c<integer>: supprime le dernier rectangle de la pile et le peint à la couleur donnée en paramètre. 1 = blanc, 2 = rouge, 3 = bleu, 4 = jaune

Défi

Écrivez un programme qui prend en paramètre une description de peinture et crée une représentation bitmap 256x256 des rectangles peints. Les rectangles doivent être séparés par une ligne noire de 3 pixels. Un rectangle d'un ou deux pixels doit avoir ses pixels non noirs masqués par les pixels noirs de bordure.

L'entrée peut être lue comme un paramètre ou comme un fichier, selon vous. Les commandes doivent être séparées par un espace. Vous pouvez supposer que le fichier d'entrée a une syntaxe correcte et n'a pas d'espaces de fin ou de début, des tabulations, etc. La sortie peut être directement affichée à l'écran, ou enregistrée dans un fichier, jusqu'à vous.

Le code le plus court gagne.

Tester

La source suivante:

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

Devrait produire la composition II en rouge, bleu et jaune :

entrez la description de l'image ici

Arnaud
la source
1
La langue n'est pas géniale. vet les harguments doivent être en pixels
John Dvorak
De plus, je ne sais pas quel est l'intérêt de faire tourner la pile au lieu de sauter.
John Dvorak
L'utilisation de pourcentages vous permet de choisir la taille de l'image bitmap de sortie - le résultat sera le même (seulement il sera mis à l'échelle)
Arnaud
1
Oui quelque chose comme ça, mais notez que vous pouvez toujours vous passer d'éléments de syntaxe supplémentaires car tous les opérateurs ont un nombre constant de paramètres. Ainsi, ce qui précède peut toujours être analysé lorsqu'il est représenté par v30 v50 c1 c5 h70 v50 c1 c3 c2.
nutki
3
J'espère vraiment que quelqu'un écrit une solution dans Piet !
Skyler

Réponses:

6

Perl 5 + ImageMagick - 297

Quelque chose pour commencer:

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"

Prend des entrées sur la ligne de commande et génère a.gif.

nutki
la source
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

Le programme lit les instructions sur une seule ligne de stdin , si cela est inacceptable, faites-le moi savoir.

Compile dans un programme qui prend les drapeaux -w largeur -h hauteur -o fichier de sortie . Génère un fichier "a.svg", si ce n'est pas immédiatement clair dans le code. Étant donné que la sortie est une image vectorielle, elle n'est pas «pixel parfaite».

C'est la première fois que je travaille avec Diagrams -package, n'hésitez pas à signaler toutes les erreurs que j'ai faites. Surtout n'importe quel backend qui me permettrait de produire avec moins de code serait bien.

Vous pouvez voir certaines des premières étapes que j'ai prises lors du développement du code dans http://paste.hskll.org/get/1737 . Il diffère du code ci-dessus dans les importations et manque de principal car le paste.hskll.org fournit son propre environnement principal et de dessin.

shiona
la source
2

Python - 434 405 377 364 361

Mon premier golf en python. Cela peut probablement être BEAUCOUP amélioré, donc toute rétroaction est appréciée.

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
la source
1
Vous pouvez enregistrer un caractère en fusionnant les lignes 4, 5 avec un point-virgule. Aussi a+=[x]au lieu de a.append(x). Et split n'a pas besoin d'argument s'il est séparé par des espaces.
Sp3000
1

HTML + JavaScript ES6 (407)

Testé avec 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
la source
1
Bien plus golfable! x.charAt(0)-> x[0]; x.substr-> x.slice; white yellow-> #fff #ff0; document.getElementById("c")-> c... et plus
edc65
@ edc65 Merci! Je vais l'améliorer encore demain.
Mika Lammi
Merci pour la réponse, mais j'essaye de la tester et j'ai un écran blanc?
Arnaud
@SuperChafouin Quel navigateur utilisez-vous? Je ne pense pas que les fonctions fléchées (et d'autres choses ES6) soient vraiment prises en charge, sauf dans Firefox.
Mika Lammi
1

HTML + JavaScript (ES6) 335

Trop similaire à la réponse @mika - marquage CW.

  • remplacer par une fonction au lieu de scinder ... carte
  • opérateur de diffusion
  • pousser 2 valeurs à la fois
  • opérateur ternaire au lieu des propriétés de fonction

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