Skip to content

Instantly share code, notes, and snippets.

@dehowell
Last active July 13, 2016 09:33
Show Gist options
  • Save dehowell/b311759a5dba5dea644fa519735828b7 to your computer and use it in GitHub Desktop.
Save dehowell/b311759a5dba5dea644fa519735828b7 to your computer and use it in GitHub Desktop.
One-Dimensional Cellular Automaton in Elixir
defmodule CellularAutomata do
@initial [0, 1, 0]
def run(generations, rule_number) do
rule_fn = rule(rule_number)
width = generations * 2 + 1
Stream.iterate(@initial, &(step(&1, rule_fn)))
|> Enum.take(generations)
|> Enum.map(&(center_pad(&1, width, 0)))
|> Enum.each(&print/1)
end
# Generate a rule function
def rule(n) do
digits = to_binary(n, 8)
rules = Enum.to_list(7..0)
|> Enum.map(&(to_binary(&1, 3)))
map = Enum.zip(rules, digits)
|> Map.new
fn ns -> map[ns] end
end
# Advance the cellular automata one generation.
#
# The edges will be padded with zeroes to account for the boundary conditions.
defp step(field, rule) do
Enum.chunk([0, 0] ++ field ++ [0, 0], 3, 1) |> Enum.map(rule)
end
# Convert an integer into a list of binary digits, left-padded with zeroes.
defp to_binary(n, size), do: Integer.digits(n, 2) |> left_pad(size, 0)
defp left_pad(list, n, value) when length(list) < n do
left_pad([value | list], n, value)
end
defp left_pad(list, _, _), do: list
# This is gross.
defp center_pad(list, width, value) when length(list) < width do
center_pad([value|list] ++ [value], width, value)
end
defp center_pad(list, _, _), do: list
defp print([0|tail]) do
IO.write(" ")
print(tail)
end
defp print([1|tail]) do
IO.write("X")
print(tail)
end
defp print([]), do: IO.puts("")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment