@@ -16,40 +16,13 @@ struct Movement {
1616 distance : i32
1717}
1818
19- impl Movement {
20- pub fn dx ( & self ) -> i32 {
21- if self . direction == Direction :: R {
22- return self . distance
23- } else if self . direction == Direction :: L {
24- return -self . distance
25- }
26- return 0
27- }
28-
29- pub fn dy ( & self ) -> i32 {
30- if self . direction == Direction :: U {
31- return self . distance
32- } else if self . direction == Direction :: D {
33- return -self . distance
34- }
35- return 0
36- }
37- }
38-
39-
19+ #[ derive( Clone , Copy ) ]
4020struct Position {
4121 x : i32 ,
4222 y : i32 ,
4323}
4424
4525impl Position {
46- pub fn distance_sq ( & self , position : & Position ) -> i32 {
47- // Returns the distance squared.
48- let dx = ( self . x - position. x ) . abs ( ) ;
49- let dy = ( self . y - position. y ) . abs ( ) ;
50- return dx * dx + dy * dy
51- }
52-
5326 pub fn to_hashable ( & self ) -> String {
5427 return format ! ( "{},{}" , self . x, self . y) ;
5528 }
@@ -69,21 +42,35 @@ impl PartialEq for Position {
6942}
7043impl Eq for Position { }
7144
72- fn move_positions ( head : & Position , tail : & Position , movement : & Movement ) -> ( Position , Position ) {
73- let new_head = Position { x : head. x + movement. dx ( ) , y : head. y + movement. dy ( ) } ;
74- let mut new_tail = Position { x : tail. x , y : tail. y } ;
75- if new_head. distance_sq ( tail) > 2 {
76- new_tail = match movement. direction {
77- Direction :: U => Position { x : new_head. x , y : new_head. y - 1 } ,
78- Direction :: D => Position { x : new_head. x , y : new_head. y + 1 } ,
79- Direction :: L => Position { x : new_head. x + 1 , y : new_head. y } ,
80- Direction :: R => Position { x : new_head. x - 1 , y : new_head. y }
81- } ;
45+ fn move_head ( head : & Position , direction : & Direction ) -> Position {
46+ match direction {
47+ Direction :: U => return Position { x : head. x + 1 , y : head. y } ,
48+ Direction :: D => return Position { x : head. x - 1 , y : head. y } ,
49+ Direction :: L => return Position { x : head. x , y : head. y - 1 } ,
50+ Direction :: R => return Position { x : head. x , y : head. y + 1 }
51+ }
52+ }
53+
54+ fn follow_head ( head : & Position , tail : & Position ) -> Position {
55+ if ( head. x - tail. x ) . abs ( ) >= 2 {
56+ // Two steps left or right...
57+ if head. x > tail. x {
58+ return Position { x : head. x - 1 , y : head. y }
59+ } else {
60+ return Position { x : head. x + 1 , y : head. y }
61+ }
62+ } else if ( head. y - tail. y ) . abs ( ) >= 2 {
63+ // Two steps up or down...
64+ if head. y > tail. y {
65+ return Position { x : head. x , y : head. y - 1 }
66+ } else {
67+ return Position { x : head. x , y : head. y + 1 }
68+ }
8269 }
83- return ( new_head , new_tail )
70+ return tail . clone ( )
8471}
8572
86- fn part1 ( movements : Vec < Movement > ) {
73+ fn part1 ( movements : & Vec < Movement > ) {
8774 let mut tail_visits = HashMap :: new ( ) ;
8875
8976 let mut head_position = Position { x : 0 , y : 0 } ;
@@ -94,13 +81,8 @@ fn part1(movements: Vec<Movement>) {
9481 for movement in movements {
9582 // Simulate each step of each movement instruction.
9683 for _ in 0 ..movement. distance {
97- ( head_position, tail_position) = move_positions (
98- & head_position,
99- & tail_position,
100- & Movement { direction : movement. direction , distance : 1 }
101- ) ;
102-
103- println ! ( "{}" , tail_position. to_hashable( ) ) ;
84+ head_position = move_head ( & head_position, & movement. direction ) ;
85+ tail_position = follow_head ( & head_position, & tail_position) ;
10486
10587 tail_visits. insert ( tail_position. to_hashable ( ) , 0 ) ;
10688 }
@@ -109,6 +91,28 @@ fn part1(movements: Vec<Movement>) {
10991 println ! ( "Part 1: {}" , tail_visits. len( ) ) ;
11092}
11193
94+ fn part2 ( movements : & Vec < Movement > ) {
95+ let mut tail_visits = HashMap :: new ( ) ;
96+
97+ let mut knots: Vec < Position > = vec ! [ Position { x: 0 , y: 0 } ; 10 ] ;
98+
99+ for movement in movements {
100+ // Simulate each step of each movement instruction.
101+ for _ in 0 ..movement. distance {
102+ knots[ 0 ] = move_head ( & knots[ 0 ] , & movement. direction ) ;
103+
104+ for k in 1 ..knots. len ( ) {
105+ knots[ k] = follow_head ( & knots[ k-1 ] , & knots[ k] ) ;
106+ }
107+
108+ println ! ( "Part 2: {}" , knots. last( ) . unwrap( ) . to_hashable( ) ) ;
109+ tail_visits. insert ( knots. last ( ) . unwrap ( ) . to_hashable ( ) , 0 ) ;
110+ }
111+ }
112+
113+ println ! ( "Part 2: {}" , tail_visits. len( ) ) ;
114+ }
115+
112116pub fn run ( ) {
113117 let input = input_reader:: read_file_in_cwd ( "src/day_09.data" ) ;
114118
@@ -129,5 +133,6 @@ pub fn run() {
129133 }
130134 } ) . collect ( ) ;
131135
132- part1 ( movements)
136+ part1 ( & movements) ;
137+ part2 ( & movements) ;
133138}
0 commit comments