Abusing python: Game of life using ncurses in one line of code
I like to make one-liners. Not because they are useful but because it’s fun, and it teaches you stuff about the workings of a language and how to abuse it. When I say one-liner, I mean a single statement that does not use eval (otherwise one-liners are trivial) or ; to separate multiple statements.
I have never written any implementation of Conway’s Game of Life before, and tried to see if I could get it done using a single line of code.
I started out by coding a function that when given a sequence of (x,y) coordinate tuples returned a new dictionary with the next set of coordinates set to True. The choice of a dict for the return value was actually not perfect, as a set would have done just fine, but I used a dictionary earlier in the algorithm for checking which of the coordinates that should be alive, and I didn’t really see any need to rewrite it since a dict here pretty much is a set with a (in this case) redundant value.
The first working algorithm looked like this:
def get_next(old):
new, new2 = {}, {}
offset = ((-1, -1),(-1, 0),(-1, 1),(0, -1),
(0, 1),(1, -1),(1, 0),(1, 1))
for (x, y) in old:
for (ox, oy) in offset:
new[(x+ox, y+oy)] = \
new.get((x+ox, y+oy), 0) + 1
for (x, y) in new:
v = new[(x, y)]
if v == 3 or v == 2 and (x, y) in old:
new2[(x, y)] = True
return new2
A bit of abuse got this down to a single line that looked like this (as you might see, the backslashes are used to make this more readable, it really is just a single line of code.
def get_next(old): return globals().__setitem__("new",{}) \
or globals().__setitem__("new2",{}) or \
[[new.__setitem__((x+ox,y+oy),
new.get((x+ox,y+oy), 0) + 1) \
for (ox, oy) in ((-1, -1),(-1, 0),(-1, 1),(0, -1),(0, 1),
(1, -1),(1, 0),(1, 1))] for (x,y) in old if old[(x,y)]] \
and [new2.__setitem__((x,y),True) for (x,y) in new if \
(new[(x,y)] == 3 or new[(x,y)] == 2 and (x,y) in old)] and new2
This works fine for getting the next “map” of the game of life, but how fun is that? I wanted ncurses support so that I could actually see this. Eventually I ended up with this:
print globals().__setitem__("f",globals().__setitem__) or \
f("d",{(1,2):True,(2,3):True,(3,1):True,(3,2):True,(3,3):True,}) \
or f("curses",__import__("curses")) or f("stdscr", curses.initscr()) \
or stdscr.nodelay(1) or curses.noecho() or curses.cbreak() \
or (curses.curs_set(0) or 1) and f("bar",[1]) or [1]+[(bar.append(1) \
or stdscr.clear() or [1]+[stdscr.addstr(0,0,"Press q to quit") \
or stdscr.addch(y%20+1,x%20,"x") for (x,y) in d] and stdscr.refresh() \
or __import__("time").sleep(0.2) or f("d",(lambda old: f("new",{}) \
or f("new2",{}) or [[new.__setitem__((x+ox,y+oy),
new.get((x+ox,y+oy), 0) + 1) \
for (ox, oy) in ((-1, -1),(-1, 0),(-1, 1),(0, -1),(0, 1),
(1, -1),(1, 0),(1, 1))] \
for (x,y) in old if old[(x,y)]] and [new2.__setitem__((x,y),True) \
for (x,y) in new if (new[(x,y)] == 3 or new[(x,y)] == 2 and (x,y) \
in old)] and new2)(d))) for foo in bar if (stdscr.getch() !=
ord('q'))] and curses.nocbreak() or stdscr.keypad(0) or \
curses.echo() or curses.endwin() or "Bye!"
Now THAT is a one-liner!
Running this creates a ncurses window and a “glider” that will move on forever (wraps to x=0,y=0 at position x=20,y=20).
Here are some pics of it running:
![]()
![]()
![]()
If you want to run this yourself to have a look you can download the one-liner here. It should work on any unix/linux/mac-system supporting ncurses. I don’t think that ncurses works in more obscure operating systems such as windows so if you are a windows user then you will just have to take my word on that it works ![]()
This version also lacks the line separation backslashes used for the presentation here which perhaps makes it clearer that it is just a single line of (rather horrible) code.
Like I said, I am well aware of the fact that this code isn’t pretty, it isn’t meant to be. It does however contain a nice bunch of clever tricks that some people might not be aware of.
Recent Comments