aboutsummaryrefslogtreecommitdiff
path: root/aoc2017-gleam/src/aoc_2017/day_12.gleam
blob: a9d73c52d1ef3b48ecf9f4cde65a0eafd51fd27e (plain)
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)
    }
  }
}