lud

lud

Advent of Code 2020 - Day 21

This topic is about Day 21 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

blue_quartz

blue_quartz

After the slaughter that is day 20 (which I did solve, but with a sprawling 163 sloc solution :frowning:), this was a good detox, and I got to even reuse day 16’s logic a bit too…

I ‘accidentally’ created the relevant map for day 2 while solving for day 1, and the day 16 reuse is for the part where we have a map of values with increasing lengths, so we just need to sort by that and start picking out the correct value for the key.

defmodule AdventOfCode.Day21 do
  @moduledoc "Day 21"

  defmodule Food do
    defstruct ingredients: MapSet.new(), allergens: MapSet.new()
  end

  defp parse(food) do
    to_set = &(MapSet.new(String.split(&1, &2)))
    [_, ingredients, allergens] = Regex.run(~r/^(.*) \(contains (.*)\)$/, food)
    %Food{ingredients: to_set.(ingredients, " "), allergens: to_set.(allergens, ", ")}
  end

  defp process(input) do
    all_food = Enum.map(input, &parse/1)
    by_allergen = Map.new(
      Enum.reduce(all_food, MapSet.new(), &(MapSet.union(&1.allergens, &2))),
      fn allergen ->
        case Enum.filter(all_food, &(allergen in &1.allergens)) do
          [] -> {allergen, []}
          x -> {allergen, Enum.reduce(tl(x), hd(x).ingredients, &(MapSet.intersection(&1.ingredients, &2)))}
        end
      end
    )
    {all_food, by_allergen}
  end

  def part1(input) do
    {all_food, by_allergen} = process(input)
    bad = MapSet.new(Enum.flat_map(by_allergen, &(elem(&1, 1))))
    Enum.sum(Enum.map(all_food, fn food -> Enum.count(Enum.filter(food.ingredients, &(!(&1 in bad)))) end))
  end

  def part2(input) do
    {_, by_allergen} = process(input)
    Enum.reduce(
      Enum.sort_by(by_allergen, &(Enum.count(elem(&1, 1)))),
      Map.new(),
      fn {allergen, ingredients}, acc -> Map.put(acc, hd(MapSet.to_list(ingredients) -- Map.keys(acc)), allergen) end
    )
    |> Enum.sort_by(&(elem(&1, 1)))
    |> Enum.map(&(elem(&1, 0)))
    |> Enum.join(",")
  end
end
Papey

Papey

Yep, mine is a bit verbose maybe but it works so :man_shrugging:

Where Next?

Popular in Challenges Top

sasajuric
Note: This topic is to talk about Day 12 of the Advent of Code. For general discussion about the Advent of Code 2018 and links to topics...
New
kwando
Phew, this one took a while to get right. My naive attempts was way to slow so I reached for Dijkstras shortest path algorithm… and that ...
New
bjorng
This topic is about Day 18 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums): https://adve...
New
sasajuric
Note by the Moderators: This topic is to talk about Day 5 of the Advent of Code. For general discussion about the Advent of Code 2018 an...
New
shritesh
This was way too easy after the last few days. Simple map, filter and count.
New
Aetherus
Today’s challenge is quite interesting. I ended up using Zipper to solve this problem. Maybe I overengineered quite a bit. The data stru...
New
bjorng
Note: This topic is to talk about Day 1 of the Advent of Code 2019.
New
bjorng
My solution finishes both parts in 5 seconds on my computer. That time should be possible to reduce by optimizing my rather naive tilt/2 ...
New
rugyoga
Fairly straightforward Dijkstra’s algorithm import AOC aoc 2023, 17 do def compute(input, candidates) do {{max_row, max_col}, ite...
New
coen.bakker
Since I started using Elixir, I have benefited greatly from being able to study various open-source projects. The codebase of LiveBook, i...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
jerry
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
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
273 38985 115
New
lanycrost
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

We're in Beta

About us Mission Statement