diff options
author | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-02-22 13:01:06 +0100 |
---|---|---|
committer | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-02-22 13:01:06 +0100 |
commit | e83a0b8b0c71dbbce6b3cdb87c77b2740b9f79f8 (patch) | |
tree | 06225c03aacf6d5b0c813dfaa3efc961e917bfde /aoc-2020-gleam/src/days | |
parent | 6eaf758850feebd8cfc97c3ead2de2625465a326 (diff) | |
download | gleam_aoc2020-e83a0b8b0c71dbbce6b3cdb87c77b2740b9f79f8.tar.gz gleam_aoc2020-e83a0b8b0c71dbbce6b3cdb87c77b2740b9f79f8.zip |
Finish first part of day 7
Diffstat (limited to 'aoc-2020-gleam/src/days')
-rw-r--r-- | aoc-2020-gleam/src/days/day07.gleam | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/aoc-2020-gleam/src/days/day07.gleam b/aoc-2020-gleam/src/days/day07.gleam new file mode 100644 index 0000000..eee817f --- /dev/null +++ b/aoc-2020-gleam/src/days/day07.gleam @@ -0,0 +1,80 @@ +import gleam/io +import gleam/list +import gleam/function as fun +import gleam/pair +import gleam/iterator as iter +import gleam/map.{Map} +import ext/resultx as resx +import ext/iteratorx as iterx +import util/graph +import util/input_util +import util/parser as p + +const special_bag = "shiny gold" + +type BagEdge = + #(String, Int) + +type BagGraph = + Map(String, List(BagEdge)) + +fn parse_graph(lines: List(String)) -> BagGraph { + let bag_type_parser = + [p.str1_until_ws(), p.ws_gc(), p.str1_until_ws()] + |> p.str_of_seq + |> p.labeled(with: "bag_type") + + let line_parser = + bag_type_parser + |> p.then_skip(p.literal(" bags contain ")) + |> p.then(p.or( + p.int() + |> p.then_skip(p.ws_gc()) + |> p.then(bag_type_parser) + |> p.map(with: pair.swap) + |> p.then_skip(p.ws_gc()) + |> p.then_skip(p.then(p.literal("bag"), p.opt(p.literal("s")))) + |> p.sep1(by: p.literal(", ")), + else: p.literal("no other bags") + |> p.map(fun.constant([])), + )) + |> p.then_skip(p.literal(".")) + + lines + |> list.map(with: fun.compose( + p.parse_entire(_, with: line_parser), + resx.force_unwrap, + )) + |> map.from_list +} + +fn part1(lines: List(String)) -> Int { + let graph = parse_graph(lines) + let neighbours = fn(bag) { + graph + |> map.get(bag) + |> resx.force_unwrap + |> list.map(with: pair.first) + |> iter.from_list + } + + graph + |> map.keys + |> iter.from_list + |> iter.filter(for: fn(bag) { bag != special_bag }) + |> iterx.count(satisfying: fn(start) { + start + |> graph.dfs(with: neighbours) + |> iter.any(fn(bag) { bag == special_bag }) + }) +} + +pub fn run() -> Nil { + let test = input_util.read_lines("test07") + assert 4 = part1(test) + + let input = input_util.read_lines("day07") + io.debug(part1(input)) + + Nil +} |