From 34d4dea789e77dadf11b9dbab27b0a68545e4df2 Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Wed, 16 Dec 2020 21:49:43 -0800 Subject: [PATCH] Day 17 Part 1 --- 2020/day17/day17.ex | 165 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 2020/day17/day17.ex diff --git a/2020/day17/day17.ex b/2020/day17/day17.ex new file mode 100644 index 0000000..b23f7f0 --- /dev/null +++ b/2020/day17/day17.ex @@ -0,0 +1,165 @@ +defmodule Day17 do + defp read_input do + Path.expand('input', Path.dirname(__ENV__.file)) + |> File.read!() + end + + defp test_input do + """ + .#. + ..# + ### + """ + end + + defp parse_space(text) do + String.split(text, "\n", trim: true) + |> Enum.with_index() + |> Enum.reduce(%{}, fn {line, y}, map -> + String.codepoints(line) + |> Enum.with_index() + |> Enum.reduce(map, fn {char, x}, map -> + Map.put(map, {x, y, 0}, char_to_content(char)) + end) + end) + end + + defp char_to_content(char) do + case char do + "." -> :inactive + "#" -> :active + end + end + + defp state_char(char) do + case char do + :inactive -> "." + :active -> "#" + end + end + + defp expand_range(lo..hi, val) do + cond do + val < lo -> val..hi + val > hi -> lo..val + true -> lo..hi + end + end + + defp get_bounds(space) do + Enum.reduce(space, %{x: 0..0, y: 0..0, z: 0..0}, fn {{x, y, z}, state}, bounds -> + case state do + :inactive -> + bounds + + :active -> + %{ + x: expand_range(bounds.x, x), + y: expand_range(bounds.y, y), + z: expand_range(bounds.z, z) + } + end + end) + end + + defp show(space) do + bounds = get_bounds(space) + + for z <- bounds.z do + IO.puts("z = #{z}") + + for y <- bounds.y do + for x <- bounds.x do + state = Map.get(space, {x, y, z}, :inactive) + IO.write(state_char(state)) + end + + IO.write("\n") + end + + IO.write("\n\n") + end + + space + end + + defp populate(space) do + Enum.reduce(space, %{}, fn {cell, state}, counts -> + if state == :inactive do + counts + else + neighbors(cell) + |> Enum.reduce(counts, fn neighbor, counts -> + Map.put(counts, neighbor, 1 + Map.get(counts, neighbor, 0)) + end) + end + end) + end + + defp tick(space) do + populate(space) + |> Enum.reduce(%{}, fn {cell, count}, new_space -> + new_state = + case Map.get(space, cell, :inactive) do + :active -> + if count == 2 or count == 3 do + :active + else + :inactive + end + + :inactive -> + if count == 3 do + :active + else + :inactive + end + end + + case new_state do + :active -> Map.put(new_space, cell, :active) + :inactive -> new_space + end + end) + end + + defp neighbors(cell = {x, y, z}) do + for dx <- -1..1, + dy <- -1..1, + dz <- -1..1 do + {x + dx, y + dy, z + dz} + end + |> Enum.reject(&(&1 == cell)) + end + + defp run(space, 0) do + space + end + + defp run(space, cycles) do + IO.puts("cycles = #{cycles}") + show(space) + + tick(space) + |> run(cycles - 1) + end + + def part1 do + read_input() + |> parse_space() + |> run(6) + |> show() + |> Enum.count(fn {_cell, state} -> state == :active end) + end + + def debug do + test_input() + |> parse_space() + |> tick() + + # neighbors(%{}, {0, 0, 0}) + end +end + +Day17.part1() |> IO.inspect() +# Day17.debug() |> IO.inspect()