summaryrefslogtreecommitdiff
path: root/2022/Rust/src
diff options
context:
space:
mode:
authoromagdy7 <omar.professional8777@gmail.com>2023-04-10 18:01:24 +0200
committeromagdy7 <omar.professional8777@gmail.com>2023-04-10 18:01:24 +0200
commit28d6c497dbb75a51419e107fc8a2e5af1656193f (patch)
treed75a9bf9af53aaebee0cd465aa1749941c73c154 /2022/Rust/src
parent6fe48efac60f0ffcff0a81f41df33f6423189e03 (diff)
downloadaoc-28d6c497dbb75a51419e107fc8a2e5af1656193f.tar.xz
aoc-28d6c497dbb75a51419e107fc8a2e5af1656193f.zip
Day9 done in rust
Diffstat (limited to '2022/Rust/src')
-rw-r--r--2022/Rust/src/day8.rs4
-rw-r--r--2022/Rust/src/day9.rs237
2 files changed, 237 insertions, 4 deletions
diff --git a/2022/Rust/src/day8.rs b/2022/Rust/src/day8.rs
index 6a337f6..3af5d26 100644
--- a/2022/Rust/src/day8.rs
+++ b/2022/Rust/src/day8.rs
@@ -18,7 +18,6 @@ impl Direction {
}
fn is_visible(grd: &Vec<&str>, direction: &Direction, visible: &mut Vec<Vec<bool>>) {
- let mut max_height = 0;
match direction {
Direction::Up => {
for j in 0..grd[0].len() {
@@ -109,16 +108,13 @@ fn count_vis_up(pos: (usize, usize), grd: &Vec<&str>) -> usize {
let mut cnt = 0;
if is_valid_idx(pos, (grd.len(), grd[0].len()), &Direction::Up) {
let ch = grd[pos.0].chars().nth(pos.1).unwrap() as u8;
- // print!("{:?} ", pos);
for i in (0..=(pos.0 - 1)).rev() {
- // print!("{:?}, ", (i, pos.1));
if grd[i].chars().nth(pos.1).unwrap() as u8 >= ch {
cnt += 1;
break;
}
cnt += 1
}
- // println!()
}
cnt
}
diff --git a/2022/Rust/src/day9.rs b/2022/Rust/src/day9.rs
new file mode 100644
index 0000000..b32c910
--- /dev/null
+++ b/2022/Rust/src/day9.rs
@@ -0,0 +1,237 @@
+use std::{collections::HashSet, str::FromStr, string::ParseError};
+
+#[derive(Debug)]
+enum Command {
+ Up(usize),
+ Down(usize),
+ Right(usize),
+ Left(usize),
+}
+
+impl FromStr for Command {
+ type Err = ParseError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let (dir, amount) = s.split_once(" ").unwrap();
+ let parsed_amount = amount
+ .parse::<usize>()
+ .expect("Should be parsable to usize");
+ match dir {
+ "R" => Ok(Command::Right(parsed_amount)),
+ "L" => Ok(Command::Left(parsed_amount)),
+ "U" => Ok(Command::Up(parsed_amount)),
+ "D" => Ok(Command::Down(parsed_amount)),
+ _ => unreachable!(),
+ }
+ }
+}
+
+enum Direction {
+ Up,
+ Down,
+ Right,
+ Left,
+ UpRight,
+ UpLeft,
+ DownRight,
+ DownLeft,
+ NoOp,
+}
+
+impl Direction {
+ fn new(diff: (i32, i32)) -> Self {
+ use Direction::*;
+ match diff {
+ (2, 0) => Right,
+ (-2, 0) => Left,
+ (0, 2) => Up,
+ (0, -2) => Down,
+ (1, 2) => UpRight,
+ (2, 1) => UpRight,
+ (2, 2) => UpRight,
+ (-2, 1) => UpLeft,
+ (-1, 2) => UpLeft,
+ (-2, 2) => UpLeft,
+ (-1, -2) => DownLeft,
+ (-2, -2) => DownLeft,
+ (-2, -1) => DownLeft,
+ (2, -1) => DownRight,
+ (2, -2) => DownRight,
+ (1, -2) => DownRight,
+ _ => NoOp,
+ }
+ }
+}
+
+struct Simulation {
+ unique_pos: HashSet<(i32, i32)>, // will mark tail positions
+ head_pos: (i32, i32),
+ tail_pos: Vec<(i32, i32)>,
+}
+
+impl Simulation {
+ fn new(
+ unique_pos: HashSet<(i32, i32)>,
+ head_pos: (i32, i32),
+ tail_pos: Vec<(i32, i32)>,
+ ) -> Self {
+ Simulation {
+ unique_pos,
+ head_pos,
+ tail_pos,
+ }
+ }
+
+ fn update_head(&mut self, command: &Command, tail_idx: usize) {
+ match command {
+ Command::Up(amount) => {
+ for _ in 1..=*amount {
+ self.head_pos.1 += 1;
+ for i in 0..9 {
+ if !self.is_tail_one_block_away(i) {
+ self.update_tail(&self.get_direction(i), i);
+ self.unique_pos.insert(self.tail_pos[tail_idx]);
+ }
+ }
+ }
+ }
+ Command::Down(amount) => {
+ for _ in 1..=*amount {
+ self.head_pos.1 -= 1;
+ for i in 0..9 {
+ if !self.is_tail_one_block_away(i) {
+ self.update_tail(&self.get_direction(i), i);
+ self.unique_pos.insert(self.tail_pos[tail_idx]);
+ }
+ }
+ }
+ }
+ Command::Right(amount) => {
+ for _ in 1..=*amount {
+ self.head_pos.0 += 1;
+ for i in 0..9 {
+ if !self.is_tail_one_block_away(i) {
+ self.update_tail(&self.get_direction(i), i);
+ self.unique_pos.insert(self.tail_pos[tail_idx]);
+ }
+ }
+ }
+ }
+ Command::Left(amount) => {
+ for _ in 1..=*amount {
+ self.head_pos.0 -= 1;
+ for i in 0..9 {
+ if !self.is_tail_one_block_away(i) {
+ self.update_tail(&self.get_direction(i), i);
+ self.unique_pos.insert(self.tail_pos[tail_idx]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fn update_tail(&mut self, direction: &Direction, idx: usize) {
+ use Direction::*;
+ match direction {
+ Up => self.tail_pos[idx].1 += 1,
+ Down => self.tail_pos[idx].1 -= 1,
+ Right => self.tail_pos[idx].0 += 1,
+ Left => self.tail_pos[idx].0 -= 1,
+ UpRight => {
+ self.tail_pos[idx].1 += 1;
+ self.tail_pos[idx].0 += 1
+ }
+ UpLeft => {
+ self.tail_pos[idx].1 += 1;
+ self.tail_pos[idx].0 -= 1
+ }
+ DownRight => {
+ self.tail_pos[idx].1 -= 1;
+ self.tail_pos[idx].0 += 1
+ }
+ DownLeft => {
+ self.tail_pos[idx].1 -= 1;
+ self.tail_pos[idx].0 -= 1
+ }
+ NoOp => {}
+ }
+ }
+
+ fn get_pos_diff(&self, idx: usize) -> (i32, i32) {
+ match idx {
+ 0 => {
+ let dx = self.head_pos.0 - self.tail_pos[idx].0;
+ let dy = self.head_pos.1 - self.tail_pos[idx].1;
+ (dx, dy)
+ }
+ _ => {
+ let dx = self.tail_pos[idx - 1].0 - self.tail_pos[idx].0;
+ let dy = self.tail_pos[idx - 1].1 - self.tail_pos[idx].1;
+ (dx, dy)
+ }
+ }
+ }
+
+ fn is_tail_one_block_away(&self, idx: usize) -> bool {
+ match idx {
+ 0 => {
+ let dx = i32::abs(self.head_pos.0 - self.tail_pos[idx].0);
+ let dy = i32::abs(self.head_pos.1 - self.tail_pos[idx].1);
+ dx + dy + 1 < 3
+ }
+ _ => {
+ let dx = i32::abs(self.tail_pos[idx - 1].0 - self.tail_pos[idx].0);
+ let dy = i32::abs(self.tail_pos[idx - 1].1 - self.tail_pos[idx].1);
+ dx + dy + 1 < 3
+ }
+ }
+ }
+
+ fn get_direction(&self, idx: usize) -> Direction {
+ Direction::new(self.get_pos_diff(idx))
+ }
+}
+
+impl Command {
+ fn apply(&self, simulation: &mut Simulation, tail_idx: usize) {
+ simulation.update_head(self, tail_idx);
+ }
+}
+
+fn solve_part_one(data: &str) -> usize {
+ let tails = vec![(0, 0); 9];
+ let mut simulation = Simulation::new(HashSet::new(), (0, 0), tails);
+ let commands: Vec<_> = data
+ .lines()
+ .map(|x| Command::from_str(x).unwrap())
+ .collect();
+ for command in commands {
+ command.apply(&mut simulation, 0)
+ }
+ simulation.unique_pos.len() + 1
+}
+
+fn solve_part_two(data: &str) -> usize {
+ let tails = vec![(0, 0); 9];
+ let mut simulation = Simulation::new(HashSet::new(), (0, 0), tails);
+ let commands: Vec<_> = data
+ .lines()
+ .map(|x| Command::from_str(x).unwrap())
+ .collect();
+ for command in commands {
+ command.apply(&mut simulation, 8)
+ }
+ simulation.unique_pos.len()
+}
+
+fn main() {
+ let test = include_str!("../input/day9.test");
+ let test_2 = include_str!("../input/day9_2.test");
+ let prod = include_str!("../input/day9.prod");
+ println!("part1 test: {}", solve_part_one(test));
+ println!("part1 test: {}", solve_part_one(test_2));
+ println!("part1 prod: {}", solve_part_one(prod));
+ println!("part2 test: {}", solve_part_two(test));
+ println!("part2 test: {}", solve_part_two(test_2));
+ println!("part2 prod: {}", solve_part_two(prod));
+}