Skip to content

Instantly share code, notes, and snippets.

@stevensonmt
Created December 22, 2020 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevensonmt/348e60393b0195369137da5237e99e59 to your computer and use it in GitHub Desktop.
Save stevensonmt/348e60393b0195369137da5237e99e59 to your computer and use it in GitHub Desktop.
flawed Advent of Code 2020 day 14 part 2
defmodule Day14 do
use Bitwise
@moduledoc false
@input File.read!("lib/input")
def process(version \\ 1) do
@input
|> String.split("mask = ", trim: true)
|> Enum.map(fn line -> process_line(line, version) end)
end
def process_line(line, version) do
line
|> String.split("\n", trim: true)
|> Enum.with_index()
|> Enum.reduce({[]}, fn {sub, ndx}, acc ->
case ndx do
0 ->
sub
|> process_mask(version)
|> process_helper(0, acc)
_ ->
sub
|> process_mem_assign(version)
|> process_helper(acc)
end
end)
end
def process_mask(mask, 2) do
one_mask = mask |> String.replace("X", "0")
xs =
mask
|> String.codepoints()
|> Enum.with_index()
|> Enum.filter(&Kernel.==(elem(&1, 0), "X"))
|> Enum.map(&elem(&1, 1))
{one_mask, xs}
end
def process_mem_assign(sub, _version) do
Regex.scan(~r/(?<=mem\[)\d+|(?<=]\s=\s)\d+/, sub)
|> List.flatten()
|> Enum.with_index()
|> Enum.map(fn {match, _ndx} -> String.to_integer(match) end)
|> List.to_tuple()
end
def process_helper(matches, 0, acc) do
Tuple.insert_at(acc, 0, matches)
end
def process_helper(matches, {mask, assignments}) do
{mask, [matches | assignments]}
end
def initialize(version \\ 1) do
process(version)
|> build_mem_map(version)
end
def build_mem_map(processed_lines, version \\ 1) do
processed_lines
|> Enum.reduce(%{}, fn {mask, assignments}, memory ->
assign_memory(mask, assignments, memory, version)
end)
end
def assign_memory(masks, assignments, memory, 2 = version) do
assignments
|> Enum.map(&apply_mask(&1, masks, version))
|> Enum.reduce(memory, fn {addresses, val}, acc ->
update_memory({addresses, val}, acc, version)
end)
end
def apply_mask({address, value}, {one_mask, xs}, 2) do
len = one_mask |> String.length()
one_masked = (address ||| String.to_integer(one_mask, 2)) |> Integer.digits(2)
{flip_bits(
[
1..(len - length(one_masked))
|> Enum.reduce(one_masked, fn _, acc -> [0 | acc] end)
],
xs
), value}
end
def flip_bits(acc, []) do
acc
end
def flip_bits(acc, [x | rest]) do
acc
|> Enum.flat_map(fn digits ->
[List.update_at(digits, x, fn _ -> 1 end), List.update_at(digits, x, fn _ -> 0 end)]
end)
|> flip_bits(rest)
end
def update_memory({addresses, val}, memory, 2) do
addresses
|> Enum.reduce(memory, fn address, acc ->
Map.put(acc, Integer.undigits(address, 2), val)
end)
end
def run2 do
initialize(2)
|> sum_memory()
|> IO.puts()
end
def sum_memory(mem_map) do
mem_map
|> Map.values()
|> Enum.sum()
end
end
Day14.run2()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment