Created
December 21, 2020 16:31
-
-
Save ynonp/5e79f8986804a29b8680870ce166aba5 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 Day21 do | |
def read_input do | |
File.read!("input/day21.txt") | |
|> String.split("\n", trim: true) | |
end | |
def ingredients_list(line) do | |
[ingredients_str, _alergens_str] = String.split(line, [" (contains ", ")"], trim: true) | |
String.split(ingredients_str, " ", trim: true) | |
end | |
# Input line: mxmxvkd kfcds sqjhc nhms (contains dairy, fish) | |
# Output map: %{ | |
# dairy: [mxmxvkd, kfcds, sqjhc, nhms] | |
# fish: [mxmxvkd, kfcds, sqjhc, nhms] | |
# } | |
def parse_product(line) do | |
[ingredients_str, alergens_str] = String.split(line, [" (contains ", ")"], trim: true) | |
alergens = String.split(alergens_str, ", ", trim: true) | |
ingredients = String.split(ingredients_str, " ", trim: true) | |
for a <- alergens do | |
%{ a => [MapSet.new(ingredients)] } | |
end | |
|> Enum.reduce(&Map.merge/2) | |
end | |
def parse_product_inverse(line) do | |
[ingredients_str, alergens_str] = String.split(line, [" (contains ", ")"], trim: true) | |
alergens = String.split(alergens_str, ", ", trim: true) | |
ingredients = String.split(ingredients_str, " ", trim: true) | |
for i <- ingredients do | |
%{ i => alergens } | |
end | |
|> Enum.reduce(&Map.merge/2) | |
end | |
def maybe_dict(input) do | |
input | |
|> Enum.map(&parse_product_inverse/1) | |
|> Enum.reduce(fn | |
val, acc -> Map.merge(val, acc, fn _k, v1, v2 -> | |
v1 ++ v2 | |
end) | |
end) | |
end | |
def not_dict(input) do | |
input | |
|> Enum.map(&parse_product/1) | |
|> Enum.reduce(fn | |
val, acc -> Map.merge(val, acc, fn _k, v1, v2 -> | |
v1 ++ v2 | |
end) | |
end) | |
|> Enum.map(fn { k, v } -> | |
# v is a list of MapSet | |
# k is the name of the alerge | |
{ | |
k, | |
MapSet.difference( | |
Enum.reduce(v, &MapSet.union/2), | |
Enum.reduce(v, &MapSet.intersection/2) | |
) | |
} | |
end) | |
|> Enum.into(%{}) | |
end | |
def clear_maybe_dict(maybe_dict) do | |
singles = maybe_dict | |
|> Enum.filter(fn {k, v} -> Enum.count(v) == 1 end) | |
|> Enum.map(fn {_k, v} -> v end) | |
|> Enum.reduce(&MapSet.union/2) | |
IO.inspect(singles) | |
maybe_dict | |
|> Enum.map(fn { k, v } -> | |
{ | |
k, | |
if Enum.count(v) <= 1 do | |
v | |
else | |
MapSet.difference(v, singles) | |
end | |
} | |
end) | |
|> Enum.into(%{}) | |
end | |
def certainly_dict(maybe_dict, whatnot_dict) do | |
canstop = maybe_dict | |
|> Map.values | |
|> Enum.all?(fn v -> Enum.count(v) <= 1 end) | |
if canstop do | |
maybe_dict | |
else | |
maybe_dict | |
|> Enum.map(fn { k, v } -> | |
{ | |
k, | |
Enum.reject(v, fn alergen -> | |
MapSet.member?(Map.get(whatnot_dict, alergen), k) | |
end) | |
|> Enum.into(MapSet.new) | |
} | |
end) | |
|> Enum.into(%{}) | |
|> clear_maybe_dict() | |
|> IO.inspect | |
|> certainly_dict(whatnot_dict) | |
end | |
end | |
def count_occurences(input, stuff) do | |
input | |
|> Enum.map(&ingredients_list/1) | |
|> Enum.map(fn list -> Enum.count(list, fn i -> MapSet.member?(stuff, i) end) end) | |
|> Enum.sum | |
|> IO.inspect | |
end | |
def part1 do | |
input = read_input() | |
whatnot = not_dict(input) | |
|> IO.inspect | |
IO.inspect(maybe_dict(input)) | |
required_ingredients = maybe_dict(input) | |
|> Enum.filter(fn {k, v} -> | |
Enum.all?(v, &(MapSet.member?(Map.get(whatnot, &1), k))) | |
end) | |
|> Enum.map(&Kernel.elem(&1, 0)) | |
|> Enum.into(MapSet.new) | |
|> IO.inspect | |
count_occurences(input, required_ingredients) | |
found_it = certainly_dict(maybe_dict(input), whatnot) | |
found_it | |
|> Enum.filter(fn { k, v } -> Enum.count(v) > 0 end) | |
|> Enum.map(fn {k, v} -> {k, Enum.at(v, 0)} end) | |
|> Enum.sort_by(fn {k, v} -> v end) | |
|> Enum.map(fn {k, v} -> k end) | |
|> Enum.join(",") | |
|> IO.inspect | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment