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