You are not logged in.
Pages: 1
Anyone here played floodit?
I wrote it in Python, with the explicit goal of keeping it as short as possible, at the cost of readability.
I'm just wondering if anyone can find a way to shorten this code further, for fun.
import fltk, random
colors, path=[fltk.FL_BLACK, fltk.FL_RED, fltk.FL_BLUE, fltk.FL_GREEN, fltk.FL_WHITE, fltk.FL_YELLOW], []
def flip(x, y, color):
if "%d %d" %(x, y) in path: return
path.append("%d %d" %(x, y))
[flip(nx, ny, color) for nx, ny in [[x+1, y], [x-1, y], [x, y+1], [x, y-1]] if 0<=nx<15 and 0<=ny<15 and grid[nx][ny].color()==grid[x][y].color()]
grid[x][y].color(color)
grid[x][y].redraw()
path.pop()
if all([grid[r][c].color()==grid[r][c-1].color() for r in range(15) for c in range(15)]): fltk.fl_message("You win!")
app=fltk.Fl_Window(425, 475, "Flood-It")
app.begin()
grid=[[fltk.Fl_Box(fltk.FL_FLAT_BOX, x*25+25, y*25+75, 25, 25, "") for x in xrange(15)] for y in xrange(15)]
[square.color(random.choice(colors)) for row in grid for square in row]
[button.callback(lambda button: flip(0,0, button.color())) or button.color(colors.pop()) for button in [fltk.Fl_Button((x%3*25)+25, (x/3*25)+15, 25, 25) for x in xrange(6)]]
app.show()
fltk.Fl.run()
btw: This code does not keep track of how many turns you have played
Offline
I'm sure that with a complete rewrite there's a lot that can be removed from this. I really enjoy obfuscating python, so I hope to take a look at it at the weekend, but for now you can cut out about 200 characters with a couple of small changes:
from fltk import *;c,p,t,f,z,a,r=[56,88,216,63,255,95],[],25,15,0,Fl_Window(425,475,"Flood-It"),__import__('random')
def w(x,y,color):
if(x,y)in p or p.append((x,y)):return
[flip(e,f,color)for e,f in[[x+1,y],[x-1,y],[x,y+1],[x,y-1]]if 0<=e<f and 0<=f<f and g[e][f].color()==g[x][y].color()];g[x][y].color(color);g[x][y].redraw();p.pop()
if all([g[r][c].color()==g[r][c-1].color()for r in range(f)for c in range(f)]):fl_message("You win!")
g=[[Fl_Box(1,x*t+t,y*t+t,t,t,"")for x in range(f)] for y in range(f)];a.begin();[square.color(r.choice(c))for row in g for square in row];[b.callback(lambda b:w(0,0,b.color()))or b.color(c.pop())for b in[Fl_Button((x%3*t)+t,(x/3*t)+f,t,t)for x in range(6)]];a.show();Fl.run()
EDIT: noticed a few more redundancies -- now down ~270 characters
Last edited by AlecSchueler (2010-05-11 17:38:57)
Offline
How does replacing newlines with semicolons help size? It is one byte either way. The single biggest savings would be from replacing the "button" variable with just "b". Some more savings by using product(range(15), repeat=2) instead of nested list comprehensions. Use "import fltk as f, random as r".
It might be better to store the grid not as a 2D list, but as a dictionary with (x,y) tuples as keys and the data as values.
Last edited by keenerd (2010-05-11 17:35:17)
Offline
How does replacing newlines with semicolons help size?
Some people count display size as well as the size in bytes. It also makes it harder to read, which I took as an additional goal implicitly stated by the topic title.
The single biggest savings would be from replacing the "button" variable with just "b".
You beat me to it. I was just revisiting the thread to make this change.
Use "import fltk as f, random as r"
I tried this, but `from fltk import *` was shorter. That was actually before I replaced a lot of stuff with the literal values though, so that may not be the case now. I'll try it again shortly.
Last edited by AlecSchueler (2010-05-11 17:47:10)
Offline
It cuts out a single byte
import fltk as F,random as r;c,p,t,f,z,a=[56,88,216,63,255,95],[],25,15,0,F.Fl_Window(425,475,"Flood-It")
def w(x,y,color):
if(x,y)in p or p.append((x,y)):return
[flip(e,f,color)for e,f in[[x+1,y],[x-1,y],[x,y+1],[x,y-1]]if 0<=e<f and 0<=f<f and g[e][f].color()==g[x][y].color()];g[x][y].color(color);g[x][y].redraw();p.pop()
if all([g[r][c].color()==g[r][c-1].color()for r in range(f)for c in range(f)]):F.fl_message("You win!")
g=[[F.Fl_Box(1,x*t+t,y*t+t,t,t,"")for x in xrange(f)] for y in xrange(f)];a.begin();[square.color(r.choice(c))for row in g for square in row];[button.callback(lambda b:w(0,0,b.color()))or button.color(c.pop())for button in[F.Fl_Button((x%3*t)+t,(x/3*t)+f,t,t)for x in xrange(6)]];a.show();F.Fl.run()
Offline
Too lazy to super crunch it. Itertools might have been a wash. Setattr(c) was also futile. But using a dict of tuples helped quite a bit! I am annoyed with the offset calculations, there must be a better way. Untested.
import fltk as F, random as r, itertools as i
cs,pa=[56,88,216,63,255,95],[]
def f(p, c):
if p in pa or min(p) < 0 or max(p)>15: return
pa.append(p)
[f(p2,c) for p2 in [(p[0]+o[0], p[1]+o[1]) for o in [(1,0),(-1,0),(0,1),(0,-1)]] and g[p2].c()==g[p].c()]
g[p].c(c)
g[p].redraw()
pa.pop()
if all(g[(0,0)].c() == v.c() for v in g.values()): F.fl_message("You win!")
a=F.Fl_Window(425, 475, "Flood-It")
a.begin()
g=dict((x,y),F.Fl_Box(1, x*25+25, y*25+75, 25, 25, "") for x,y in i.product(range(15), repeat=2))
[s.__setattr__('c', s.color) for s in g.values()]
[s.c(r.choice(cs)) for s in g.values()]
[b.callback(lambda b: f((0,0), b.color())) or b.color(cs.pop()) for b in [F.Fl_Button((x%3*25)+25, (x/3*25)+15, 25, 25) for x in xrange(6)]]
a.show()
F.Fl.run()
Decoder ring:
cs colors
c color
F fltk
r random
i itertools
pa path
f flip
g grid
s square
a app
b button
o offset
p point
Last edited by keenerd (2010-05-11 18:48:42)
Offline
lol, this is awesome
I actually only had lines in mind, but I was considering counting characters. I definitely wouldn't use newlines though, even though it helps obfuscation--they're like pseudo-cheating
Interesting that so "clean" a language doesn't have to be, though. Come to think of it, my code looks relatively clean compared to some of the other implementations here...
Offline
Pages: 1