aboutsummaryrefslogtreecommitdiff
path: root/aoc-2020-gleam/src/days/day10.gleam
blob: 12f252e259a19dd3e65007d6ead3d13813d0fce4 (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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import gleam/io
import gleam/int
import gleam/list
import gleam/bool
import gleam/result as res
import ext/listx
import ext/pairx
import ext/genericx as genx
import util/input_util
import util/cache.{type Cache}

const outlet_joltage = 0

const max_increase = 3

fn process_adapters(numbers: List(Int)) -> List(Int) {
  let numbers = list.sort(numbers, by: int.compare)

  let assert Ok(device_joltage) =
    numbers
    |> list.last
    |> res.map(with: int.add(_, max_increase))

  list.flatten([[outlet_joltage], numbers, [device_joltage]])
}

fn part1(numbers: List(Int)) -> Int {
  let adapters = process_adapters(numbers)
  let diffs =
    adapters
    |> list.window_by_2
    |> list.map(with: pairx.difference)

  let ones = listx.count(diffs, satisfying: genx.equals(_, 1))
  let threes = listx.count(diffs, satisfying: genx.equals(_, 3))
  ones * threes
}

fn arrangements(number: Int, adapters: List(Int), cache: Cache(Int, Int)) -> Int {
  use <- bool.guard(when: number == 0, return: 1)
  use <- bool.guard(when: !list.contains(adapters, number), return: 0)
  use <- cache.memoize(with: cache, this: number)

  list.range(from: 1, to: max_increase)
  |> list.map(with: fn(j) { arrangements(number - j, adapters, cache) })
  |> int.sum
}

fn part2(numbers: List(Int)) -> Int {
  let adapters = process_adapters(numbers)
  let assert Ok(device_joltage) = list.last(adapters)
  use cache <- cache.create()
  arrangements(device_joltage, adapters, cache)
}

pub fn main() -> Nil {
  let testing = input_util.read_numbers("test10")
  let assert 220 = part1(testing)
  let assert 19_208 = part2(testing)

  let input = input_util.read_numbers("day10")
  io.debug(part1(input))
  io.debug(part2(input))

  Nil
}