1
- use std:: io:: stdin;
2
-
3
1
use common:: { solution, Answer } ;
4
- use itertools:: Itertools ;
5
2
use nd_vec:: { vector, Vec2 } ;
6
3
7
4
solution ! ( "Restroom Redoubt" , 14 ) ;
8
5
6
+ // Part A was easy enough, just implement the logic and run it for 100 ticks. To
7
+ // be more efferent, instead of adding the velocity to the position of each
8
+ // robot on each tick, you can just add vel * ticks then basically modulo to put
9
+ // it back in bounds.
9
10
fn part_a ( input : & str ) -> Answer {
10
11
let mut problem = Problem :: parse ( input) ;
11
-
12
- // println!();
13
- for _ in 0 ..100 {
14
- problem. tick ( ) ;
15
- }
16
- // problem.debug();
12
+ problem. tick ( 100 ) ;
17
13
problem. score ( ) . into ( )
18
14
}
19
15
16
+ // When I read todays part B, I was just so confused for a while. To find boards
17
+ // that were likely showing some pattern, I just sum the distances from each
18
+ // robot to the board center, when this drops below a set threshold, I assume
19
+ // that is the tree. You can uncomment the .debug() call to actually see the
20
+ // tree.
20
21
fn part_b ( input : & str ) -> Answer {
21
22
let mut problem = Problem :: parse ( input) ;
22
23
23
- // println!();
24
- for i in 0 ..10_000 {
25
- problem. tick ( ) ;
26
- // println!("{} v", i + 1);
27
- // problem.debug();
28
- // println!();
29
- // println!("{}", problem.total_distance());
30
-
31
- if problem. total_distance ( ) < 6_000_000 {
32
- println ! ( "{}" , problem. total_distance( ) ) ;
33
- println ! ( "{} v" , i + 1 ) ;
34
- problem. debug ( ) ;
35
- stdin ( ) . read_line ( & mut String :: new ( ) ) ;
24
+ for i in 0 .. {
25
+ problem. tick ( 1 ) ;
26
+ if problem. total_distance ( ) < 20_000 {
27
+ // problem.debug();
28
+ return ( i + 1 ) . into ( ) ;
36
29
}
37
30
}
38
- // problem.debug();
39
- problem . score ( ) . into ( )
31
+
32
+ unreachable ! ( )
40
33
}
41
34
42
- // rename
43
- #[ derive( Debug ) ]
44
35
struct Problem {
45
36
bounds : Vec2 < i32 > ,
46
37
robots : Vec < Robot > ,
47
38
}
48
39
49
- #[ derive( Debug ) ]
50
40
struct Robot {
51
41
pos : Vec2 < i32 > ,
52
42
vel : Vec2 < i32 > ,
53
43
}
54
44
55
45
impl Problem {
56
46
fn parse ( input : & str ) -> Self {
57
- let robots = input. lines ( ) . map ( |x| Robot :: parse ( x ) ) . collect :: < Vec < _ > > ( ) ;
47
+ let robots = input. lines ( ) . map ( Robot :: parse) . collect :: < Vec < _ > > ( ) ;
58
48
59
49
let mut bounds = vector ! ( 0 , 0 ) ;
60
- for robot in robots. iter ( ) {
61
- bounds = vector ! ( robot. pos. x( ) . max( bounds. x( ) ) , robot. pos. y( ) . max( bounds. y( ) ) ) ;
62
- }
63
- bounds += vector ! ( 1 , 1 ) ;
50
+ robots. iter ( ) . for_each ( |robot| {
51
+ bounds = vector ! ( robot. pos. x( ) . max( bounds. x( ) ) , robot. pos. y( ) . max( bounds. y( ) ) )
52
+ } ) ;
64
53
65
- Self { robots, bounds }
54
+ Self {
55
+ robots,
56
+ bounds : bounds + vector ! ( 1 , 1 ) ,
57
+ }
66
58
}
67
59
68
- fn tick ( & mut self ) {
69
- self . robots . iter_mut ( ) . for_each ( |x| x. tick ( self . bounds ) ) ;
60
+ fn tick ( & mut self , n : i32 ) {
61
+ self . robots . iter_mut ( ) . for_each ( |x| x. tick ( self . bounds , n ) ) ;
70
62
}
71
63
72
64
fn total_distance ( & self ) -> i32 {
73
- let mut sum = 0 ;
74
- for ( a , b ) in self . robots . iter ( ) . tuple_combinations ( ) {
75
- sum += a . pos . manhattan_distance ( & b . pos ) ;
76
- }
77
- sum
65
+ let middle = self . bounds / 2 ;
66
+ self . robots
67
+ . iter ( )
68
+ . map ( |x| x . pos . manhattan_distance ( & middle ) )
69
+ . sum ( )
78
70
}
79
71
72
+ #[ allow( unused) ]
80
73
fn debug ( & self ) {
81
- let half_bounds = self . bounds / 2 ;
82
-
83
- for y in ( 0 ..self . bounds . y ( ) ) {
84
- for x in ( 0 ..self . bounds . x ( ) ) {
74
+ for y in 0 ..self . bounds . y ( ) {
75
+ for x in 0 ..self . bounds . x ( ) {
85
76
let robots = self
86
77
. robots
87
78
. iter ( )
@@ -101,19 +92,14 @@ impl Problem {
101
92
fn score ( & self ) -> u32 {
102
93
let half_bounds = self . bounds / 2 ;
103
94
104
- // 0 1 2 3 4
105
-
106
95
let mut quadrants = [ 0 ; 4 ] ;
107
- for robot in self . robots . iter ( ) {
108
- let pos = robot. pos ;
109
-
96
+ for pos in self . robots . iter ( ) . map ( |x| x. pos ) {
110
97
if pos. x ( ) == half_bounds. x ( ) || pos. y ( ) == half_bounds. y ( ) {
111
98
continue ;
112
99
}
113
100
114
101
let width = ( 0 ..=half_bounds. x ( ) ) . contains ( & pos. x ( ) ) ;
115
102
let height = ( 0 ..=half_bounds. y ( ) ) . contains ( & pos. y ( ) ) ;
116
-
117
103
quadrants[ ( ( width as usize ) << 1 ) | height as usize ] += 1 ;
118
104
}
119
105
@@ -135,24 +121,12 @@ impl Robot {
135
121
}
136
122
}
137
123
138
- fn tick ( & mut self , bounds : Vec2 < i32 > ) {
139
- self . pos += self . vel ;
140
-
141
- while self . pos . x ( ) < 0 {
142
- self . pos += vector ! ( bounds. x( ) , 0 ) ;
143
- }
144
-
145
- while self . pos . x ( ) >= bounds. x ( ) {
146
- self . pos -= vector ! ( bounds. x( ) , 0 ) ;
147
- }
148
-
149
- while self . pos . y ( ) < 0 {
150
- self . pos += vector ! ( 0 , bounds. y( ) ) ;
151
- }
152
-
153
- while self . pos . y ( ) >= bounds. y ( ) {
154
- self . pos -= vector ! ( 0 , bounds. y( ) ) ;
155
- }
124
+ fn tick ( & mut self , bounds : Vec2 < i32 > , n : i32 ) {
125
+ self . pos += self . vel * n;
126
+ self . pos = vector ! (
127
+ ( self . pos. x( ) % bounds. x( ) + bounds. x( ) ) % bounds. x( ) ,
128
+ ( self . pos. y( ) % bounds. y( ) + bounds. y( ) ) % bounds. y( )
129
+ ) ;
156
130
}
157
131
}
158
132
0 commit comments