broken implementation of day 9
This commit is contained in:
parent
2e2d668269
commit
9236e70abe
@ -39,6 +39,10 @@ path = "src/day7.rs"
|
|||||||
name = "day8"
|
name = "day8"
|
||||||
path = "src/day8.rs"
|
path = "src/day8.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day9"
|
||||||
|
path = "src/day9.rs"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -8,7 +8,7 @@ const DATA: &'static str = include_str!("../data/day8.txt");
|
|||||||
// ";
|
// ";
|
||||||
|
|
||||||
|
|
||||||
// O(N * (2 * sqrt(N) - 1)), so roughly N^1.5? Where N is number of elements in the grid
|
// O(N * (2 * (sqrt(N) - 1))), so roughly N^1.5? Where N is number of elements in the grid
|
||||||
fn is_visible(grid: &Vec<Vec<usize>>, x: usize, y: usize) -> bool {
|
fn is_visible(grid: &Vec<Vec<usize>>, x: usize, y: usize) -> bool {
|
||||||
let height = grid[y][x];
|
let height = grid[y][x];
|
||||||
let rows = grid.len();
|
let rows = grid.len();
|
||||||
|
140
2022/src/day9.rs
Normal file
140
2022/src/day9.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum Direction {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Direction {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, String> {
|
||||||
|
match s {
|
||||||
|
"L" => Ok(Direction::Left),
|
||||||
|
"R" => Ok(Direction::Right),
|
||||||
|
"U" => Ok(Direction::Up),
|
||||||
|
"D" => Ok(Direction::Down),
|
||||||
|
_ => Err(format!("Not a valid direction: {s}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
struct Pos {
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Rope<const L: usize> {
|
||||||
|
knots: [Pos; L],
|
||||||
|
tail_visited: HashSet<Pos>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const L: usize> Rope<L> {
|
||||||
|
fn new() -> Self {
|
||||||
|
Rope {
|
||||||
|
knots: [Pos {x: 0, y: 0}; L],
|
||||||
|
tail_visited: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_move(&mut self, dir: Direction, count: isize) {
|
||||||
|
for _ in 0..count {
|
||||||
|
let head = &mut self.knots[0];
|
||||||
|
match dir {
|
||||||
|
Direction::Left => head.x -= 1,
|
||||||
|
Direction::Right => head.x += 1,
|
||||||
|
Direction::Up => head.y += 1,
|
||||||
|
Direction::Down => head.y -= 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 1..(self.knots.len()) {
|
||||||
|
self.move_follower(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tail_visited.insert(*self.knots.last().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_follower(&mut self, i: usize) {
|
||||||
|
let leader = self.knots[i - 1];
|
||||||
|
let follower = &mut self.knots[i];
|
||||||
|
|
||||||
|
let dx = leader.x - follower.x;
|
||||||
|
let dy = leader.y - follower.y;
|
||||||
|
|
||||||
|
// check to make sure that we didn't do anything wrong previously
|
||||||
|
if dx.abs() + dy.abs() > 3
|
||||||
|
|| dx.abs() == 0 && dy.abs() == 3
|
||||||
|
|| dx.abs() == 3 && dy.abs() == 0
|
||||||
|
{
|
||||||
|
panic!("Invalid head and tail positions: {dx}, {dy}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// head and tail are in line vertically
|
||||||
|
if dx == 0 && dy.abs() == 2 {
|
||||||
|
follower.y += dy / 2; // use integer division to keep the sign of dy
|
||||||
|
}
|
||||||
|
// in line horizontally
|
||||||
|
if dy == 0 && dx.abs() == 2 {
|
||||||
|
follower.x += dx / 2; // similarly
|
||||||
|
}
|
||||||
|
|
||||||
|
// head and tail are offset by 1 horizontaly and 2 vertically
|
||||||
|
if dx.abs() == 1 && dy.abs() == 2 {
|
||||||
|
follower.x += dx;
|
||||||
|
follower.y += dy / 2;
|
||||||
|
}
|
||||||
|
// offset by 1 vertically and 2 horizontally
|
||||||
|
if dy.abs() == 1 && dx.abs() == 2 {
|
||||||
|
follower.y += dy;
|
||||||
|
follower.x += dx / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() -> Result<(), String> {
|
||||||
|
let instructions = DATA.trim()
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let mut splat = line.split(' ');
|
||||||
|
match (splat.next(), splat.next()) {
|
||||||
|
(Some(dir), Some(dist)) => {
|
||||||
|
let dist = dist.parse().map_err(|_e| format!("Not an integer: {dist}"));
|
||||||
|
Ok((dir.parse()?, dist?))
|
||||||
|
},
|
||||||
|
_ => Err(format!("Could not parse move instruction from line: {line}"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<(Direction, isize)>, String>>()?;
|
||||||
|
|
||||||
|
let mut rope = Rope::<10>::new();
|
||||||
|
for (dir, dist) in instructions {
|
||||||
|
rope.do_move(dir, dist)
|
||||||
|
}
|
||||||
|
println!("{}", rope.tail_visited.len());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// const DATA: &'static str = include_str!("../data/day9.txt");
|
||||||
|
const DATA: &'static str = "
|
||||||
|
R 5
|
||||||
|
U 8
|
||||||
|
L 8
|
||||||
|
D 3
|
||||||
|
R 17
|
||||||
|
D 10
|
||||||
|
L 25
|
||||||
|
U 20
|
||||||
|
";
|
@ -0,0 +1,67 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
|
||||||
|
struct Grid<T> {
|
||||||
|
rows: Vec<Vec<T>>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> Grid<T> {
|
||||||
|
fn new() -> Self {
|
||||||
|
Grid { rows: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_default_values<D>(width: usize, height: usize) -> Self
|
||||||
|
where T: Default + Clone
|
||||||
|
{
|
||||||
|
let rows = (0..height)
|
||||||
|
.map(|_i| vec![Default::default(); width])
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Grid { rows }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_rows<I>(rows: I) -> Self
|
||||||
|
where I: Iterator<Item = Vec<T>>
|
||||||
|
{
|
||||||
|
Grid { rows: rows.collect() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_chars<F, E>(src: &str, conv: F) -> Result<Self, E>
|
||||||
|
where F: Fn(char) -> Result<T, E>
|
||||||
|
{
|
||||||
|
let rows: Result<Vec<Vec<T>>, E> = src.lines()
|
||||||
|
.map(|line| {
|
||||||
|
line.chars()
|
||||||
|
.map(|c| conv(c))
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(Grid { rows: rows? })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter_rows(&self) -> impl Iterator<Item = &Vec<T>> {
|
||||||
|
self.rows.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> Index<[usize; 2]> for Grid<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, idx: [usize; 2]) -> &T {
|
||||||
|
let [x, y] = idx;
|
||||||
|
&self.rows[y][x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> IndexMut<[usize; 2]> for Grid<T> {
|
||||||
|
fn index_mut(&mut self, idx: [usize; 2]) -> &mut T {
|
||||||
|
let [x, y] = idx;
|
||||||
|
&mut self.rows[y][x]
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user