1
0
Fork 0
advent-of-code/src/bin/p09.rs

169 lines
3.7 KiB
Rust

#![feature(iterator_try_collect)]
use std::fs;
use std::collections::HashSet;
use std::str;
use std::error::Error;
use std::str::FromStr;
use std::io::{self, BufRead};
#[derive(PartialEq, Debug)]
enum Direction {
Right,
Left,
Up,
Down,
}
impl FromStr for Direction {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"R" => Ok(Direction::Right),
"L" => Ok(Direction::Left),
"U" => Ok(Direction::Up),
"D" => Ok(Direction::Down),
_ => Err("Can't parse into a direction"),
}
}
}
#[derive(PartialEq, Debug)]
struct MoveDirective {
direction: Direction,
amount: i32,
}
impl FromStr for MoveDirective {
type Err = Box<dyn Error>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.len() {
x if x >= 3 => {
Ok(MoveDirective {
direction: s[0..1].parse()?,
amount: s[2..].parse()?,
})
},
_ => Err("Can't parse.".into()),
}
}
}
trait Movable {
fn do_move(&mut self, direction: &Direction);
}
type Pos = (i32, i32);
impl Movable for Pos {
fn do_move(&mut self, direction: &Direction) {
match direction {
Direction::Left => self.0 -= 1,
Direction::Right => self.0 += 1,
Direction::Up => self.1 -= 1,
Direction::Down => self.1 += 1,
}
}
}
#[derive(PartialEq, Debug)]
struct Rope {
front: Pos,
end: Pos,
}
impl Movable for Rope {
fn do_move(&mut self, direction: &Direction) {
self.front.do_move(direction);
self.update();
}
}
impl Rope {
fn new() -> Rope {
Rope{
front: (0, 0),
end: (0, 0),
}
}
fn update(&mut self) {
fn process(f: i32, e: i32, f2: i32, e2: i32) -> Pos {
// Check difference, clamp if abs greater than 1
// Then add the clamped difference to the front.
// E F
let d = e - f;
if d == 0 {
return (f, e2);
}
let abs = d.abs();
let endpos = f + d.signum();
(endpos, match abs {
x if x > 1 => f2,
_ => e2,
})
}
(self.end.0, self.end.1) = process(self.front.0, self.end.0, self.front.1, self.end.1);
(self.end.1, self.end.0) = process(self.front.1, self.end.1, self.front.0, self.end.0);
}
}
#[derive(Debug)]
struct EtchASketch(HashSet<Pos>);
impl EtchASketch {
fn new() -> EtchASketch {
EtchASketch(HashSet::new())
}
fn visit(&mut self, pos: Pos) {
self.0.insert(pos);
}
}
fn main() {
let filename = "etc/p09.txt";
let file = fs::File::open(filename).expect("Can't open file");
let reader = io::BufReader::new(file);
let directives: Vec<MoveDirective> = reader.lines().flatten().flat_map(|l| l.parse()).collect();
let mut etch = EtchASketch::new();
let mut rope = Rope::new();
etch.visit(rope.end);
for directive in directives {
dbg!(&directive);
for _ in 0..directive.amount {
rope.do_move(&directive.direction);
etch.visit(rope.end);
}
dbg!(&rope);
}
//dbg!(rope, &etch);
println!("PART ONE ---------------");
dbg!(etch.0.len());
part1();
println!("\nPART TWO ---------------");
part2();
}
fn part1() {}
fn part2() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input() {
assert_eq!(MoveDirective{ direction: Direction::Down, amount: 42 }, "D 42".parse().unwrap());
}
}