diff --git a/src/days/d01.rs b/src/days/d01.rs index fd0566a..3767a33 100644 --- a/src/days/d01.rs +++ b/src/days/d01.rs @@ -3,18 +3,17 @@ use std::fs; pub fn solve() { let path = "res/01/input.txt"; - let contents = fs::read_to_string(path) - .expect("Should have been able to read the file"); + let contents = fs::read_to_string(path).expect("Should have been able to read the file"); let cont_arr = contents.split("\n"); - + let mut calories = Vec::::new(); calories.push(0); let mut index = 0; cont_arr.into_iter().for_each(|i| { if i == "" { - index+=1; + index += 1; calories.push(0); } else { calories[index] += i.parse::().unwrap(); @@ -34,5 +33,5 @@ pub fn solve() { let res3: i32 = calories.clone().into_iter().rev().take(3).sum(); - println!("Result 2: {}", res3); -} \ No newline at end of file + println!("Result 2: {}", res3); +} diff --git a/src/days/d06.rs b/src/days/d06.rs index bce9227..3fb96ac 100644 --- a/src/days/d06.rs +++ b/src/days/d06.rs @@ -18,8 +18,6 @@ pub fn solve() { println!("Result 2: {}", res); } - - // Finds 1st occurence of l unique characters in chars and returns // the index of the last of them or -1 fn find_marker(l: usize, chars: &Vec) -> i32 { @@ -38,11 +36,12 @@ fn find_marker(l: usize, chars: &Vec) -> i32 { } fn _find_marker_v2(l: usize, chars: &Vec) -> usize { - chars.iter() + chars + .iter() .filter(|c| **c != '\n') .collect::>() .windows(l) .position(|window| window.iter().collect::>().len() == l) - .map(|pos| pos+l) + .map(|pos| pos + l) .unwrap() -} \ No newline at end of file +} diff --git a/src/days/d07.rs b/src/days/d07.rs index c45a109..c83703d 100644 --- a/src/days/d07.rs +++ b/src/days/d07.rs @@ -1,4 +1,4 @@ -use std::{fs, collections::HashMap}; +use std::{collections::HashMap, fs}; pub fn solve() { let path = "res/07/input.txt"; @@ -13,22 +13,28 @@ pub fn solve() { let mut path = Vec::<&str>::new(); // Put all paths into the HashMap, add sizes to all parent paths as well - cont_arr.iter() + cont_arr + .iter() .filter(|line| **line != "") // remove last line .for_each(|line| { let words = line.split(" ").collect::>(); - if line.starts_with("dir ") { } // ignore - else if line.starts_with("$ ls") { } // ignore - else if line.starts_with("$ cd ..") { // go folder up by deleting deepest folder + if line.starts_with("dir ") { + } + // ignore + else if line.starts_with("$ ls") { + } + // ignore + else if line.starts_with("$ cd ..") { + // go folder up by deleting deepest folder path.pop(); - } - else if line.starts_with("$ cd") { // add new folder to path + } else if line.starts_with("$ cd") { + // add new folder to path path.push(words[2]) - } - else { // file, add filesize to current and all parent paths + } else { + // file, add filesize to current and all parent paths let size = words[0].parse::().unwrap(); for i in 0..path.len() { - let current_path = path[0..i+1].join("/"); + let current_path = path[0..i + 1].join("/"); if paths.contains_key(¤t_path) { *paths.get_mut(¤t_path).unwrap() += size; } else { @@ -36,10 +42,11 @@ pub fn solve() { } } } - }); - + }); + // Sum of all paths lower than 100000 is result - let res = paths.iter() + let res = paths + .iter() .map(|pair| *pair.1) .filter(|size| *size <= 100000) .sum::(); @@ -51,10 +58,12 @@ pub fn solve() { let min_to_delete = 30000000 - (70000000 - space_occupied); // Find min folder size higher-or-equal to min_to_delete - let res = paths.iter() + let res = paths + .iter() .map(|pair| *pair.1) .filter(|size| *size >= min_to_delete) - .min().unwrap(); - - println!("Result 2: {}", res) -} \ No newline at end of file + .min() + .unwrap(); + + println!("Result 2: {}", res) +} diff --git a/src/days/d08.rs b/src/days/d08.rs index 4399c5a..fa3a7cb 100644 --- a/src/days/d08.rs +++ b/src/days/d08.rs @@ -8,25 +8,26 @@ pub fn solve() { let cont_arr = contents.lines().collect::>(); // parse trees as 2D i32 Vec - let trees: Vec> = cont_arr.iter() + let trees: Vec> = cont_arr + .iter() .filter(|line| **line != "") - .map(|line| - line.chars().collect::>() - .iter().map(|t| return t.to_digit(10).unwrap() as i32) - .collect() - ).collect(); + .map(|line| { + line.chars() + .collect::>() + .iter() + .map(|t| return t.to_digit(10).unwrap() as i32) + .collect() + }) + .collect(); let width = trees[0].len(); let height = trees.len(); // task 1 // initialize visibilities with 0 - let mut visibilities: Vec> = (0..height).map(|_| { - (0..width).map(|_| 0).collect() - }).collect(); - - - + let mut visibilities: Vec> = (0..height) + .map(|_| (0..width).map(|_| 0).collect()) + .collect(); // mark visible trees with 1 // left to right & right to left @@ -39,11 +40,10 @@ pub fn solve() { visibilities[i][j] = 1; last_max_left = trees[i][j]; } - if trees[i][width-j-1] > last_max_right { - visibilities[i][width-j-1] = 1; - last_max_right = trees[i][width-j-1]; - } - + if trees[i][width - j - 1] > last_max_right { + visibilities[i][width - j - 1] = 1; + last_max_right = trees[i][width - j - 1]; + } } } @@ -57,58 +57,71 @@ pub fn solve() { visibilities[j][i] = 1; last_max_top = trees[j][i]; } - if trees[width-j-1][i] > last_max_bot { - visibilities[height-j-1][i] = 1; - last_max_bot = trees[height-j-1][i]; - } - + if trees[width - j - 1][i] > last_max_bot { + visibilities[height - j - 1][i] = 1; + last_max_bot = trees[height - j - 1][i]; + } } } // sum all visible trees - let res = visibilities.iter() + let res = visibilities + .iter() .map(|line| line.iter().sum::()) .sum::(); println!("Result 1: {}", res); - // task 2 - let scenic_scores: Vec> = (0..height).map(|i| { - (0..width).map(|j| { - // calculate view range in each direction - let mut to_top = 0; - for k in (0..i).rev() { - to_top += 1; - if trees[k][j] >= trees[i][j] { break; } - } + let scenic_scores: Vec> = (0..height) + .map(|i| { + (0..width) + .map(|j| { + // calculate view range in each direction + let mut to_top = 0; + for k in (0..i).rev() { + to_top += 1; + if trees[k][j] >= trees[i][j] { + break; + } + } - let mut to_bot = 0; - for k in i+1..height { - to_bot += 1; - if trees[k][j] >= trees[i][j] { break; } - } + let mut to_bot = 0; + for k in i + 1..height { + to_bot += 1; + if trees[k][j] >= trees[i][j] { + break; + } + } - let mut to_left = 0; - for k in (0..j).rev() { - to_left += 1; - if trees[i][k] >= trees[i][j] { break; } - } + let mut to_left = 0; + for k in (0..j).rev() { + to_left += 1; + if trees[i][k] >= trees[i][j] { + break; + } + } - let mut to_right = 0; - for k in j+1..width { - to_right += 1; - if trees[i][k] >= trees[i][j] { break; } - } + let mut to_right = 0; + for k in j + 1..width { + to_right += 1; + if trees[i][k] >= trees[i][j] { + break; + } + } + + to_top * to_bot * to_left * to_right + }) + .collect() + }) + .collect(); - to_top*to_bot*to_left*to_right - }).collect() - }).collect(); - // find max scenic score - let res = scenic_scores.iter() + let res = scenic_scores + .iter() .map(|line| line.iter().max().unwrap()) - .max().unwrap(); - + .max() + .unwrap(); + println!("Result 2: {}", res) -} \ No newline at end of file +} diff --git a/src/days/d09.rs b/src/days/d09.rs index 35a07db..1243e7d 100644 --- a/src/days/d09.rs +++ b/src/days/d09.rs @@ -5,16 +5,12 @@ const GRID_HEIGHT: i32 = 1000; const START_X: i32 = 500; const START_Y: i32 = 500; - pub fn solve() { let path = "res/09/input.txt"; let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); - let lines: Vec<&str> = contents - .lines() - .filter(|line| *line != "") - .collect(); + let lines: Vec<&str> = contents.lines().filter(|line| *line != "").collect(); // task 1 - rope with 2 knots let mut rope2 = Rope::new(2); @@ -30,7 +26,7 @@ pub fn solve() { "D" => Dir::Down, "L" => Dir::Left, "R" => Dir::Right, - _ => Dir::Up + _ => Dir::Up, }; let amount = cmd[1].parse::().unwrap(); @@ -48,9 +44,6 @@ pub fn solve() { // task 2 res let res = rope10.tail_visited_num(); println!("Result 1: {}", res); - - - } #[derive(Debug, Copy, Clone)] @@ -58,13 +51,13 @@ enum Dir { Up, Down, Left, - Right + Right, } struct Rope { knots_x: Vec, knots_y: Vec, - tail_visited_grid: Vec> // [Y][X] + tail_visited_grid: Vec>, // [Y][X] } impl Rope { @@ -73,27 +66,18 @@ impl Rope { knots_x: (0..knots).map(|_| START_X).collect(), knots_y: (0..knots).map(|_| START_Y).collect(), tail_visited_grid: (0..GRID_HEIGHT) - .map(|_| (0..GRID_WIDTH) - .map(|_| false).collect() - ).collect() + .map(|_| (0..GRID_WIDTH).map(|_| false).collect()) + .collect(), } } // move head (first knot) pub fn mv(&mut self, dir: Dir) { match dir { - Dir::Up => { - self.knots_y[0] -= 1 - }, - Dir::Down => { - self.knots_y[0] += 1 - }, - Dir::Left => { - self.knots_x[0] -= 1 - }, - Dir::Right => { - self.knots_x[0] += 1 - } + Dir::Up => self.knots_y[0] -= 1, + Dir::Down => self.knots_y[0] += 1, + Dir::Left => self.knots_x[0] -= 1, + Dir::Right => self.knots_x[0] += 1, } self.check_tail_pos() } @@ -102,42 +86,49 @@ impl Rope { fn check_tail_pos(&mut self) { // check pos of each knot except first for i in 1..self.knots_x.len() { - if (self.knots_x[i-1] == self.knots_x[i] && (self.knots_y[i-1] - self.knots_y[i]).abs() == 1) - || (self.knots_y[i-1] == self.knots_y[i] && (self.knots_x[i-1] - self.knots_x[i]).abs() == 1) { + if (self.knots_x[i - 1] == self.knots_x[i] + && (self.knots_y[i - 1] - self.knots_y[i]).abs() == 1) + || (self.knots_y[i - 1] == self.knots_y[i] + && (self.knots_x[i - 1] - self.knots_x[i]).abs() == 1) + { // Knots are touching, nothing to do - } else if (self.knots_x[i-1] - self.knots_x[i]).abs() == 1 && (self.knots_y[i-1] - self.knots_y[i]).abs() == 1 { + } else if (self.knots_x[i - 1] - self.knots_x[i]).abs() == 1 + && (self.knots_y[i - 1] - self.knots_y[i]).abs() == 1 + { // Knots are touching diagonally, nothing to do } else { // Tail needs to be moved - if self.knots_x[i-1] != self.knots_x[i] && self.knots_y[i-1] != self.knots_y[i] { + if self.knots_x[i - 1] != self.knots_x[i] && self.knots_y[i - 1] != self.knots_y[i] + { // Move diagonally - self.knots_x[i] += normalize(self.knots_x[i-1] - self.knots_x[i]); - self.knots_y[i] += normalize(self.knots_y[i-1] - self.knots_y[i]); + self.knots_x[i] += normalize(self.knots_x[i - 1] - self.knots_x[i]); + self.knots_y[i] += normalize(self.knots_y[i - 1] - self.knots_y[i]); } else { // Move vertically/horizontally - if self.knots_x[i-1] == self.knots_x[i] { - self.knots_y[i] += normalize(self.knots_y[i-1] - self.knots_y[i]); + if self.knots_x[i - 1] == self.knots_x[i] { + self.knots_y[i] += normalize(self.knots_y[i - 1] - self.knots_y[i]); } else { - self.knots_x[i] += normalize(self.knots_x[i-1] - self.knots_x[i]); + self.knots_x[i] += normalize(self.knots_x[i - 1] - self.knots_x[i]); } } } } // Set current tail (last knot) pos as visited - self.tail_visited_grid[*self.knots_y.last().unwrap() as usize][*self.knots_x.last().unwrap() as usize] = true; + self.tail_visited_grid[*self.knots_y.last().unwrap() as usize] + [*self.knots_x.last().unwrap() as usize] = true; } // returns number of cells visited by tail pub fn tail_visited_num(&self) -> i32 { - self.tail_visited_grid.iter() - .map(|row| + self.tail_visited_grid + .iter() + .map(|row| { row.iter() - .map(|cell| - if *cell { 1 as i32 } - else { 0 as i32 } - ).sum::() - ).sum() + .map(|cell| if *cell { 1 as i32 } else { 0 as i32 }) + .sum::() + }) + .sum() } } @@ -149,4 +140,4 @@ fn normalize(n: i32) -> i32 { } else { 0 } -} \ No newline at end of file +} diff --git a/src/days/d10.rs b/src/days/d10.rs index 3db3ae6..03e442a 100644 --- a/src/days/d10.rs +++ b/src/days/d10.rs @@ -5,11 +5,8 @@ pub fn solve() { let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); - let lines: Vec<&str> = contents - .lines() - .filter(|line| *line != "") - .collect(); - + let lines: Vec<&str> = contents.lines().filter(|line| *line != "").collect(); + let mut reg_x = 1; let mut cycle = 0; let mut signal_strengths = Vec::::new(); @@ -24,22 +21,22 @@ pub fn solve() { // increase cycle 1 time cycle += 1; if rel_cycle(cycle) { - signal_strengths.push(cycle*reg_x); + signal_strengths.push(cycle * reg_x); } crt.push(sprite_draw(cycle, reg_x)); - }, + } "addx" => { // increase cycle 2 times (0..2).for_each(|_| { cycle += 1; if rel_cycle(cycle) { - signal_strengths.push(cycle*reg_x); + signal_strengths.push(cycle * reg_x); } crt.push(sprite_draw(cycle, reg_x)); }); // change regX according to parameter reg_x += parts[1].parse::().unwrap(); - }, + } _ => {} } }); @@ -52,21 +49,23 @@ pub fn solve() { let mut print_buffer = "".to_string(); // print the crt line by line crt.iter().enumerate().for_each(|(i, p)| { - if *p { print_buffer += "#" } - else { print_buffer += "." } + if *p { + print_buffer += "#" + } else { + print_buffer += "." + } // print buffer if a line is completed - if (i+1) % 40 == 0 { + if (i + 1) % 40 == 0 { println!("{}", print_buffer); print_buffer = "".to_string(); } }) - } // returns whether the passed cycle is a relevant one fn rel_cycle(cycle: i32) -> bool { - if (cycle-20) % 40 == 0 && cycle >= 20 { + if (cycle - 20) % 40 == 0 && cycle >= 20 { true } else { false @@ -75,5 +74,5 @@ fn rel_cycle(cycle: i32) -> bool { // returns whether the sprite is currently in a position to draw a pixel fn sprite_draw(cycle: i32, reg_x: i32) -> bool { - return ((cycle-1)%40).abs_diff(reg_x) <= 1 -} \ No newline at end of file + return ((cycle - 1) % 40).abs_diff(reg_x) <= 1; +} diff --git a/src/days/d11.rs b/src/days/d11.rs index 14e1cff..23539ed 100644 --- a/src/days/d11.rs +++ b/src/days/d11.rs @@ -5,11 +5,12 @@ pub fn solve() { let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); - let monk_strings: Vec<&str> = contents - .split("\n\n") - .collect(); + let monk_strings: Vec<&str> = contents.split("\n\n").collect(); - let mut monkeys: Vec = monk_strings.iter().map(|monkey| Monkey::new(*monkey)).collect(); + let mut monkeys: Vec = monk_strings + .iter() + .map(|monkey| Monkey::new(*monkey)) + .collect(); let mut monkeys2 = monkeys.clone(); let monkeys_num = monkeys.len(); @@ -19,7 +20,9 @@ pub fn solve() { let new_items = monkeys[i].turn(monkeys_num, |x| x / 3); // add items to correct monkeys (0..monkeys_num).for_each(|i| { - new_items[i].iter().for_each(|item| monkeys[i].items.push(*item)) + new_items[i] + .iter() + .for_each(|item| monkeys[i].items.push(*item)) }); }) }); @@ -29,7 +32,6 @@ pub fn solve() { println!("Result 1: {res}"); - (0..10000).for_each(|_| { (0..monkeys_num).for_each(|i| { // get changed items, modulo them with common divider of divisible by tests @@ -37,7 +39,9 @@ pub fn solve() { let new_items = monkeys2[i].turn(monkeys_num, |x| x % common_divider); // add items to correct monkeys (0..monkeys_num).for_each(|i| { - new_items[i].iter().for_each(|item| monkeys2[i].items.push(*item)) + new_items[i] + .iter() + .for_each(|item| monkeys2[i].items.push(*item)) }); }) }); @@ -46,14 +50,12 @@ pub fn solve() { let res = monkeys2[0].inspections * monkeys2[1].inspections; println!("Result 2: {res}"); - - } #[derive(Debug, PartialEq, Clone)] enum Operation { Mult, - Add + Add, } #[derive(Debug, Clone)] @@ -78,54 +80,57 @@ impl Monkey { test_divisible_by: 0, monkey_if_true: 0, monkey_if_false: 0, - inspections: 0 + inspections: 0, }; - input.split("\n").filter(|line| *line != "").for_each(|line| { - let (ident, val) = line.split_at(line.find(":").unwrap()); - match ident { - " Starting items" => { - // remove whitespace and beginning, split by , - let val = val.replace(":","").replace(" ", ""); - monkey.items = val - .split(",") - .collect::>() - .iter() - .map(|i| (*i).parse::().unwrap()) - .collect() - }, - " Operation" => { - // parse operator, parse last word as number - let val = val.replace(": new = old ", ""); - let (op, num) = val.split_at(val.find(" ").unwrap()); - match op { - "+" => monkey.operation_type = Operation::Add, - "*" => monkey.operation_type = Operation::Mult, - _ => {} + input + .split("\n") + .filter(|line| *line != "") + .for_each(|line| { + let (ident, val) = line.split_at(line.find(":").unwrap()); + match ident { + " Starting items" => { + // remove whitespace and beginning, split by , + let val = val.replace(":", "").replace(" ", ""); + monkey.items = val + .split(",") + .collect::>() + .iter() + .map(|i| (*i).parse::().unwrap()) + .collect() } - if num == " old" { - monkey.operation_quad = true - } else { - monkey.operation_num = num.trim().parse::().unwrap(); + " Operation" => { + // parse operator, parse last word as number + let val = val.replace(": new = old ", ""); + let (op, num) = val.split_at(val.find(" ").unwrap()); + match op { + "+" => monkey.operation_type = Operation::Add, + "*" => monkey.operation_type = Operation::Mult, + _ => {} + } + if num == " old" { + monkey.operation_quad = true + } else { + monkey.operation_num = num.trim().parse::().unwrap(); + } } - }, - " Test" => { - // parse last word as number - let words: Vec<&str> = val.split(" ").collect(); - monkey.test_divisible_by = words.last().unwrap().parse::().unwrap(); - }, - " If true" => { - // parse last word as number - let words: Vec<&str> = val.split(" ").collect(); - monkey.monkey_if_true = words.last().unwrap().parse::().unwrap(); - }, - " If false" => { - // parse last word as number - let words: Vec<&str> = val.split(" ").collect(); - monkey.monkey_if_false = words.last().unwrap().parse::().unwrap(); - }, - _ => {} - } - }); + " Test" => { + // parse last word as number + let words: Vec<&str> = val.split(" ").collect(); + monkey.test_divisible_by = words.last().unwrap().parse::().unwrap(); + } + " If true" => { + // parse last word as number + let words: Vec<&str> = val.split(" ").collect(); + monkey.monkey_if_true = words.last().unwrap().parse::().unwrap(); + } + " If false" => { + // parse last word as number + let words: Vec<&str> = val.split(" ").collect(); + monkey.monkey_if_false = words.last().unwrap().parse::().unwrap(); + } + _ => {} + } + }); monkey } @@ -158,4 +163,4 @@ impl Monkey { items } -} \ No newline at end of file +} diff --git a/src/days/d12.rs b/src/days/d12.rs index c2650f9..05beb02 100644 --- a/src/days/d12.rs +++ b/src/days/d12.rs @@ -1,60 +1,72 @@ -use std::{fs, collections::{HashMap, HashSet}}; +use std::{ + collections::{HashMap, HashSet}, + fs, +}; pub fn solve() { let path = "res/12/input.txt"; let contents = fs::read_to_string(path).expect("I/O error, wrong path?"); - let lines: Vec<&str> = contents - .lines() - .collect(); + let lines: Vec<&str> = contents.lines().collect(); // Build grid let mut start = (0, 0); let mut end = (0, 0); - let grid: Vec> = lines.iter().enumerate().map(|(y, line)| { - line.chars().enumerate().map(|(x, c)| - match c { - 'S' => { - start = (x as u32, y as u32); - return char_to_numeric('a') - - }, - 'E' => { - end = (x as u32, y as u32); - return char_to_numeric('z') - }, - _ => { - return char_to_numeric(c) - } - }).collect() - }).collect(); + let grid: Vec> = lines + .iter() + .enumerate() + .map(|(y, line)| { + line.chars() + .enumerate() + .map(|(x, c)| match c { + 'S' => { + start = (x as u32, y as u32); + return char_to_numeric('a'); + } + 'E' => { + end = (x as u32, y as u32); + return char_to_numeric('z'); + } + _ => return char_to_numeric(c), + }) + .collect() + }) + .collect(); // Build adjacent lists - let mut adjacents = HashMap::<(u32,u32),Vec<(u32,u32)>>::new(); + let mut adjacents = HashMap::<(u32, u32), Vec<(u32, u32)>>::new(); - grid.iter() - .enumerate() - .for_each(|(y, line)| { - line.iter() - .enumerate() - .for_each(|(x, height)| { - adjacents.insert((x as u32, y as u32), Vec::<(u32,u32)>::new()); + grid.iter().enumerate().for_each(|(y, line)| { + line.iter().enumerate().for_each(|(x, height)| { + adjacents.insert((x as u32, y as u32), Vec::<(u32, u32)>::new()); // top - if y != 0 && grid[y-1][x] <= height+1 { - adjacents.get_mut(&(x as u32, y as u32)).unwrap().push((x as u32, (y-1) as u32)) + if y != 0 && grid[y - 1][x] <= height + 1 { + adjacents + .get_mut(&(x as u32, y as u32)) + .unwrap() + .push((x as u32, (y - 1) as u32)) } // bot - if y != grid.len()-1 && grid[y+1][x] <= height+1 { - adjacents.get_mut(&(x as u32, y as u32)).unwrap().push((x as u32, (y+1) as u32)) + if y != grid.len() - 1 && grid[y + 1][x] <= height + 1 { + adjacents + .get_mut(&(x as u32, y as u32)) + .unwrap() + .push((x as u32, (y + 1) as u32)) } //left - if x != 0 && grid[y][x-1] <= height+1 { - adjacents.get_mut(&(x as u32, y as u32)).unwrap().push(((x-1) as u32, y as u32)) + if x != 0 && grid[y][x - 1] <= height + 1 { + adjacents + .get_mut(&(x as u32, y as u32)) + .unwrap() + .push(((x - 1) as u32, y as u32)) } // right - if x != grid[0].len()-1 && grid[y][x+1] <= height+1 { - adjacents.get_mut(&(x as u32, y as u32)).unwrap().push(((x+1) as u32, y as u32)) + if x != grid[0].len() - 1 && grid[y][x + 1] <= height + 1 { + adjacents + .get_mut(&(x as u32, y as u32)) + .unwrap() + .push(((x + 1) as u32, y as u32)) } }) }); @@ -66,26 +78,16 @@ pub fn solve() { // task 2 - find min distance for each node with height 1, select min let mut distances = Vec::::new(); - grid.iter() - .enumerate() - .for_each(|(y, line)| { - line.iter() - .enumerate() - .for_each(|(x, height)| { + grid.iter().enumerate().for_each(|(y, line)| { + line.iter().enumerate().for_each(|(x, height)| { if *height == 1 { - distances.push( - bfs((x as u32, y as u32), end, &adjacents) - ) + distances.push(bfs((x as u32, y as u32), end, &adjacents)) } }) }); - let res = *distances.iter() - .filter(|dist| **dist != -1) - .min() - .unwrap(); - - println!("Result 2: {res}") + let res = *distances.iter().filter(|dist| **dist != -1).min().unwrap(); + println!("Result 2: {res}") } // Maps lowercase chars to 1..=26 @@ -94,10 +96,14 @@ fn char_to_numeric(c: char) -> u32 { } // Runs a Breadth-first search on the given graph and returns the minimal steps necessary to reach end from start, -1 if not reachable -fn bfs(start: (u32,u32), end: (u32,u32), adjacents: &HashMap<(u32,u32),Vec<(u32,u32)>>) -> i32 { - let mut queue = Vec::<(u32,u32)>::new(); - let mut seen_nodes = HashSet::<(u32,u32)>::new(); - let mut predecessor = HashMap::<(u32,u32),(u32,u32)>::new(); +fn bfs( + start: (u32, u32), + end: (u32, u32), + adjacents: &HashMap<(u32, u32), Vec<(u32, u32)>>, +) -> i32 { + let mut queue = Vec::<(u32, u32)>::new(); + let mut seen_nodes = HashSet::<(u32, u32)>::new(); + let mut predecessor = HashMap::<(u32, u32), (u32, u32)>::new(); queue.push(start); seen_nodes.insert(start); while !queue.is_empty() { @@ -105,15 +111,13 @@ fn bfs(start: (u32,u32), end: (u32,u32), adjacents: &HashMap<(u32,u32),Vec<(u32, if node == end { break; } - adjacents.get(&node).unwrap() - .iter() - .for_each(|child| { - if !seen_nodes.contains(child) { - queue.push(*child); - seen_nodes.insert(*child); - predecessor.insert(*child, node); - } - }) + adjacents.get(&node).unwrap().iter().for_each(|child| { + if !seen_nodes.contains(child) { + queue.push(*child); + seen_nodes.insert(*child); + predecessor.insert(*child, node); + } + }) } // if end is reachable, it now is in predecessor let mut res = 0; // steps @@ -121,10 +125,10 @@ fn bfs(start: (u32,u32), end: (u32,u32), adjacents: &HashMap<(u32,u32),Vec<(u32, while node != start { node = match predecessor.get(&node) { Some(n) => *n, - None => return -1 // return -1 if end not reachable + None => return -1, // return -1 if end not reachable }; res += 1; } res -} \ No newline at end of file +} diff --git a/src/days/d13.rs b/src/days/d13.rs index 2967d84..40d0113 100644 --- a/src/days/d13.rs +++ b/src/days/d13.rs @@ -1,5 +1,5 @@ -use std::{fs, cmp::Ordering}; use serde_json::Value; +use std::{cmp::Ordering, fs}; pub fn solve() { let path = "res/13/input.txt"; @@ -11,7 +11,7 @@ pub fn solve() { .split("\n\n") .map(|pair| pair.split_at(pair.find("\n").unwrap())) .collect(); - + let mut right_order_indices = Vec::::new(); pairs.iter().enumerate().for_each(|(i, pair)| { let json1: Value = serde_json::from_str(pair.0).unwrap(); @@ -23,7 +23,7 @@ pub fn solve() { // println!("Pair {}: {res:?}\n", i+1); if res != Ordered::No { - right_order_indices.push((i+1) as u32); + right_order_indices.push((i + 1) as u32); } }); @@ -36,17 +36,16 @@ pub fn solve() { .filter(|line| *line != "") .map(|line| serde_json::from_str(line).unwrap()) .collect(); - + // add [[2]] and [[6]] as divider packets packets.push(serde_json::from_str("[[6]]").unwrap()); packets.push(serde_json::from_str("[[2]]").unwrap()); // sort by compare function using is_right_order - packets.sort_by(|a, b| - match is_right_order((a, b)) { - Ordered::Yes => Ordering::Less, - Ordered::Maybe => Ordering::Equal, - Ordered::No => Ordering::Greater + packets.sort_by(|a, b| match is_right_order((a, b)) { + Ordered::Yes => Ordering::Less, + Ordered::Maybe => Ordering::Equal, + Ordered::No => Ordering::Greater, }); // find [[2]] and [[6]] indices @@ -58,16 +57,15 @@ pub fn solve() { if v[0].is_array() && v[0].as_array().unwrap().len() == 1 { let v = v[0].as_array().unwrap(); if v[0].is_number() && v[0].as_u64().unwrap() == 2 { - i2 = i+1 - } - else if v[0].is_number() && v[0].as_u64().unwrap() == 6 { - i6 = i+1 + i2 = i + 1 + } else if v[0].is_number() && v[0].as_u64().unwrap() == 6 { + i6 = i + 1 } } } }); - - let res = i2*i6; + + let res = i2 * i6; println!("Result 2: {res}"); } @@ -76,37 +74,37 @@ pub fn solve() { enum Ordered { Yes, Maybe, - No + No, } // returns whether the passed Values are in the right order // with Ordered enum option fn is_right_order(values: (&Value, &Value)) -> Ordered { //println!("Compare {} vs {}", values.0, values.1); - + // both values numbers if values.0.is_number() && values.1.is_number() { let v0 = values.0.as_u64().unwrap(); let v1 = values.1.as_u64().unwrap(); // wrong order if right is higher than left if v0 < v1 { - return Ordered::Yes + return Ordered::Yes; } else if v0 == v1 { - return Ordered::Maybe + return Ordered::Maybe; } else { - return Ordered::No + return Ordered::No; } - } + } // left number, right array else if values.0.is_number() && values.1.is_array() { // wrap number into arr, then compare again - let left = Value::Array(vec!(values.0.clone())); + let left = Value::Array(vec![values.0.clone()]); return is_right_order((&left, &values.1)); } // left array, right number else if values.0.is_array() && values.1.is_number() { // wrap number into arr, then compare again - let right = Value::Array(vec!(values.1.clone())); + let right = Value::Array(vec![values.1.clone()]); return is_right_order((&values.0, &right)); } // both array @@ -123,17 +121,17 @@ fn is_right_order(values: (&Value, &Value)) -> Ordered { // left smaller, counts as ordered if left.is_none() && right.is_some() { - return Ordered::Yes + return Ordered::Yes; } // right smaller, counts as unordered if left.is_some() && right.is_none() { - return Ordered::No + return Ordered::No; } // both have same length, doesn't say anything about ordering if left.is_none() && right.is_none() { - return Ordered::Maybe + return Ordered::Maybe; } let left = left.unwrap(); @@ -142,10 +140,10 @@ fn is_right_order(values: (&Value, &Value)) -> Ordered { // only go into next iteration if not definitely yes or no let res = is_right_order((&left, &right)); if res != Ordered::Maybe { - return res + return res; } } } Ordered::Yes -} \ No newline at end of file +} diff --git a/src/days/d14.rs b/src/days/d14.rs index dffd073..f8ea443 100644 --- a/src/days/d14.rs +++ b/src/days/d14.rs @@ -3,7 +3,7 @@ use std::fs; const CAVE_WIDTH: u32 = 400; const CAVE_HEIGHT: u32 = 200; const X_OFFSET: u32 = 300; -const START_POINT: (u32,u32) = (500,0); +const START_POINT: (u32, u32) = (500, 0); pub fn solve() { let path = "res/14/input.txt"; @@ -18,18 +18,23 @@ pub fn solve() { line.split(" -> ") .map(|coord| { let coord_arr: Vec<&str> = coord.split(",").collect(); - (coord_arr[0].parse::().unwrap(), - coord_arr[1].parse::().unwrap()) - }).collect() - }).collect(); - + ( + coord_arr[0].parse::().unwrap(), + coord_arr[1].parse::().unwrap(), + ) + }) + .collect() + }) + .collect(); + // cave[X][Y] - let mut cave: Vec> = (0..CAVE_WIDTH).map(|_| (0..CAVE_HEIGHT).map(|_| false).collect()).collect(); + let mut cave: Vec> = (0..CAVE_WIDTH) + .map(|_| (0..CAVE_HEIGHT).map(|_| false).collect()) + .collect(); // set cave path structure rock_paths.iter().for_each(|path| { - path.windows(2) - .for_each(|pairs| { + path.windows(2).for_each(|pairs| { // draw rock lines let x_iter = if pairs[0].0 > pairs[1].0 { pairs[1].0..=pairs[0].0 @@ -43,19 +48,17 @@ pub fn solve() { pairs[0].1..=pairs[1].1 }; y_iter.for_each(|y| { - cave[(x-X_OFFSET) as usize][y as usize] = true; + cave[(x - X_OFFSET) as usize][y as usize] = true; }) }); - }) }); - // task 1 - normal cave // let sand fall let mut sand_unit_counter: u32 = 0; let mut sand_pos = next_sand_pos(&cave); - while sand_pos.1 < CAVE_HEIGHT-1 { + while sand_pos.1 < CAVE_HEIGHT - 1 { cave[sand_pos.0 as usize][sand_pos.1 as usize] = true; sand_pos = next_sand_pos(&cave); sand_unit_counter += 1; @@ -63,49 +66,43 @@ pub fn solve() { println!("Result 1: {sand_unit_counter}"); - // task 2 - cave with ground // find ground - cave height is 2 + max y value let cave_height = 2 + rock_paths .iter() - .map(|line| - line - .iter() - .map(|r| r.1) - .max() - .unwrap() - ) + .map(|line| line.iter().map(|r| r.1).max().unwrap()) .max() .unwrap(); // build ground - cave.iter_mut().for_each(|col| { - col[(cave_height) as usize] = true - }); + cave.iter_mut() + .for_each(|col| col[(cave_height) as usize] = true); // let sand fall again, until it reaches the start point - while sand_pos != (START_POINT.0-X_OFFSET, START_POINT.1) { + while sand_pos != (START_POINT.0 - X_OFFSET, START_POINT.1) { cave[sand_pos.0 as usize][sand_pos.1 as usize] = true; sand_pos = next_sand_pos(&cave); sand_unit_counter += 1; } - println!("Result 2: {sand_unit_counter}"); + println!("Result 2: {sand_unit_counter}"); } // returns the next position a sand unit will come to rest at fn next_sand_pos(cave: &Vec>) -> (u32, u32) { - let start_pos = (START_POINT.0-X_OFFSET, START_POINT.1); + let start_pos = (START_POINT.0 - X_OFFSET, START_POINT.1); let mut pos: (u32, u32) = start_pos; while !is_end_pos(pos, cave) { // first check directly below - if !cave[(pos.0) as usize][(pos.1+1) as usize] { - pos = (pos.0, pos.1+1) - } // then diagonally down-left - else if !cave[(pos.0-1) as usize][(pos.1+1) as usize] { - pos = (pos.0-1, pos.1+1) - } // then diagonally down-right - else if !cave[(pos.0+1) as usize][(pos.1+1) as usize] { - pos = (pos.0+1, pos.1+1) + if !cave[(pos.0) as usize][(pos.1 + 1) as usize] { + pos = (pos.0, pos.1 + 1) + } + // then diagonally down-left + else if !cave[(pos.0 - 1) as usize][(pos.1 + 1) as usize] { + pos = (pos.0 - 1, pos.1 + 1) + } + // then diagonally down-right + else if !cave[(pos.0 + 1) as usize][(pos.1 + 1) as usize] { + pos = (pos.0 + 1, pos.1 + 1) } } @@ -114,15 +111,16 @@ fn next_sand_pos(cave: &Vec>) -> (u32, u32) { // returns whether the passed coordinates are a valid end position for a sand unit fn is_end_pos(pos: (u32, u32), cave: &Vec>) -> bool { - if pos.1 as usize == cave[0].len()-1 { + if pos.1 as usize == cave[0].len() - 1 { // pos is on ground of the cave, lays still - return true + return true; } // don't need to check for enough space to left+right since cave is big enough - if cave[(pos.0-1) as usize][(pos.1+1) as usize] - && cave[(pos.0) as usize][(pos.1+1) as usize] - && cave[(pos.0+1) as usize][(pos.1+1) as usize] { - return true + if cave[(pos.0 - 1) as usize][(pos.1 + 1) as usize] + && cave[(pos.0) as usize][(pos.1 + 1) as usize] + && cave[(pos.0 + 1) as usize][(pos.1 + 1) as usize] + { + return true; } false @@ -132,12 +130,10 @@ fn is_end_pos(pos: (u32, u32), cave: &Vec>) -> bool { fn _print_cave(cave: &Vec>) { let mut out: Vec = (0..CAVE_HEIGHT).map(|_| "".to_string()).collect(); cave.iter().for_each(|line| { - line.iter().enumerate().for_each(|(i, cell)| - match *cell { - true => out[i] += "#", - false => out[i] += "." - } - ); + line.iter().enumerate().for_each(|(i, cell)| match *cell { + true => out[i] += "#", + false => out[i] += ".", + }); }); out.iter().for_each(|s| println!("{s}")); -} \ No newline at end of file +} diff --git a/src/days/d15.rs b/src/days/d15.rs new file mode 100644 index 0000000..68ed73c --- /dev/null +++ b/src/days/d15.rs @@ -0,0 +1,9 @@ +use std::fs; + +pub fn solve() { + let path = "res/15/input.txt"; + + let contents = fs::read_to_string(path).expect("File read error"); + + +} diff --git a/src/main.rs b/src/main.rs index 1fafc25..7910a3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ pub mod days; fn main() { - days::d14::solve() + days::d15::solve() //_all_days() } @@ -32,4 +32,8 @@ fn _all_days() { days::d12::solve(); println!("\nDay 13"); days::d13::solve(); + println!("\nDay 14"); + days::d14::solve(); + println!("\nDay 15"); + days::d14::solve(); }