bjorng
Advent of Code 2020 - Day 14
This topic is about Day 14 of the Advent of Code 2020 .
Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/leaderboard/private/view/39276
The join code is:
39276-eeb74f9a
Most Liked
bjorng
Hello, everyone. I’m back. This year I didn’t want to do every AOC puzzle the minute it was posted every day for 25 straight days as I did the last two years. Two weeks in I realized that I missed this yearly opportunity to learn some more Elixir, so I will drop in here now and then, probably doing some of the puzzles out of order.
Today’s puzzle was a fun one. Here is my solution.
Aetherus
Today I reinstalled the operating system on my laptop, and I just finished recovering my GitHub account, so it’s a bit late to post my solutions to today’s quizzes.
I didn’t use bitwise operations, either, because I couldn’t find a neat one. I hope to see some smart solutions.
Anyway, here’s my solution:
Part 1
#!/usr/bin/env elixir
initial_state = %{
mem: %{},
mask: ""
}
parse_mem_set = fn line ->
[address, value] = Regex.run(~r/^mem\[(\d+)\] = (\d+)$/, line, capture: :all_but_first)
{address, value}
end
apply_mask = fn value, mask ->
value = value
|> String.to_integer()
|> Integer.to_string(2)
|> String.pad_leading(36, "0")
|> :binary.bin_to_list()
mask
|> :binary.bin_to_list()
|> Enum.zip(value)
|> Enum.map(fn
{?0, _} -> ?0
{?1, _} -> ?1
{?X, v} -> v
end)
|> List.to_integer(2)
end
"day14.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Enum.reduce(initial_state, fn
"mask = " <> mask, state -> %{state | mask: mask}
"mem" <> _ = line, state ->
{address, value} = parse_mem_set.(line)
masked_value = apply_mask.(value, state.mask)
put_in(state, [:mem, String.to_integer(address)], masked_value)
end)
|> Map.get(:mem)
|> Map.values()
|> Enum.sum()
|> IO.inspect()
Part 2
#!/usr/bin/env elixir
initial_state = %{
mem: %{},
mask: ""
}
parse_mem_set = fn line ->
[address, value] = Regex.run(~r/^mem\[(\d+)\] = (\d+)$/, line, capture: :all_but_first)
{address, value}
end
do_mask = fn zipped ->
# acc is a list of lists of codepoints.
zipped
|> Enum.reduce([[]], fn
{?0, v}, acc -> Enum.map(acc, &[v | &1])
{?1, _}, acc -> Enum.map(acc, &[?1 | &1])
{?X, _}, acc -> Enum.map(acc, &[?0 | &1]) ++ Enum.map(acc, &[?1 | &1])
end)
|> Enum.map(&Enum.reverse/1)
|> Enum.map(&List.to_integer(&1, 2))
end
apply_mask = fn address, mask ->
address = address
|> String.to_integer()
|> Integer.to_string(2)
|> String.pad_leading(36, "0")
|> :binary.bin_to_list()
mask
|> :binary.bin_to_list()
|> Enum.zip(address)
|> do_mask.()
end
"day14.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Enum.reduce(initial_state, fn
"mask = " <> mask, state -> %{state | mask: mask}
"mem" <> _ = line, state ->
{address, value} = parse_mem_set.(line)
masked_addresses = apply_mask.(address, state.mask)
for address <- masked_addresses, reduce: state do
st -> put_in(st, [:mem, address], String.to_integer(value))
end
end)
|> Map.get(:mem)
|> Map.values()
|> Enum.sum()
|> IO.inspect()
cblavier
Hi there 
Part1 was easy to me (used Bitwise operator), but I struggled with recursion for Part2 until I found out that I could manage without recursion 
My code here :
the bitwise part for anyone interested
def run_program_chunk({mask, instructions}, memory) do
{or_mask, _} = mask |> String.replace("X", "0") |> Integer.parse(2)
{and_mask, _} = mask |> String.replace("X", "1") |> Integer.parse(2)
Enum.reduce(instructions, memory, fn {address, value}, memory ->
Map.put(memory, address, (value ||| or_mask) &&& and_mask)
end)
end
EDIT : simplified my Part 2 code, to remove a lot of string manipulations
Part2 address generation
def find_addresses(address_and_mask) do
Enum.reduce(address_and_mask, [0], fn
{_, "X"}, acc -> fork(acc)
{_, "1"}, acc -> add_bit(acc, 1)
{"1", _}, acc -> add_bit(acc, 1)
_, acc -> add_bit(acc, 0)
end)
end
def add_bit(acc, bit), do: Enum.map(acc, &(&1 * 2 + bit))
def fork(acc), do: Enum.flat_map(acc, &[&1 * 2, &1 * 2 + 1])







