@@ -2,8 +2,10 @@ import gleam/int
2
2
import gleam/io
3
3
import gleam/list
4
4
import gleam/order
5
+ import gleam/result
5
6
import gleam/string
6
7
import internal/aoc_utils
8
+ import internal/memoize
7
9
import internal/point . { type Point }
8
10
9
11
pub fn main ( ) {
@@ -61,39 +63,74 @@ pub fn main() {
61
63
// Part 1
62
64
pub fn solve_p1 ( lines : List ( String ) ) -> Result ( String , String ) {
63
65
list . map ( lines , fn ( line ) {
64
- decode_numeric_sequence ( line )
65
- |> io . debug
66
- |> decode_directional_sequence
67
- |> io . debug
68
- |> decode_directional_sequence
69
- |> io . debug
70
- |> string . length
71
- |> io . debug
66
+ let length =
67
+ decode_numeric_sequence ( line )
68
+ |> decode_directional_sequence
69
+ |> decode_directional_sequence
70
+ |> list . map ( fn ( l ) { string . length ( l ) } )
71
+ |> list . reduce ( int . min )
72
+ |> result . unwrap ( 0 )
73
+ get_numeric_portions ( line ) * length
72
74
} )
73
-
74
- todo
75
+ |> int . sum
76
+ |> int . to_string
77
+ |> Ok
75
78
}
76
79
77
80
// Part 2
78
81
pub fn solve_p2 ( lines : List ( String ) ) -> Result ( String , String ) {
79
- Error ( "Unimplemented" )
82
+ // I think I will need to memoize, but I need to figure out what.
83
+ use cache <- memoize . with_cache ( )
84
+
85
+ list . map ( lines , fn ( line ) {
86
+ let length =
87
+ decode_numeric_sequence ( line )
88
+ |> todo
89
+ |> list . map ( fn ( l ) { string . length ( l ) } )
90
+ |> list . reduce ( int . min )
91
+ |> result . unwrap ( 0 )
92
+ get_numeric_portions ( line ) * length
93
+ } )
94
+ |> int . sum
95
+ |> int . to_string
96
+ |> Ok
80
97
}
81
98
82
- fn decode_numeric_sequence ( sequence : String ) -> String {
99
+ fn decode_numeric_sequence ( sequence : String ) -> List ( String ) {
83
100
string . to_graphemes ( "A" <> sequence )
84
101
|> list . window_by_2
85
102
|> list . map ( fn ( pair ) { find_motion_numeric ( pair . 0 , pair . 1 ) } )
86
- |> string . join ( "" )
103
+ |> list . reduce ( fn ( solutions , next_set ) {
104
+ solutions
105
+ |> list . map ( fn ( s ) {
106
+ next_set
107
+ |> list . map ( fn ( n ) { s <> n } )
108
+ } )
109
+ |> list . flatten
110
+ } )
111
+ |> result . unwrap ( [ ] )
87
112
}
88
113
89
- fn decode_directional_sequence ( sequence : String ) -> String {
90
- string . to_graphemes ( "A" <> sequence )
91
- |> list . window_by_2
92
- |> list . map ( fn ( pair ) { find_motion_directional ( pair . 0 , pair . 1 ) } )
93
- |> string . join ( "" )
114
+ fn decode_directional_sequence ( sequences : List ( String ) ) -> List ( String ) {
115
+ sequences
116
+ |> list . map ( fn ( sequence ) {
117
+ string . to_graphemes ( "A" <> sequence )
118
+ |> list . window_by_2
119
+ |> list . map ( fn ( pair ) { find_motion_directional ( pair . 0 , pair . 1 ) } )
120
+ |> list . reduce ( fn ( solutions , next_set ) {
121
+ solutions
122
+ |> list . map ( fn ( s ) {
123
+ next_set
124
+ |> list . map ( fn ( n ) { s <> n } )
125
+ } )
126
+ |> list . flatten
127
+ } )
128
+ |> result . unwrap ( [ ] )
129
+ } )
130
+ |> list . flatten
94
131
}
95
132
96
- fn find_motion_directional ( start : String , push : String ) -> String {
133
+ fn find_motion_directional ( start : String , push : String ) -> List ( String ) {
97
134
let assert Ok ( start_pos ) = get_directional_position ( start )
98
135
let assert Ok ( push_pos ) = get_directional_position ( push )
99
136
@@ -106,23 +143,26 @@ fn find_motion_directional(start: String, push: String) -> String {
106
143
order . Gt -> string . join ( list . repeat ( "<" , - right_count ) , "" )
107
144
}
108
145
109
- case int . compare ( start_pos . 1 , push_pos . 1 ) {
110
- order . Lt -> {
111
- // Go up first then left or right
112
- horizontal <> string . join ( list . repeat ( "^" , up_count ) , "" ) <> "A"
113
- }
114
- order . Eq -> {
115
- // Go left or right
116
- horizontal <> "A"
117
- }
118
- order . Gt -> {
119
- // Go left or right first, then down
120
- string . join ( list . repeat ( "v" , - up_count ) , "" ) <> horizontal <> "A"
121
- }
146
+ let vertical = case int . compare ( start_pos . 1 , push_pos . 1 ) {
147
+ order . Lt -> string . join ( list . repeat ( "^" , up_count ) , "" )
148
+ order . Eq -> ""
149
+ order . Gt -> string . join ( list . repeat ( "v" , - up_count ) , "" )
150
+ }
151
+
152
+ case start_pos , push_pos {
153
+ # ( _ , 1 ) , # ( 0 , _ ) -> [ vertical <> horizontal <> "A" ]
154
+ # ( 0 , _ ) , # ( _ , 1 ) -> [ horizontal <> vertical <> "A" ]
155
+ _ , _ ->
156
+ case vertical , horizontal {
157
+ "" , "" -> [ "A" ]
158
+ "" , _ -> [ horizontal <> "A" ]
159
+ _ , "" -> [ vertical <> "A" ]
160
+ _ , _ -> [ vertical <> horizontal <> "A" , horizontal <> vertical <> "A" ]
161
+ }
122
162
}
123
163
}
124
164
125
- fn find_motion_numeric ( start : String , push : String ) -> String {
165
+ fn find_motion_numeric ( start : String , push : String ) -> List ( String ) {
126
166
let assert Ok ( start_pos ) = get_numeric_position ( start )
127
167
let assert Ok ( push_pos ) = get_numeric_position ( push )
128
168
@@ -135,19 +175,22 @@ fn find_motion_numeric(start: String, push: String) -> String {
135
175
order . Gt -> string . join ( list . repeat ( "<" , - right_count ) , "" )
136
176
}
137
177
138
- case int . compare ( start_pos . 1 , push_pos . 1 ) {
139
- order . Lt -> {
140
- // Go up first then left or right
141
- string . join ( list . repeat ( "^" , up_count ) , "" ) <> horizontal <> "A"
142
- }
143
- order . Eq -> {
144
- // Go left or right
145
- horizontal <> "A"
146
- }
147
- order . Gt -> {
148
- // Go left or right first, then down
149
- horizontal <> string . join ( list . repeat ( "v" , - up_count ) , "" ) <> "A"
150
- }
178
+ let vertical = case int . compare ( start_pos . 1 , push_pos . 1 ) {
179
+ order . Lt -> string . join ( list . repeat ( "^" , up_count ) , "" )
180
+ order . Eq -> ""
181
+ order . Gt -> string . join ( list . repeat ( "v" , - up_count ) , "" )
182
+ }
183
+
184
+ case start_pos , push_pos {
185
+ # ( _ , 0 ) , # ( 0 , _ ) -> [ vertical <> horizontal <> "A" ]
186
+ # ( 0 , _ ) , # ( _ , 0 ) -> [ horizontal <> vertical <> "A" ]
187
+ _ , _ ->
188
+ case vertical , horizontal {
189
+ "" , "" -> [ "A" ]
190
+ "" , _ -> [ horizontal <> "A" ]
191
+ _ , "" -> [ vertical <> "A" ]
192
+ _ , _ -> [ vertical <> horizontal <> "A" , horizontal <> vertical <> "A" ]
193
+ }
151
194
}
152
195
}
153
196
@@ -178,3 +221,9 @@ fn get_numeric_position(key: String) -> Result(Point, Nil) {
178
221
_ -> Error ( Nil )
179
222
}
180
223
}
224
+
225
+ fn get_numeric_portions ( s : String ) -> Int {
226
+ string . drop_end ( s , 1 )
227
+ |> int . parse
228
+ |> result . unwrap ( 0 )
229
+ }
0 commit comments