aboutsummaryrefslogtreecommitdiff
path: root/aoc-2020-gleam/src/days/day15.gleam
blob: 83f2bb822f192bd112815a7b6797c6fdcbd3482d (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
import gleam/io
import gleam/int
import gleam/list
import gleam/dict
import gleam/string as str
import gleam/function as fun
import gleam/iterator as iter
import ext/resultx as resx
import ext/iteratorx as iterx

fn solve(input: String, nth: Int) -> Int {
  let starting =
    input
    |> str.split(on: ",")
    |> list.map(with: fun.compose(int.parse, resx.assert_unwrap))

  let history =
    starting
    |> list.index_map(fn(number, index) { #(number, index + 1) })
    |> dict.from_list
  let turn = list.length(starting)
  let assert Ok(last) = list.last(starting)

  iterx.unfold_infinitely(from: #(history, turn, last), with: fn(state) {
    let #(history, turn, last) = state
    #(
      dict.insert(into: history, for: last, insert: turn),
      turn
      + 1,
      case dict.get(history, last) {
        Ok(previous) -> turn - previous
        Error(Nil) -> 0
      },
    )
  })
  |> iter.filter(fn(state) { state.1 == nth })
  |> iter.map(fn(state) { state.2 })
  |> iter.first
  |> resx.assert_unwrap
}

fn part1(input: String) -> Int {
  solve(input, 2020)
}

fn part2(input: String) -> Int {
  solve(input, 30_000_000)
}

pub fn main() -> Nil {
  let assert 436 = part1("0,3,6")
  let assert 1 = part1("1,3,2")
  let assert 27 = part1("1,2,3")
  let assert 78 = part1("2,3,1")
  let assert 438 = part1("3,2,1")
  let assert 1836 = part1("3,1,2")

  let input = "12,20,0,6,1,17,7"
  io.debug(part1(input))
  io.debug(part2(input))

  Nil
}