Skip to content

Instantly share code, notes, and snippets.

@billgathen
Forked from avdi/gol.exs
Last active August 29, 2015 14:05
Show Gist options
  • Save billgathen/ad839ac08c9a66c024d0 to your computer and use it in GitHub Desktop.
Save billgathen/ad839ac08c9a66c024d0 to your computer and use it in GitHub Desktop.
Elixir 0.15.1-compatible version of @avdi implementation of Conway's Game of Life
defmodule Life do
def run(board) when is_binary(board) do
board |> parse_board |> run
end
def run(board) do
IO.write("\e[H\e[2J")
Life.print_board board
:timer.sleep 1000
board = next_board(board)
run(board)
end
def parse_board(board) do
rows = Regex.scan(~r/^[.o]+$/m, board)
Enum.map rows, &String.graphemes(List.first(&1))
end
def print_board(board) do
Enum.each board, fn row ->
IO.puts(Enum.join(row))
end
end
def next_board(board) do
Enum.map Enum.with_index(board), fn { row, y } ->
Enum.map Enum.with_index(row), fn { _, x } ->
next_state(board, x, y)
end
end
end
def next_state(board, x, y) do
cell = cell_at(board, x, y)
live_count = live_neighbors(board, x, y)
next_state(cell, live_count)
end
def next_state("o", live_count) when live_count in 2..3, do: "o"
def next_state("o", _), do: "."
def next_state(".", live_count) when live_count === 3, do: "o"
def next_state(".", _), do: "."
def cell_at(_, x, y) when (x < 0 or y < 0), do: "."
def cell_at(board, x, y) do
case Enum.at(board, y) do
nil -> "."
row -> Enum.at(row, x, ".")
end
end
def live_neighbors(board, x, y) do
Enum.count(neighbors(board, x, y), &(&1 === "o"))
end
def neighbors(board, x, y) do
coords = neighbor_coords(x, y)
Enum.map coords, fn [x,y] -> cell_at(board, x,y) end
end
def neighbor_coords(x, y) do
[[x-1, y-1], [x, y-1], [x+1, y-1],
[x-1, y], [x+1, y],
[x-1, y+1], [x, y+1], [x+1, y+1]]
end
end
board = """
.o......
..o.....
ooo.....
........
........
........
........
........
"""
Life.run(board)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment