1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
import gleam/dict
import gleam/list
import gleam/set.{type Set}
import gleam/string
type Pipes =
dict.Dict(String, List(String))
pub fn parse(input: String) -> Pipes {
use acc, row <- list.fold(string.split(input, "\n"), dict.new())
let assert Ok(#(from, to)) = string.split_once(row, " <-> ")
let to_nodes = string.split(to, ", ")
dict.insert(acc, from, to_nodes)
}
pub fn pt_1(input: Pipes) {
next_nodes("0", input, set.new()) |> set.size()
}
pub fn pt_2(input: Pipes) {
count_groups(dict.keys(input), input, 0)
}
fn next_nodes(current: String, pipes: Pipes, found: Set(String)) {
let assert Ok(to_nodes) = dict.get(pipes, current)
use acc, node <- list.fold(to_nodes, found)
case set.contains(found, node) {
False -> acc |> set.insert(node) |> next_nodes(node, pipes, _)
True -> acc
}
}
fn count_groups(all_nodes: List(String), pipes: Pipes, count: Int) {
case all_nodes {
[] -> count
[first, ..] -> {
let next_subgraph = next_nodes(first, pipes, set.new())
let remaining =
list.filter(all_nodes, fn(n) { !set.contains(next_subgraph, n) })
count_groups(remaining, pipes, count + 1)
}
}
}
|