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])
Last Post!
stevensonmt
FINALLY GOT IT
defmodule Day14Part2Only do
use Bitwise
@moduledoc false
@input File.read!("lib/input")
defmodule MyParser do
import NimbleParsec
mask =
ignore(string("mask = "))
|> ascii_string([?1, ?0, ?X], 36)
|> ignore(string("\n"))
mem =
ignore(string("mem["))
|> integer(min: 1)
|> ignore(string("] = "))
|> integer(min: 1)
|> ignore(string("\n"))
|> reduce({List, :to_tuple, []})
group =
mask
|> repeat(mem)
|> reduce({List, :wrap, []})
defparsec(:nimble_parse, repeat(group))
end
def nimble_parse do
MyParser.nimble_parse(@input)
|> elem(1)
|> Enum.map(fn [mask | assignments] -> {mask, assignments} end)
end
def initialize(version \\ 1) do
nimble_parse()
|> 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(mask, assignments, memory, 2 = version) do
assignments
|> Enum.map(&apply_mask(&1, mask, version))
|> Enum.reduce(memory, fn {addresses, val}, acc ->
update_memory({addresses, val}, acc, version)
end)
end
def apply_mask({address, value}, mask, 2) do
{address
|> Integer.to_string(2)
|> String.pad_leading(36, "0")
|> String.codepoints()
|> Enum.zip(String.codepoints(mask))
|> Enum.reduce([0], fn {a, b}, acc ->
case b do
"0" -> Enum.map(acc, fn addr -> addr * 2 + String.to_integer(a) end)
"1" -> Enum.map(acc, fn addr -> addr * 2 + 1 end)
"X" -> fork(acc)
end
end), value}
end
def fork(acc) do
acc
|> Enum.flat_map(fn addr -> [addr * 2, addr * 2 + 1] end)
end
def update_memory({addresses, val}, memory, 2) do
addresses
|> Enum.reduce(memory, fn address, acc ->
Map.put(acc, address, 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
Day14Part2Only.run2()
I’ve done a half dozen approaches to the branching/flat mapping portion of applying the mask, but in the end there was something squirrelly about how I was processing the input. Once I broke down and used Nimble Parsec it just worked. UGGGGH.
Popular in Challenges
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









