This commit is contained in:
2022-12-09 19:09:51 +01:00
parent 5b96ff7baf
commit c8ea1f9fa2
5 changed files with 2132 additions and 0 deletions

2000
inputs/day09.txt Normal file

File diff suppressed because it is too large Load Diff

8
src/bin/day09_1.rs Normal file
View 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
View 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
View 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);
}
}

View File

@@ -9,3 +9,4 @@ pub mod day05;
pub mod day06;
pub mod day07;
pub mod day08;
pub mod day09;