Skip to content

Commit

Permalink
2022_09: rust solution(part 2)
Browse files Browse the repository at this point in the history
  • Loading branch information
MellKam committed Dec 14, 2022
1 parent ee9a822 commit 4dca86e
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 38 deletions.
4 changes: 2 additions & 2 deletions 2022/day_9/rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use rope::{parse_series_of_motions, Rope};
fn main() {
let input = include_str!("../../input.txt");

let mut rope = Rope::new();
let mut rope = Rope::new(10, (0, 0));
let motions = parse_series_of_motions(input);

motions.iter().for_each(|motion| rope.apply_motion(motion));

assert_eq!(rope.get_tails_visited_positions(), 5710);
assert_eq!(rope.get_tails_visited_positions(), 2259);
}
110 changes: 74 additions & 36 deletions 2022/day_9/rust/src/rope.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
cmp::{max, min},
collections::HashSet,
ops::Range,
};

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -42,72 +43,105 @@ pub fn parse_series_of_motions(string: &str) -> Vec<Motion> {

#[derive(Debug)]
pub struct Rope {
head: (i32, i32),
tail: (i32, i32),
knots: Vec<(i32, i32)>,
tails_visited_positions: HashSet<(i32, i32)>,
}

pub fn get_vectors_delta(v1: (i32, i32), v2: (i32, i32)) -> (i32, i32) {
pub fn get_vectors_delta(v1: &(i32, i32), v2: &(i32, i32)) -> (i32, i32) {
(
max(v1.0, v2.0) - min(v1.0, v2.0),
max(v1.1, v2.1) - min(v1.1, v2.1),
)
}

impl Rope {
pub fn new() -> Self {
pub fn new(knots_count: u8, start_point: (i32, i32)) -> Self {
let mut tails_visited_positions = HashSet::new();
tails_visited_positions.insert((0, 0));
tails_visited_positions.insert(start_point);

let mut knots: Vec<(i32, i32)> = Vec::new();

for _ in 0..knots_count {
knots.push(start_point);
}

Self {
head: (0, 0),
tail: (0, 0),
knots,
tails_visited_positions,
}
}

fn get_rope_state(&self) -> (bool, (i32, i32)) {
let delta = get_vectors_delta(self.head, self.tail);
return (!(delta.0 > 1 || delta.1 > 1), delta);
fn is_ropes_touch(delta: &(i32, i32)) -> bool {
return !(delta.0 > 1 || delta.1 > 1);
}

pub fn move_tail_to_head(&mut self, delta: (i32, i32)) {
pub fn move_knot(&mut self, delta: &(i32, i32), top_knot_index: usize) {
if delta.0 >= 1 {
if self.head.0 > self.tail.0 {
self.tail.0 += 1;
if self.knots[top_knot_index].0 > self.knots[top_knot_index + 1].0 {
self.knots[top_knot_index + 1].0 += 1;
} else {
self.tail.0 -= 1;
self.knots[top_knot_index + 1].0 -= 1;
}
}

if delta.1 >= 1 {
if self.head.1 > self.tail.1 {
self.tail.1 += 1;
if self.knots[top_knot_index].1 > self.knots[top_knot_index + 1].1 {
self.knots[top_knot_index + 1].1 += 1;
} else {
self.tail.1 -= 1;
self.knots[top_knot_index + 1].1 -= 1;
}
}
}

pub fn apply_motion(&mut self, motion: &Motion) {
match *motion {
Motion::Down => self.head.1 -= 1,
Motion::Left => self.head.0 -= 1,
Motion::Right => self.head.0 += 1,
Motion::Up => self.head.1 += 1,
Motion::Down => self.knots[0].1 -= 1,
Motion::Left => self.knots[0].0 -= 1,
Motion::Right => self.knots[0].0 += 1,
Motion::Up => self.knots[0].1 += 1,
}

let (is_touch, delta) = self.get_rope_state();
let mut iter = (0..self.knots.len() - 1).into_iter();

loop {
let i = match iter.next() {
Some(i) => i,
None => break,
};

if !is_touch {
self.move_tail_to_head(delta);
self.tails_visited_positions.insert(self.tail);
let delta = get_vectors_delta(&self.knots[i], &self.knots[i + 1]);

if Rope::is_ropes_touch(&delta) {
break;
}

self.move_knot(&delta, i);
}

self
.tails_visited_positions
.insert(*self.knots.last().unwrap());
}

pub fn get_tails_visited_positions(&self) -> usize {
self.tails_visited_positions.len()
}

pub fn print_rope(&self) {
let y_range = -16..16;
let x_range = -16..16;

for y in y_range.rev() {
for x in x_range.clone() {
let i = self.knots.iter().position(|&p| p == (x + 1, y + 1));
match i {
Some(i) => print!("{i}"),
None => print!("."),
}
}
print!("\n");
}
}
}

#[cfg(test)]
Expand All @@ -117,20 +151,24 @@ mod tests {
#[test]
fn demo() {
let input = "\
R 4\n\
U 4\n\
L 3\n\
D 1\n\
R 4\n\
D 1\n\
L 5\n\
R 2";

let mut rope = Rope::new();
R 5\n\
U 8\n\
L 8\n\
D 3\n\
R 17\n\
D 10\n\
L 25\n\
";

let mut rope = Rope::new(10, (0, 0));
let motions = parse_series_of_motions(input);

motions.iter().for_each(|motion| rope.apply_motion(motion));

assert_eq!(rope.tails_visited_positions.len(), 13);
rope.print_rope();

println!("{:?}", rope.knots);

assert_eq!(rope.tails_visited_positions.len(), 36);
}
}

0 comments on commit 4dca86e

Please sign in to comment.