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
|
import gleam/io
import gleam/int
import gleam/list
import gleam/map
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(index, number) { #(number, index + 1) })
|> map.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
#(
map.insert(into: history, for: last, insert: turn),
turn + 1,
case map.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
}
|