Skip to content

Instantly share code, notes, and snippets.

@avdi

avdi/gol.exs

Last active Jun 3, 2016
Embed
What would you like to do?
Game of life in Elixir (take 1)
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(&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 board, fn row, y ->
Enum.map 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)
@avdi

This comment has been minimized.

Copy link
Owner Author

@avdi avdi commented Jul 10, 2013

Obviously this version just targets the most basic stuff like functions and pattern matching, there's no process-wrangling here.

@philss

This comment has been minimized.

Copy link

@philss philss commented Jul 17, 2013

@avdi I get an error when running with "Elixir 0.9.4dev". I notice that a comma is missing at line 45:

def next_state(".", _), do: "."
@javichito

This comment has been minimized.

Copy link

@javichito javichito commented Aug 3, 2013

same here

@billgathen

This comment has been minimized.

Copy link

@billgathen billgathen commented Aug 19, 2014

Requires a few minor tweaks to run under Elixir 0.15.1 (including the missing comma). I'm just learning Elixir and really enjoyed debugging this. 😄

15,16c15,16
<     rows = Regex.scan(%r/^[.o]+$/m, board)
<     Enum.map rows, String.graphemes(&1)

---
>     rows = Regex.scan(~r/^[.o]+$/m, board)
>     Enum.map rows, &String.graphemes(List.first(&1))
26,27c26,27
<     Enum.map board, fn row, y ->
<       Enum.map row, fn _, x ->

---
>     Enum.map Enum.with_index(board), fn { row, y } ->
>       Enum.map Enum.with_index(row), fn { _, x } ->
45c45
<   def next_state(".", _) do: "."

---
>   def next_state(".", _), do: "."
57c57
<     Enum.count(neighbors(board, x, y), &1 === "o")

---
>     Enum.count(neighbors(board, x, y), &(&1 === "o"))

Forked here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment