tangled
alpha
login
or
join now
regnault.dev
/
gleam-aoc-2025
1
fork
atom
this repo has no description
1
fork
atom
overview
issues
pulls
pipelines
Day 7
regnault.dev
3 months ago
4a9c8b93
a7081cb4
+166
2 changed files
expand all
collapse all
unified
split
src
aoc.gleam
days
day7.gleam
+2
src/aoc.gleam
···
6
6
import days/day4
7
7
import days/day5
8
8
import days/day6
9
9
+
import days/day7
9
10
import gleam/erlang
10
11
import gleam/int
11
12
import gleam/io
···
31
32
4 -> day4.start()
32
33
5 -> day5.start()
33
34
6 -> day6.start()
35
35
+
7 -> day7.start()
34
36
_ -> io.println("Tried to run day " <> int.to_string(day))
35
37
}
36
38
birl.now()
+164
src/days/day7.gleam
···
1
1
+
import gleam/dict
2
2
+
import gleam/float
3
3
+
import gleam/function
4
4
+
import gleam/int
5
5
+
import gleam/io
6
6
+
import gleam/list
7
7
+
import gleam/otp/task
8
8
+
import gleam/result
9
9
+
import gleam/set
10
10
+
import gleam/string
11
11
+
import simplifile
12
12
+
import utils/utils
13
13
+
14
14
+
type Type {
15
15
+
Tachion
16
16
+
Splitter
17
17
+
}
18
18
+
19
19
+
type Position {
20
20
+
Position(x: Int)
21
21
+
}
22
22
+
23
23
+
type Cell {
24
24
+
Cell(pos: Position, typ: Type)
25
25
+
}
26
26
+
27
27
+
pub fn start() -> Nil {
28
28
+
let assert Ok(content) = simplifile.read("inputs/day7.txt")
29
29
+
let data = parse(content)
30
30
+
31
31
+
let _ = io.debug(part1(data))
32
32
+
let _ = io.debug(part2(data))
33
33
+
34
34
+
Nil
35
35
+
}
36
36
+
37
37
+
fn parse(data: String) {
38
38
+
string.split(data, "\n")
39
39
+
|> list.index_map(fn(l, y) {
40
40
+
list.index_map(string.to_graphemes(l), fn(c, x) {
41
41
+
case c {
42
42
+
"S" -> Ok(Cell(Position(x), Tachion))
43
43
+
"^" -> Ok(Cell(Position(x), Splitter))
44
44
+
45
45
+
// Should never happen
46
46
+
_ -> Error(Nil)
47
47
+
}
48
48
+
})
49
49
+
|> list.filter_map(function.identity)
50
50
+
})
51
51
+
|> list.filter(fn(x) { !list.is_empty(x) })
52
52
+
}
53
53
+
54
54
+
type Res {
55
55
+
Res(splits: Int, tachions: List(Cell))
56
56
+
}
57
57
+
58
58
+
fn part1(data: List(List(Cell))) {
59
59
+
let res =
60
60
+
list.fold(data, Res(0, []), fn(acc, cells_on_line) {
61
61
+
let new_tachions =
62
62
+
list.map(cells_on_line, fn(c) {
63
63
+
case c.typ {
64
64
+
Tachion -> #([c], 0, [])
65
65
+
Splitter -> {
66
66
+
let Position(cx) = c.pos
67
67
+
case list.find(acc.tachions, fn(x) { x.pos.x == cx }) {
68
68
+
Ok(c) -> #(
69
69
+
[
70
70
+
Cell(Position(cx - 1), Tachion),
71
71
+
Cell(Position(cx + 1), Tachion),
72
72
+
],
73
73
+
1,
74
74
+
[c],
75
75
+
)
76
76
+
Error(_) -> #([], 0, [])
77
77
+
}
78
78
+
}
79
79
+
}
80
80
+
})
81
81
+
82
82
+
let used_tachions =
83
83
+
list.fold(new_tachions, [], fn(acc, x) { [x.2, ..acc] })
84
84
+
|> list.flatten
85
85
+
|> list.fold(set.new(), set.insert)
86
86
+
|> set.to_list
87
87
+
88
88
+
let new_splits =
89
89
+
acc.splits + list.fold(new_tachions, 0, fn(acc, t) { acc + t.1 })
90
90
+
91
91
+
let new_tachions =
92
92
+
list.map(new_tachions, fn(x) { x.0 })
93
93
+
|> list.filter(fn(x) { !list.is_empty(x) })
94
94
+
|> list.flatten
95
95
+
96
96
+
let tachions =
97
97
+
list.filter(acc.tachions, fn(x) { !list.contains(used_tachions, x) })
98
98
+
|> list.append(new_tachions)
99
99
+
|> list.fold(set.new(), set.insert)
100
100
+
|> set.to_list
101
101
+
102
102
+
Res(new_splits, tachions)
103
103
+
})
104
104
+
105
105
+
res.splits
106
106
+
}
107
107
+
108
108
+
type Cache =
109
109
+
dict.Dict(#(Int, Int), Int)
110
110
+
111
111
+
fn rec(
112
112
+
line: Int,
113
113
+
next: List(List(Cell)),
114
114
+
depth: Int,
115
115
+
cache: Cache,
116
116
+
) -> #(Int, Cache) {
117
117
+
let next_splitter =
118
118
+
utils.list_find_indexes(next, fn(x) {
119
119
+
result.is_ok(list.find(x, fn(y) { y.pos.x == line && y.typ == Splitter }))
120
120
+
})
121
121
+
|> list.filter(fn(x) { x > depth })
122
122
+
|> list.first()
123
123
+
124
124
+
case next_splitter {
125
125
+
Ok(lidx) -> {
126
126
+
let assert Ok(l) = list.drop(next, lidx) |> list.first
127
127
+
let assert Ok(splitter) =
128
128
+
list.find(l, fn(y) { y.pos.x == line && y.typ == Splitter })
129
129
+
130
130
+
// Check left Side
131
131
+
let #(left, cache) = case
132
132
+
dict.has_key(cache, #(splitter.pos.x - 1, lidx))
133
133
+
{
134
134
+
True -> {
135
135
+
let assert Ok(v) = dict.get(cache, #(splitter.pos.x - 1, lidx))
136
136
+
#(v, cache)
137
137
+
}
138
138
+
False -> rec(splitter.pos.x - 1, next, lidx, cache)
139
139
+
}
140
140
+
let cache = dict.insert(cache, #(splitter.pos.x - 1, lidx), left)
141
141
+
142
142
+
// Check right Side
143
143
+
let #(right, cache) = case
144
144
+
dict.has_key(cache, #(splitter.pos.x + 1, lidx))
145
145
+
{
146
146
+
True -> {
147
147
+
let assert Ok(v) = dict.get(cache, #(splitter.pos.x + 1, lidx))
148
148
+
#(v, cache)
149
149
+
}
150
150
+
False -> rec(splitter.pos.x + 1, next, lidx, cache)
151
151
+
}
152
152
+
let cache = dict.insert(cache, #(splitter.pos.x + 1, lidx), right)
153
153
+
154
154
+
#(left + right, cache)
155
155
+
}
156
156
+
Error(_) -> #(1, cache)
157
157
+
}
158
158
+
}
159
159
+
160
160
+
fn part2(data: List(List(Cell))) {
161
161
+
let assert Ok(fl) = list.first(data)
162
162
+
let assert Ok(t) = list.first(fl)
163
163
+
rec(t.pos.x, data, 0, dict.new()).0
164
164
+
}