Docking Data
defmodule Aoc2020.Day14 do
@moduledoc "Docking Data"
def run() do
parse_input()
|> run_program()
|> (fn {memory, _} -> Map.values(memory) end).()
|> Enum.filter(&(&1 != 0))
|> Enum.sum()
end
def parse_input() do
File.read!("priv/inputs/2020/day14.txt")
|> String.trim()
|> String.split("\n")
|> Enum.map(&String.split(&1, [" = ", "[", "]"]))
|> Enum.map(&parse_instruction/1)
end
def parse_instruction(["mask", mask]) do
{:update_mask, mask}
end
def parse_instruction(["mem", location, _, value]) do
{:update_memory, {String.to_integer(location), value}}
end
def run_program(instructions) do
Enum.reduce(
instructions,
{%{}, ""},
fn instruction, {memory, mask} ->
handle_instruction(instruction, memory, mask)
end
)
end
def handle_instruction({:update_mask, mask}, memory, _) do
{memory, :binary.bin_to_list(mask)}
end
def handle_instruction({:update_memory, {location, value}}, memory, mask) do
new_value = apply_mask(mask, value)
{Map.put(memory, location, new_value), mask}
end
def apply_mask(mask, value) do
input =
String.to_integer(value)
|> Integer.to_string(2)
|> String.pad_leading(36, "0")
|> :binary.bin_to_list()
Enum.zip(input, mask)
|> Enum.map(fn
{v, ?X} ->
v
{_, m} ->
m
end)
|> List.to_integer(2)
end
end