finish day 9

This commit is contained in:
Joseph Montanaro 2022-12-09 22:41:21 -08:00
parent 9236e70abe
commit 9ef31dde55

View File

@ -1,4 +1,5 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt::{Display, Formatter};
use std::str::FromStr; use std::str::FromStr;
@ -35,14 +36,14 @@ struct Pos {
#[derive(Debug)] #[derive(Debug)]
struct Rope<const L: usize> { struct Rope<const L: usize> {
knots: [Pos; L], knots: [Pos; L],
tail_visited: HashSet<Pos> tail_visited: HashSet<Pos>,
} }
impl<const L: usize> Rope<L> { impl<const L: usize> Rope<L> {
fn new() -> Self { fn new() -> Self {
Rope { Rope {
knots: [Pos {x: 0, y: 0}; L], knots: [Pos {x: 0, y: 0}; L],
tail_visited: HashSet::new(), tail_visited: HashSet::new()
} }
} }
@ -72,9 +73,9 @@ impl<const L: usize> Rope<L> {
let dy = leader.y - follower.y; let dy = leader.y - follower.y;
// check to make sure that we didn't do anything wrong previously // check to make sure that we didn't do anything wrong previously
if dx.abs() + dy.abs() > 3 if dx.abs() + dy.abs() > 4
|| dx.abs() == 0 && dy.abs() == 3 || dx.abs() == 0 && dy.abs() > 2
|| dx.abs() == 3 && dy.abs() == 0 || dx.abs() > 2 && dy.abs() == 0
{ {
panic!("Invalid head and tail positions: {dx}, {dy}"); panic!("Invalid head and tail positions: {dx}, {dy}");
} }
@ -98,6 +99,43 @@ impl<const L: usize> Rope<L> {
follower.y += dy; follower.y += dy;
follower.x += dx / 2; follower.x += dx / 2;
} }
// offset by 2 in both dimensions
if dx.abs() == 2 && dy.abs() == 2 {
follower.x += dx / 2;
follower.y += dy / 2;
}
}
}
use std::convert::TryFrom;
impl<const L: usize> Display for Rope<L> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
let min_x = self.knots.iter().map(|pos| pos.x).min().unwrap();
let max_x = self.knots.iter().map(|pos| pos.x).max().unwrap();
let min_y = self.knots.iter().map(|pos| pos.y).min().unwrap();
let max_y = self.knots.iter().map(|pos| pos.y).max().unwrap();
let n_rows = usize::try_from(max_y - min_y + 1).unwrap();
let n_cols = usize::try_from(max_x - min_x + 1).unwrap();
let mut grid = vec![vec!['.'; n_cols]; n_rows];
for (i, kt) in self.knots.iter().enumerate() {
let rel_x = usize::try_from(kt.x - min_x).unwrap();
let rel_y = usize::try_from(max_y - kt.y).unwrap();
let tgt = &mut grid[rel_y][rel_x];
if *tgt == '.' {
*tgt = char::from_digit(i as u32, 10).unwrap();
}
}
for row in grid {
write!(f, "{}\n", row.iter().collect::<String>())?;
}
Ok(())
} }
} }
@ -117,24 +155,30 @@ fn main() -> Result<(), String> {
}) })
.collect::<Result<Vec<(Direction, isize)>, String>>()?; .collect::<Result<Vec<(Direction, isize)>, String>>()?;
let mut rope = Rope::<10>::new(); let mut rope1 = Rope::<2>::new();
for (dir, dist) in instructions { for &(dir, dist) in &instructions {
rope.do_move(dir, dist) rope1.do_move(dir, dist);
} }
println!("{}", rope.tail_visited.len()); println!("Part 1: {}", rope1.tail_visited.len());
let mut rope2 = Rope::<10>::new();
for &(dir, dist) in &instructions {
rope2.do_move(dir, dist);
}
println!("Part 2: {}", rope2.tail_visited.len());
Ok(()) Ok(())
} }
// const DATA: &'static str = include_str!("../data/day9.txt"); const DATA: &'static str = include_str!("../data/day9.txt");
const DATA: &'static str = " // const DATA: &'static str = "
R 5 // R 5
U 8 // U 8
L 8 // L 8
D 3 // D 3
R 17 // R 17
D 10 // D 10
L 25 // L 25
U 20 // U 20
"; // ";