Skip to content

Instantly share code, notes, and snippets.

@batate
Created January 19, 2024 00:28
Show Gist options
  • Save batate/a45e9224733b620bb2d84baa6a74749f to your computer and use it in GitHub Desktop.
Save batate/a45e9224733b620bb2d84baa6a74749f to your computer and use it in GitHub Desktop.
Life Lifebook

Conway's Game of Life

import IEx.Helpers

Mix.install([
  {:kino, "~> 0.12.2"}
])

Section

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
board = Board.new()
defmodule Runner do
  def loop(board) do
    board =
      Board.next(board)

    board |> Board.show() |> IO.puts()
    Process.sleep(200)
    loop(board)
  end
end
Runner.loop(Board.new())
Board.new() |> Board.next() |> Board.next() |> Board.next() |> Board.show() |> IO.puts()
Cell.neighbors(board, {1, 1})
Cell.next_cell(board, {3, 3})
Board.next(board)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment