Skip to content

Instantly share code, notes, and snippets.

@SegFaultAX
Created July 27, 2012 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SegFaultAX/3190354 to your computer and use it in GitHub Desktop.
Save SegFaultAX/3190354 to your computer and use it in GitHub Desktop.
Python Conway's Game of Life
#!/usr/bin/env python
# Author: Michael-Keith Bernard
# Date: July 27, 2012
#
# Game of Life
#
# Ported from this clojure implementation:
#
# (defn neighbours [[x y]]
# (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
# [(+ dx x) (+ dy y)]))
#
# (defn step [cells]
# (set (for [[loc n] (frequencies (mapcat neighbours cells))
# :when (or (= n 3) (and (= n 2) (cells loc)))]
# loc)))
#
# Notes: See this Lua port of the same implementation:
# https://gist.github.com/3186788
#
# This code is almost definitely not idiomatic Python as such, but was
# written to demonstrate the benefits of hashable and comparable types
# over the relatively simplistic tables provided by Lua.
from os import system
from time import sleep
from random import randint
from collections import defaultdict
def concat(l):
return [e for m in l for e in m]
def mapcat(f, l):
return concat(map(f, l))
def freq(l):
freqs = defaultdict(lambda: 0)
for e in l:
freqs[e] += 1
return freqs
# Game of Life
def neighbors(point):
x, y = point
return [(x+dx, y+dy) for dx in range(-1,2) for dy in range(-1,2)
if not (dx==0 and dy==0)]
def step(cells):
new_cells = set()
for (loc, cnt) in freq(mapcat(neighbors, cells)).items():
if cnt == 3 or (cnt == 2 and loc in cells):
new_cells.add(loc)
return new_cells
def prune(cells, w, h):
new_cells = set()
for (x, y) in cells:
if (x >= 0 and x <= w) and (y >= 0 and y <= h):
new_cells.add((x,y))
return new_cells
def new_board(w, h, fill=True):
board = set()
if fill:
while len(board) < (w * h) / 4:
board.add((randint(0,w), randint(0,h)))
return board
def clear():
system("clear")
def render(board, w, h):
clear()
for y in range(h):
for x in range(w):
if (x,y) in board:
print "#",
else:
print ".",
print
print
def conway(w, h):
board = new_board(w, h)
gen = 0
while True:
if gen > 50 and randint(1, 100) > 95:
board = new_board(w, h)
gen = 0
gen += 1
render(board, w, h)
board = prune(step(board), w, h)
sleep(0.125)
conway(20, 20)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment