Created
July 27, 2012 20:34
-
-
Save SegFaultAX/3190354 to your computer and use it in GitHub Desktop.
Python Conway's Game of Life
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 ".", | |
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