Aetherus
Advent of Code 2020 - Day 7
This topic is about Day 7 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
I become busy this week, so I may not be able to create such topics in time. Apologies in advance.
Most Liked
code-shoily
I used :digraph for the first one
still doing the second one (the way I found ended up counting leaves), your solution does give me a little hint
so thank you.
2
kwando
I tried a too clever solution first… but I rolled back to this one… took some tries to get right, so it is not that polished yet 
defmodule Aoc2020.Day07 do
def part1(input) do
rules =
input
|> Enum.into(%{})
for {color, specs} <- rules, color != "shiny gold", reduce: 0 do
sum ->
if find(rules, specs, "shiny gold") do
sum + 1
else
sum
end
end
end
def part2(input) do
rules =
input
|> Enum.into(%{})
count_bags(rules, "shiny gold") - 1
end
def find(rules, [], _), do: false
def find(rules, [{_, color} | rest], color), do: true
def find(rules, [{_, child_color} | rest], color),
do: find(rules, rest, color) || find(rules, Map.get(rules, child_color, []), color)
def count_bags(rules, color) do
specs = Map.get(rules, color, [])
for {quantity, color} <- specs, reduce: 1 do
sum ->
sum + quantity * count_bags(rules, color)
end
end
def input_stream(path) do
File.stream!(path)
|> Stream.map(&parse/1)
end
def parse(line) do
line
|> String.replace(["bags", "contain", "bag"], "")
|> String.replace(~r/\s+|\./, " ")
|> String.trim()
|> String.split(",")
|> Enum.map(fn part -> String.trim(part) |> String.split(" ") end)
|> create_rule()
end
def create_rule([[mod, color | rule] | rules]) do
{"#{mod} #{color}", parse_spec([rule | rules])}
end
defp parse_spec([["no", "other"]]), do: []
defp parse_spec([]), do: []
defp parse_spec([[quantity, mod, color] | rest]) do
[{String.to_integer(quantity), "#{mod} #{color}"} | parse_spec(rest)]
end
end
input = Aoc2020.Day07.input_stream("input.txt")
Aoc2020.Day07.part1(input)
|> IO.inspect(label: "part1")
Aoc2020.Day07.part2(input)
|> IO.inspect(label: "part2")
1
LostKobrakai
Same here. But now it’s working:
1
code-shoily
Finally done with number 2. Here’s how I did it. Used :digraph for the first one.
1
faried
They get uglier every day!
defmodule Day07.Fns do
# revmap: map a bag to the list of bags that contain it
def revmap(_container, [], bagmap), do: bagmap
def revmap(container, [bag | bags], bagmap) do
bag = String.replace(bag, ".", "")
# ugly
bagmap = Map.update(bagmap, bag, [container], fn cur -> [container | cur] end)
revmap(container, bags, bagmap)
end
# map a bag to a map of bags it contains, and how many
# %{"wavy lavender" => %{"light magenta" => 1, "striped cyan" => 2}}
def nummap(_container, [], bagmap), do: bagmap
def nummap(container, [bag | bags], bagmap) do
bag = String.replace(bag, ".", "")
[count, containedbag] =
Regex.scan(~r/(\d+)\s(.*)/, bag, capture: :all_but_first)
|> hd()
# ugly
bagmap =
Map.update(bagmap, container, %{containedbag => String.to_integer(count)}, fn cur ->
Map.put(cur, containedbag, String.to_integer(count))
end)
nummap(container, bags, bagmap)
end
def cancontain(_bagmap, [], mapset), do: Enum.count(mapset)
def cancontain(bagmap, [bag | bags], mapset) do
containers =
Map.get(bagmap, bag, [])
|> Enum.reject(fn nextbag -> nextbag == bag or nextbag in mapset end)
newmapset =
containers
|> MapSet.new()
|> MapSet.union(mapset)
cancontain(bagmap, bags ++ containers, newmapset)
end
def totalbags(bagmap, bag) do
contains = Map.get(bagmap, bag, %{})
# ugly, not tail-recursive
if contains == %{} do
0
else
immediate =
Map.values(contains)
|> Enum.sum()
inside =
Enum.map(contains, fn {ibag, icount} -> icount * totalbags(bagmap, ibag) end)
|> Enum.sum()
immediate + inside
end
end
end
defmodule Day07 do
alias Day07.Fns
def readinput() do
File.read!("7.input.txt")
|> String.replace(~r/ bag(s)?/, "")
|> String.replace(", ", ".")
|> String.split("\n", trim: true)
|> Enum.reject(fn s -> String.contains?(s, "no other") end)
end
def part1(input \\ readinput()) do
input
|> Enum.map(&String.replace(&1, ~r/(\d+) /, ""))
|> Enum.map(&String.split(&1, " contain "))
|> Enum.map(fn [container, contains] ->
[container, String.split(contains, ".", trim: true)]
end)
|> Enum.reduce(%{}, fn [container | [contains | _]], acc ->
Fns.revmap(container, contains, acc)
end)
|> Fns.cancontain(["shiny gold"], MapSet.new())
end
def part2(input \\ readinput()) do
input
|> Enum.map(&String.split(&1, " contain "))
|> Enum.map(fn [container, contains] ->
[container, String.split(contains, ".", trim: true)]
end)
|> Enum.reduce(%{}, fn [container | [contains | _]], acc ->
Fns.nummap(container, contains, acc)
end)
|> Fns.totalbags("shiny gold")
end
end
1
Popular in Challenges
Everything went smoothly today.
Nothing to change to solve part 2 because I already used memoization for part 1 (it looked like an AoC e...
New
Note by the Moderators: This topic is to talk about the first day of the Advent of Code.
For general discussion about the Advent of Code...
New
This was way too easy after the last few days. Simple map, filter and count.
New
Ok, that was a rough one today.
I haven’t found a way to improve the algorithm further. Part 1 runs in .5 seconds, Part 2 in ~ 5 minutes...
New
Note by the Moderators: This topic is to talk about the Day 2 of the Advent of Code.
For general discussion about the Advent of Code 201...
New
Note: This topic is to talk about Day 2 of the Advent of Code 2019 .
There is a private leaderboard for elixirforum members. You can joi...
New
The second part of today’s puzzle is very misleading.
FYI, each of the ghosts has only one possible position that ends with a "Z" on its...
New
This topic is about Day 7 of the Advent of Code 2020 .
Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/le...
New
Just did part 1. Part 2 seems to be demanding too much of my reading time so will get to that after I am done with some chores.
Oh here ...
New
This topic is about Day 2 of the Advent of Code 2020.
New
Other popular topics
Update:
How to use the Blogs & Podcasts section
You can post links to your blog posts or podcasts either in one of the Official Blog...
New
What is the proper way to load a module from a file in to IEX?
In the python world, doing something like this pretty standard:
from ....
New
Good day to you all.
I have been struggling to get a query involving like and ilike to work.
Can anyone assist me on this, please?
pro...
New
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this
"1000"
What is the ...
New
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
I will often find my self writing things similar to:
case some_value do
nil -> something()
"" -> something()
_ -> someth...
New
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New







