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
67
68
|
import gleam/io
import gleam/int
import gleam/list
import gleam/pair
import gleam/result as res
import gleam/iterator as iter
import ext/listx
import ext/iteratorx as iterx
import ext/resultx as resx
import util/input_util
fn satisfies_two_sum(numbers: List(Int), sum: Int) -> Bool {
numbers
|> list.combination_pairs
|> list.filter(fn(two) { pair.first(two) != pair.second(two) })
|> list.any(satisfying: fn(two) { pair.first(two) + pair.second(two) == sum })
}
fn part1(numbers: List(Int), preamble_length: Int) -> Int {
numbers
|> list.window(by: preamble_length + 1)
|> iter.from_list
|> iter.drop_while(satisfying: fn(window) {
let assert [sum, ..numbers] = list.reverse(window)
satisfies_two_sum(numbers, sum)
})
|> iter.first
|> resx.assert_unwrap
|> list.last
|> resx.assert_unwrap
}
fn part2(numbers: List(Int), preamble_length: Int) -> Int {
let sum = part1(numbers, preamble_length)
numbers
|> iter.from_list
|> iter.index
|> iterx.filter_map(with: fn(step) {
let #(_, index) = step
let sublist = list.drop(from: numbers, up_to: index)
sublist
|> list.scan(from: 0, with: int.add)
|> list.drop(up_to: 1)
|> list.take_while(satisfying: fn(s) { s <= sum })
|> listx.index_of(sum)
|> res.map(with: fn(offset) { list.take(from: sublist, up_to: offset + 2) })
})
|> iter.first
|> resx.assert_unwrap
|> fn(set) {
let assert Ok(min) = list.reduce(set, with: int.min)
let assert Ok(max) = list.reduce(set, with: int.max)
min + max
}
}
pub fn main() -> Nil {
let testing = input_util.read_numbers("test09")
let assert 127 = part1(testing, 5)
let assert 62 = part2(testing, 5)
let input = input_util.read_numbers("day09")
io.debug(part1(input, 25))
io.debug(part2(input, 25))
Nil
}
|