import IEx.Helpers
Mix.install([
{:kino, "~> 0.12.2"}
])
board = MapSet.new([{3, 2}, {3, 3}, {3, 4}])
- if a cell has less than 2 neighbors, it dies of loneliness
- if a cell has 2 neighbors, it stays the same
- if a cell has exactly 3 neighbors, it springs to life
- if a cell has more than 3 neighbors, it dies of overcrowding
MapSet.member?(board, {3, 5})
defmodule Board do
@width 100
@height 50
def new do
for r <- 1..@height, c <- 1..@width do
{r, c}
end
|> Enum.shuffle()
|> Enum.take(round(@width * @height / 2))
|> MapSet.new()
end
def next(board) do
for r <- 1..@height,
c <- 1..@width,
Cell.next_cell(board, {r, c}),
into: MapSet.new([]) do
{r, c}
end
end
def show(board) do
for row <- 1..@height, do: [show_row(board, row), "\n"]
end
defp show_row(board, row) do
for col <- 1..@width do
show_point(board, {row, col})
end
end
defp show_point(board, point) do
if MapSet.member?(board, point) do
"🤪"
else
"💀"
end
end
end
defmodule Cell do
def neighbors(board, {r, c} = point) do
for x <- (r - 1)..(r + 1), y <- (c - 1)..(c + 1), {x, y} != point, reduce: 0 do
neighbors ->
if live?(board, {x, y}),
do: neighbors + 1,
else: neighbors
end
end
def next_cell(board, point) do
count = neighbors(board, point)
cond do
count < 2 -> false
count == 2 -> live?(board, point)
count == 3 -> true
count > 3 -> false
end
end
def live?(board, point), do: MapSet.member?(board, point)
end
defmodule Runner do
def loop(board) do
board =
Board.next(board)
board |> Board.show() |> IO.puts()
Process.sleep(200)
loop(board)
end
end
Board.new() |> Board.next() |> Board.next() |> Board.next() |> Board.show() |> IO.puts()
Cell.neighbors(board, {1, 1})
Cell.next_cell(board, {3, 3})