day 9
This commit is contained in:
2000
inputs/day09.txt
Normal file
2000
inputs/day09.txt
Normal file
File diff suppressed because it is too large
Load Diff
8
src/bin/day09_1.rs
Normal file
8
src/bin/day09_1.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use std::fs;
|
||||
|
||||
use aoc2022::day09::process_part_1;
|
||||
|
||||
fn main() {
|
||||
let file = fs::read_to_string("./inputs/day09.txt").unwrap();
|
||||
println!("{}", process_part_1(&file));
|
||||
}
|
||||
8
src/bin/day09_2.rs
Normal file
8
src/bin/day09_2.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use std::fs;
|
||||
|
||||
use aoc2022::day09::process_part_2;
|
||||
|
||||
fn main() {
|
||||
let file = fs::read_to_string("./inputs/day09.txt").unwrap();
|
||||
println!("{}", process_part_2(&file));
|
||||
}
|
||||
115
src/day09.rs
Normal file
115
src/day09.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::str::FromStr;
|
||||
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete;
|
||||
use nom::character::complete::{alpha1, newline};
|
||||
use nom::combinator::map_res;
|
||||
use nom::multi::separated_list1;
|
||||
use nom::IResult;
|
||||
|
||||
pub fn process_part_1(input: &str) -> usize {
|
||||
let (_, moves) = parse(input).unwrap();
|
||||
let visited = simulate_rope(moves, 2);
|
||||
return visited.len();
|
||||
}
|
||||
|
||||
pub fn process_part_2(input: &str) -> usize {
|
||||
let (_, moves) = parse(input).unwrap();
|
||||
let visited = simulate_rope(moves, 10);
|
||||
return visited.len();
|
||||
}
|
||||
|
||||
fn simulate_rope(moves: Vec<(Direction, usize)>, rope_size: usize) -> BTreeSet<(i32, i32)> {
|
||||
let all_moves = moves
|
||||
.iter()
|
||||
.flat_map(|&(dir, count)| itertools::repeat_n(dir, count));
|
||||
|
||||
let mut knots: Vec<(i32, i32)> = vec![(0, 0); rope_size];
|
||||
let mut visited = BTreeSet::new();
|
||||
|
||||
for dir in all_moves {
|
||||
match dir {
|
||||
Direction::Left => knots[0].0 -= 1,
|
||||
Direction::Right => knots[0].0 += 1,
|
||||
Direction::Up => knots[0].1 += 1,
|
||||
Direction::Down => knots[0].1 -= 1,
|
||||
}
|
||||
|
||||
for i in 1..rope_size {
|
||||
let dist_h = knots[i - 1].0 - knots[i].0;
|
||||
let dist_v = knots[i - 1].1 - knots[i].1;
|
||||
if dist_h.abs() > 1 || dist_v.abs() > 1 {
|
||||
knots[i].0 += dist_h.signum();
|
||||
knots[i].1 += dist_v.signum();
|
||||
}
|
||||
}
|
||||
|
||||
visited.insert(*knots.last().unwrap());
|
||||
}
|
||||
visited
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
impl FromStr for Direction {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"L" => Ok(Direction::Left),
|
||||
"R" => Ok(Direction::Right),
|
||||
"U" => Ok(Direction::Up),
|
||||
"D" => Ok(Direction::Down),
|
||||
_ => Err("Invalid direction".into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> IResult<&str, Vec<(Direction, usize)>> {
|
||||
separated_list1(newline, parse_line)(input)
|
||||
}
|
||||
|
||||
fn parse_line(input: &str) -> IResult<&str, (Direction, usize)> {
|
||||
let (input, direction) = map_res(alpha1, Direction::from_str)(input)?;
|
||||
let (input, _) = tag(" ")(input)?;
|
||||
let (input, count) = complete::u32(input)?;
|
||||
Ok((input, (direction, count as usize)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const INPUT: &str = "R 4
|
||||
U 4
|
||||
L 3
|
||||
D 1
|
||||
R 4
|
||||
D 1
|
||||
L 5
|
||||
R 2";
|
||||
const INPUT2: &str = "R 5
|
||||
U 8
|
||||
L 8
|
||||
D 3
|
||||
R 17
|
||||
D 10
|
||||
L 25
|
||||
U 20";
|
||||
|
||||
#[test]
|
||||
fn day1() {
|
||||
assert_eq!(process_part_1(INPUT), 13);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn day2() {
|
||||
assert_eq!(process_part_2(INPUT2), 36);
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ pub mod day05;
|
||||
pub mod day06;
|
||||
pub mod day07;
|
||||
pub mod day08;
|
||||
pub mod day09;
|
||||
|
||||
Reference in New Issue
Block a user