Skip to content

Instantly share code, notes, and snippets.

@avdi
Last active June 3, 2016 04:30
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save avdi/5963465 to your computer and use it in GitHub Desktop.
Save avdi/5963465 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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
Copy link

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
Copy link

same here

@billgathen
Copy link

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