Last active
August 29, 2015 14:09
-
-
Save rob-brown/6969b31f0417dcd17ed1 to your computer and use it in GitHub Desktop.
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
defmodule Life do | |
# Defaults to B3/S23 | |
defstruct cells: [[]], born: [3], stays: [2, 3], width: 10, height: 10, step: 0 | |
def run(file) do | |
file |> read_file |> loop | |
end | |
def loop(life) do | |
life |> print |> wait |> step |> loop | |
end | |
## Helpers | |
defp read_file(file) do | |
lines = File.stream! file | |
height = Enum.count lines | |
width = lines |> Enum.max_by(&String.length/1) |> String.length | |
cells = Enum.map lines, &(parse_line &1, width) | |
%Life{cells: cells, width: width, height: height} | |
end | |
defp parse_line(line, width) do | |
for x <- 1..width do | |
case String.at(line, x - 1) do | |
"#" -> 1 | |
" " -> 0 | |
_ -> 0 | |
end | |
end | |
end | |
defp wait(life) do | |
:timer.sleep 250 | |
life | |
end | |
defp step(life) do | |
cells = for row <- 1..life.height do | |
for column <- 1..life.width do | |
next_value life, row - 1, column - 1 | |
end | |
end | |
%Life{life | cells: cells, step: life.step + 1} | |
end | |
defp next_value(life, row, column) do | |
cell = at(life, row, column) | |
count = count_adjacent_life life, row, column | |
_next_value life, cell, count | |
end | |
defp _next_value(life, 0, count), do: count in life.born && 1 || 0 | |
defp _next_value(life, 1, count), do: count in life.stays && 1 || 0 | |
defp count_adjacent_life(life, row, column) do | |
for x <- [-1, 0, 1], y <- [-1, 0, 1], {x,y} != {0,0} do | |
at(life, row + x, column + y) | |
end | |
|> Enum.sum | |
end | |
defp at(life, row, column) when row < 0 or column < 0, do: 0 | |
defp at(life, row, column), do: ((life.cells |> Enum.at(row) || []) |> Enum.at(column) || 0) | |
defp print(life) do | |
divider = for _ <- 1..life.width + 2, into: "", do: "=" | |
IO.puts "#{divider} (#{life.step})" | |
for line <- life.cells do | |
for cell <- line, into: "" do | |
case cell do | |
1 -> "#" | |
0 -> " " | |
end | |
end | |
|> IO.puts | |
end | |
life | |
end | |
end |
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
# # | |
# # | |
## ## | |
### ## ## ### | |
# # # # # # | |
## ## | |
## ## | |
# # # # # # | |
### ## ## ### | |
## ## | |
# # | |
# # | |
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
### | |
### | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment