Created
December 22, 2020 16:42
-
-
Save stevensonmt/348e60393b0195369137da5237e99e59 to your computer and use it in GitHub Desktop.
flawed Advent of Code 2020 day 14 part 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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