This challenge consists in coding an interpreter for a Mondrian painting description language (MPDL).
Language definition
The language operates on a stack of rectangles.
A rectangle is defined by its upper left coordinate and lower right coordinate. Coordinates must be integers.
The stack is initialized with a single rectangle with attributes (1,1,254,254)
Each command has the following format:
<character><integer>
There are three commands:
v<integer> : perform a vertical split on the latest rectangle in the stack, at the position indicated by the parameter (as percentage). The source rectangle is removed from the stack and replaced with the two new rectangles that result of the split. The left rectangle is pushed on the stack, then the right rectangle. As rectangle coordinates are integers, fractions should be rounded to biggest smaller integer.
h<integer> : horizontal split. The top rectangle is pushed on the stack, then the bottom rectangle.
c<integer> : removes the latest rectangle from the stack and paints it to the color given as parameter. 1 = white, 2 = red, 3 = blue, 4 = yellow
Challenge
Write a program that takes as parameter a painting description and creates a 256x256 bitmap representation of the painted rectangles. The rectangles must be separated with a 3 pixel black line. A one or two pixel rectangle should have his non-black pixels hidden by the border black pixels.
The input can be read as a parameter or as a file, up to you. The commands should be separated by a space. You can assume that the input file has correct syntax and does not have trailing or leading spaces, tabs, etc. The output can be directly displayed on the screen, or saved to a file, up to you.
The shortest code wins.
Test
The following source:
v25 h71 v93 h50 c4 c1 c1 c2 h71 c3 h44 c1 c1
Should produce the Composition II in Red, Blue and Yellow:
enter image description here
5 Answers 5
Perl 5 + ImageMagick - 297
Something to start with:
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"
Takes input on command line and generates a.gif.
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
The program reads the instructions as one line from stdin, if this is unacceptable let me know.
(削除) Compiles into a program that takes in flags -w width -h height -o outputfile. (削除ここまで)
Outputs an "a.svg" file, if that's not immediately clear from the code. Since the output is a vector image, it's not 'pixel perfect'.
This is my first time working with Diagrams -package, feel free to point out any mistakes I made. Especially any backend that would let me output with less code would be nice.
You can see some of the first steps I took when developing the code in http://paste.hskll.org/get/1737. It differs from the code above in imports and lacks main since the paste.hskll.org provides its own main and drawing environment.
Python - (削除) 434 405 377 364 (削除ここまで) 361
My first python golf. This can probably be improved A LOT, so any feedback is appreciated.
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]]
-
1\$\begingroup\$ You can save a char by merging lines 4, 5 with a semicolon. Also
a+=[x]instead ofa.append(x). And split doesn't need an argument if separating by whitespace. \$\endgroup\$Sp3000– Sp30002014年11月05日 00:59:48 +00:00Commented Nov 5, 2014 at 0:59
HTML + JavaScript ES6 (407)
Tested with 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>
-
1\$\begingroup\$ So much more golfable!
x.charAt(0)->x[0];x.substr->x.slice;white yellow->#fff #ff0;document.getElementById("c")->c... and more \$\endgroup\$edc65– edc652014年11月02日 22:36:39 +00:00Commented Nov 2, 2014 at 22:36 -
\$\begingroup\$ @edc65 Thanks! I'll improve it further tomorrow. \$\endgroup\$Mika Lammi– Mika Lammi2014年11月02日 23:04:25 +00:00Commented Nov 2, 2014 at 23:04
-
\$\begingroup\$ Thanks for the answer, but I try to test it and I have a white screen? \$\endgroup\$Arnaud– Arnaud2014年11月03日 02:14:54 +00:00Commented Nov 3, 2014 at 2:14
-
\$\begingroup\$ @SuperChafouin What browser are you using? I don't think that arrow functions (and other ES6 stuff) are really supported except in Firefox. \$\endgroup\$Mika Lammi– Mika Lammi2014年11月03日 06:18:45 +00:00Commented Nov 3, 2014 at 6:18
HTML+JavaScript (ES6) 335
Too similar to @mika answer - marking CW.
- replace with function instead of split...map
- spread operator
- push 2 values at once
- ternary operator instead of function properties
<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>
Explore related questions
See similar questions with these tags.
vandharguments should be in pixels \$\endgroup\$v30 v50 c1 c5 h70 v50 c1 c3 c2. \$\endgroup\$