Update solution for 2022 day 09

Just some minor cleanup
This commit is contained in:
Patrick Auernig 2022-12-10 14:21:44 +01:00
parent f36de1f4e9
commit 37eb9e1ab6
3 changed files with 39 additions and 67 deletions

View File

@ -13,14 +13,14 @@ fn main() -> io::Result<()> {
} }
fn solve(path: &str) -> io::Result<usize> { fn solve(path: &str) -> io::Result<usize> {
let instructions = parse_input(path)?; let directions = parse_input(path)?;
let mut rope = Rope::new(2); let mut rope = Rope::new(2);
let mut tail_visited = Visited::new(); let mut tail_visited = Visited::new();
tail_visited.insert(rope.tail().unwrap().clone()); tail_visited.insert(rope.tail().unwrap().clone());
for instruction in instructions { for direction in directions {
instruction.apply_to_rope(&mut rope, &mut tail_visited); direction.apply_to_rope(&mut rope, &mut tail_visited);
} }
Ok(tail_visited.len()) Ok(tail_visited.len())

View File

@ -13,14 +13,14 @@ fn main() -> io::Result<()> {
} }
fn solve(path: &str) -> io::Result<usize> { fn solve(path: &str) -> io::Result<usize> {
let instructions = parse_input(path)?; let directions = parse_input(path)?;
let mut rope = Rope::new(10); let mut rope = Rope::new(10);
let mut tail_visited = Visited::new(); let mut tail_visited = Visited::new();
tail_visited.insert(rope.tail().unwrap().clone()); tail_visited.insert(rope.tail().unwrap().clone());
for instruction in instructions { for direction in directions {
instruction.apply_to_rope(&mut rope, &mut tail_visited); direction.apply_to_rope(&mut rope, &mut tail_visited);
} }
Ok(tail_visited.len()) Ok(tail_visited.len())

View File

@ -16,31 +16,24 @@ impl Rope {
Self(vec![Knot::default(); len]) Self(vec![Knot::default(); len])
} }
pub fn move_head(&mut self, change: (isize, isize)) { pub fn move_head(&mut self, change: (i32, i32)) {
let mut knots = self.0.iter_mut(); let mut knots = self.0.iter_mut();
let mut next_a = knots.next(); let mut next_a = knots.next();
let head_knot = next_a.as_mut().expect("no head knot");
next_a.as_mut().map(|head_knot| { head_knot.0 += change.0;
head_knot.0 += change.0; head_knot.1 += change.1;
head_knot.1 += change.1;
});
let mut next_b = knots.next();
loop { loop {
if next_a.is_some() && next_b.is_some() { let mut next_b = knots.next();
next_a.as_mut().map(|knot_a| {
next_b.as_mut().map(|knot_b| {
knot_b.follow(&knot_a);
});
});
next_a = next_b; let (Some(knot_a), Some(knot_b)) = (next_a.as_mut(), next_b.as_mut()) else {
next_b = knots.next();
} else {
break; break;
} };
knot_b.follow(&knot_a);
next_a = next_b;
} }
} }
@ -50,56 +43,48 @@ impl Rope {
} }
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct Knot(isize, isize); pub struct Knot(i32, i32);
impl Knot { impl Knot {
pub fn follow(&mut self, other: &Self) { pub fn follow(&mut self, other: &Self) {
let dx = other.0 - self.0; let dx = other.0 - self.0;
let dxa = dx.abs();
let dy = other.1 - self.1; let dy = other.1 - self.1;
let dya = dy.abs();
let same_row = self.0 == other.0; let same_row = self.0 == other.0;
let same_col = self.1 == other.1; let same_col = self.1 == other.1;
let x = if dx.is_negative() { -1 } else { 1 }; if (!same_row && !same_col) && (dx.abs() > 1 || dy.abs() > 1) {
let y = if dy.is_negative() { -1 } else { 1 }; self.0 += dx.signum();
self.1 += dy.signum();
if (!same_row && !same_col) && (dxa > 1 || dya > 1) { } else if dx.abs() > 1 {
self.0 += x; self.0 += dx.signum();
self.1 += y; } else if dy.abs() > 1 {
} else if dxa > 1 { self.1 += dy.signum();
self.0 += x;
} else if dya > 1 {
self.1 += y;
} }
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Instruction { pub struct Direction(i32, i32, i32);
Up(isize),
Right(isize),
Left(isize),
Down(isize),
}
impl FromStr for Instruction { impl FromStr for Direction {
type Err = String; type Err = String;
fn from_str(val: &str) -> Result<Self, Self::Err> { fn from_str(val: &str) -> Result<Self, Self::Err> {
let parts = val.split_whitespace().collect::<Vec<&str>>(); let parts = val.split_whitespace().collect::<Vec<&str>>();
let [direction, distance, ..] = parts[..] else { let [direction, distance, ..] = parts[..] else {
return Err("Invalid instruction".to_string()); return Err("Invalid instruction".to_string());
}; };
let distance = distance let distance = distance
.parse() .parse()
.map_err(|_| "Invalid distance value".to_string())?; .map_err(|_| "Invalid distance value".to_string())?;
let result = match direction { let result = match direction {
"U" => Self::Up(distance), "U" => Self(1, 0, distance),
"R" => Self::Right(distance), "R" => Self(0, 1, distance),
"L" => Self::Left(distance), "L" => Self(0, -1, distance),
"D" => Self::Down(distance), "D" => Self(-1, 0, distance),
_ => return Err("Invalid direction value".to_string()), _ => return Err("Invalid direction value".to_string()),
}; };
@ -107,30 +92,17 @@ impl FromStr for Instruction {
} }
} }
impl Instruction { impl Direction {
pub fn apply_to_rope(&self, rope: &mut Rope, tail_visited: &mut Visited) { pub fn apply_to_rope(&self, rope: &mut Rope, tail_visited: &mut Visited) {
let (change, amount) = match *self { for _ in 0..self.2 {
Instruction::Up(dist) => ((1, 0), dist), rope.move_head((self.0, self.1));
Instruction::Right(dist) => ((0, 1), dist), let tail = rope.tail().unwrap();
Instruction::Left(dist) => ((0, -1), dist), tail_visited.insert(tail.clone());
Instruction::Down(dist) => ((-1, 0), dist),
};
for _ in 0..amount {
let old_tail = rope.tail().unwrap().clone();
rope.move_head(change);
let new_tail = rope.tail().unwrap();
if old_tail != *new_tail {
tail_visited.insert(new_tail.clone());
}
} }
} }
} }
pub fn parse_input<P>(path: P) -> io::Result<Vec<Instruction>> pub fn parse_input<P>(path: P) -> io::Result<Vec<Direction>>
where where
P: AsRef<Path>, P: AsRef<Path>,
{ {