This commit is contained in:
JonOfUs 2022-12-20 17:35:25 +01:00
parent 69a51e6299
commit c9808224ec
7 changed files with 5254 additions and 113 deletions

5000
res/20/input.txt Normal file

File diff suppressed because it is too large Load diff

7
res/20/test-input.txt Normal file
View file

@ -0,0 +1,7 @@
1
2
-3
3
-2
0
4

View file

@ -14,7 +14,7 @@ pub fn solve() {
vec![(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)], vec![(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)],
vec![(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)], vec![(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)],
vec![(0, 0), (1, 0), (2, 0), (3, 0)], vec![(0, 0), (1, 0), (2, 0), (3, 0)],
vec![(0,0),(0,1),(1,0),(1,1)] vec![(0, 0), (0, 1), (1, 0), (1, 1)],
]; ];
let directions: Vec<Dir> = contents let directions: Vec<Dir> = contents
@ -36,7 +36,6 @@ pub fn solve() {
let mut heights = Vec::<i64>::new(); let mut heights = Vec::<i64>::new();
/* /*
51 rocks 51 rocks
@ -47,14 +46,11 @@ pub fn solve() {
% %
*/ */
for i in 0..2344 { for i in 0..2344 {
// spawn new rock // spawn new rock
let r_index = i as usize % rocks.len(); // get current rock index let r_index = i as usize % rocks.len(); // get current rock index
let mut rock = Rock::new(&rocks[r_index], highest_rock); let mut rock = Rock::new(&rocks[r_index], highest_rock);
while chamber.iter().filter(|row| !row.contains(&true)).count() < 7 { while chamber.iter().filter(|row| !row.contains(&true)).count() < 7 {
chamber.push(vec![false; WIDTH]) chamber.push(vec![false; WIDTH])
} }
@ -63,7 +59,7 @@ pub fn solve() {
// move to left or right // move to left or right
let next_dir = dir_iter.next(); let next_dir = dir_iter.next();
let dir = match next_dir { let dir = match next_dir {
Some(x) => { x }, Some(x) => x,
None => { None => {
dir_iter = directions.iter(); dir_iter = directions.iter();
dir_iter.next().unwrap() dir_iter.next().unwrap()
@ -75,7 +71,7 @@ pub fn solve() {
if rock.left().valid_pos(&chamber) { if rock.left().valid_pos(&chamber) {
rock = rock.left() rock = rock.left()
} }
}, }
Dir::Right => { Dir::Right => {
if rock.right().valid_pos(&chamber) { if rock.right().valid_pos(&chamber) {
rock = rock.right() rock = rock.right()
@ -86,16 +82,17 @@ pub fn solve() {
if rock.down().valid_pos(&chamber) { if rock.down().valid_pos(&chamber) {
rock = rock.down(); rock = rock.down();
} else { } else {
rock.pos.iter().for_each(|coord| { rock.pos
chamber[coord.0 as usize][coord.1 as usize] = true .iter()
}); .for_each(|coord| chamber[coord.0 as usize][coord.1 as usize] = true);
highest_rock = match chamber highest_rock = match chamber
.iter() .iter()
.enumerate() .enumerate()
.filter(|row| row.1.contains(&true)) .filter(|row| row.1.contains(&true))
.last() { .last()
{
Some(x) => x.0 as i64, Some(x) => x.0 as i64,
None => -1 None => -1,
}; };
// find recurring patterns in amount of rocks and height // find recurring patterns in amount of rocks and height
heights.push(highest_rock); heights.push(highest_rock);
@ -111,22 +108,33 @@ pub fn solve() {
fn _test(n: usize, heights: &Vec<i64>) { fn _test(n: usize, heights: &Vec<i64>) {
if heights.len() % n == 0 if heights.len() % n == 0
&& heights[heights.len()/n-1]*n as i64+n as i64 == heights[heights.len()-1]+1 { && heights[heights.len() / n - 1] * n as i64 + n as i64 == heights[heights.len() - 1] + 1
{
println!("{}: {}", n, heights.len() / n) println!("{}: {}", n, heights.len() / n)
} }
} }
fn _print_chamber(chamber: &Vec<Vec<bool>>, curr_rock: &Rock) { fn _print_chamber(chamber: &Vec<Vec<bool>>, curr_rock: &Rock) {
let mut str_chamber: Vec<Vec<char>> = chamber.iter().map(|line| line.iter().map(|elem| let mut str_chamber: Vec<Vec<char>> = chamber
match *elem { .iter()
.map(|line| {
line.iter()
.map(|elem| match *elem {
true => '#', true => '#',
false => '.' false => '.',
} })
).collect()).collect(); .collect()
})
.collect();
curr_rock.pos.iter().for_each(|pos| { str_chamber[pos.0 as usize][pos.1 as usize] = '@'; }); curr_rock.pos.iter().for_each(|pos| {
str_chamber[pos.0 as usize][pos.1 as usize] = '@';
});
str_chamber.iter().rev().for_each(|str| println!("{}",str.iter().collect::<String>())) str_chamber
.iter()
.rev()
.for_each(|str| println!("{}", str.iter().collect::<String>()))
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -137,7 +145,7 @@ enum Dir {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Rock { struct Rock {
pos: Vec<(i64,i64)> pos: Vec<(i64, i64)>,
} }
impl Rock { impl Rock {
@ -145,7 +153,10 @@ impl Rock {
let pos: Vec<(i64, i64)> = rock let pos: Vec<(i64, i64)> = rock
.iter() .iter()
.map(|coord| { .map(|coord| {
(coord.0 as i64 + (highest_rock + 4) as i64, coord.1 as i64 + 2) (
coord.0 as i64 + (highest_rock + 4) as i64,
coord.1 as i64 + 2,
)
}) })
.collect(); .collect();
Rock { pos } Rock { pos }
@ -154,44 +165,56 @@ impl Rock {
pub fn right(&self) -> Self { pub fn right(&self) -> Self {
for coord in self.pos.iter() { for coord in self.pos.iter() {
if coord.1 >= (WIDTH - 1) as i64 { if coord.1 >= (WIDTH - 1) as i64 {
return self.clone() return self.clone();
} }
} }
Rock { Rock {
pos: self.pos.iter().map(|coord| { pos: self
.pos
.iter()
.map(|coord| {
(coord.0, coord.1 + 1) // move right, only check for wall ! (coord.0, coord.1 + 1) // move right, only check for wall !
}).collect() })
.collect(),
} }
} }
pub fn left(&self) -> Self { pub fn left(&self) -> Self {
for coord in self.pos.iter() { for coord in self.pos.iter() {
if coord.1 <= 0 { if coord.1 <= 0 {
return self.clone() return self.clone();
} }
} }
Rock { Rock {
pos: self.pos.iter().map(|coord| { pos: self
.pos
.iter()
.map(|coord| {
(coord.0, coord.1 - 1) // move left, only check for wall ! (coord.0, coord.1 - 1) // move left, only check for wall !
}).collect() })
.collect(),
} }
} }
pub fn down(&self) -> Self { pub fn down(&self) -> Self {
Rock { Rock {
pos: self.pos.iter().map(|coord| { pos: self
.pos
.iter()
.map(|coord| {
(coord.0 - 1, coord.1) // move down (coord.0 - 1, coord.1) // move down
}).collect() })
.collect(),
} }
} }
pub fn valid_pos(&self, chamber: &Vec<Vec<bool>>) -> bool { pub fn valid_pos(&self, chamber: &Vec<Vec<bool>>) -> bool {
for coord in &self.pos { for coord in &self.pos {
if coord.0 < 0 || coord.1 < 0 { if coord.0 < 0 || coord.1 < 0 {
return false return false;
} }
if chamber[coord.0 as usize][coord.1 as usize] { if chamber[coord.0 as usize][coord.1 as usize] {
return false return false;
} }
} }

View file

@ -1,4 +1,7 @@
use std::{fs, collections::{HashMap, HashSet, VecDeque}}; use std::{
collections::{HashMap, HashSet, VecDeque},
fs,
};
pub fn solve() { pub fn solve() {
let path = "res/18/input.txt"; let path = "res/18/input.txt";
@ -13,18 +16,14 @@ pub fn solve() {
( (
vals[0].parse::<usize>().unwrap(), vals[0].parse::<usize>().unwrap(),
vals[1].parse::<usize>().unwrap(), vals[1].parse::<usize>().unwrap(),
vals[2].parse::<usize>().unwrap() vals[2].parse::<usize>().unwrap(),
) )
}) })
.collect(); .collect();
let max: usize = coords let max: usize = coords
.iter() .iter()
.map(|coord| .map(|coord| coord.0.max(coord.1.max(coord.2)))
coord.0.max(
coord.1.max(coord.2)
)
)
.max() .max()
.unwrap(); .unwrap();
@ -47,7 +46,9 @@ pub fn solve() {
// x-1 // x-1
if x == 0 || !world[x - 1][y][z] { if x == 0 || !world[x - 1][y][z] {
surfaces += 1; surfaces += 1;
if x != 0 { insert_or_increase((x-1,y,z), &mut surface_blocks) } if x != 0 {
insert_or_increase((x - 1, y, z), &mut surface_blocks)
}
} }
// x+1 // x+1
if !world[x + 1][y][z] { if !world[x + 1][y][z] {
@ -57,7 +58,9 @@ pub fn solve() {
// y-1 // y-1
if y == 0 || !world[x][y - 1][z] { if y == 0 || !world[x][y - 1][z] {
surfaces += 1; surfaces += 1;
if y != 0 { insert_or_increase((x,y-1,z), &mut surface_blocks) } if y != 0 {
insert_or_increase((x, y - 1, z), &mut surface_blocks)
}
} }
// y+1 // y+1
if !world[x][y + 1][z] { if !world[x][y + 1][z] {
@ -67,7 +70,9 @@ pub fn solve() {
// z-1 // z-1
if z == 0 || !world[x][y][z - 1] { if z == 0 || !world[x][y][z - 1] {
surfaces += 1; surfaces += 1;
if z != 0 { insert_or_increase((x,y,z-1), &mut surface_blocks) } if z != 0 {
insert_or_increase((x, y, z - 1), &mut surface_blocks)
}
} }
// z+1 // z+1
if !world[x][y][z + 1] { if !world[x][y][z + 1] {
@ -87,10 +92,9 @@ pub fn solve() {
} }
println!("Result 2: {surfaces}"); println!("Result 2: {surfaces}");
} }
fn insert_or_increase(p: (usize,usize,usize), map: &mut HashMap::<(usize,usize,usize), usize>) { fn insert_or_increase(p: (usize, usize, usize), map: &mut HashMap<(usize, usize, usize), usize>) {
if map.contains_key(&p) { if map.contains_key(&p) {
*map.get_mut(&p).unwrap() += 1; *map.get_mut(&p).unwrap() += 1;
} else { } else {
@ -98,7 +102,11 @@ fn insert_or_increase(p: (usize,usize,usize), map: &mut HashMap::<(usize,usize,u
} }
} }
fn bfs_reachable(s: (usize, usize, usize), e: (usize, usize, usize), world: &Vec<Vec<Vec<bool>>>) -> bool { fn bfs_reachable(
s: (usize, usize, usize),
e: (usize, usize, usize),
world: &Vec<Vec<Vec<bool>>>,
) -> bool {
let mut queue = VecDeque::<(usize, usize, usize)>::new(); let mut queue = VecDeque::<(usize, usize, usize)>::new();
let mut seen_nodes = HashSet::<(usize, usize, usize)>::new(); let mut seen_nodes = HashSet::<(usize, usize, usize)>::new();
@ -121,7 +129,10 @@ fn bfs_reachable(s: (usize, usize, usize), e: (usize, usize, usize), world: &Vec
false false
} }
fn get_adjacents(p: (usize, usize, usize), world: &Vec<Vec<Vec<bool>>>) -> Vec<(usize,usize,usize)> { fn get_adjacents(
p: (usize, usize, usize),
world: &Vec<Vec<Vec<bool>>>,
) -> Vec<(usize, usize, usize)> {
let mut adj = Vec::<(usize, usize, usize)>::new(); let mut adj = Vec::<(usize, usize, usize)>::new();
let (x, y, z) = p; let (x, y, z) = p;

View file

@ -1,16 +1,17 @@
use std::{fs, collections::{HashMap, HashSet, VecDeque}}; use std::fs;
use scan_fmt::scan_fmt; use scan_fmt::scan_fmt;
#[allow(dead_code)]
const MINUTES: u32 = 24; const MINUTES: u32 = 24;
#[allow(dead_code)]
pub fn solve() { pub fn solve() {
let path = "res/19/input.txt"; let path = "res/19/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?");
// parse blueprints // parse blueprints
let blueprints: Vec<Blueprint> = contents let _blueprints: Vec<Blueprint> = contents
.lines() .lines()
.filter(|line| *line != "") .filter(|line| *line != "")
.map(|line| { .map(|line| {
@ -30,11 +31,9 @@ pub fn solve() {
}) })
.collect(); .collect();
} }
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
struct Blueprint { struct Blueprint {
id: u32, id: u32,
@ -44,12 +43,11 @@ struct Blueprint {
geode_bot: (u32, u32), // (ore, obsidian) geode_bot: (u32, u32), // (ore, obsidian)
} }
#[allow(dead_code)]
impl Blueprint { impl Blueprint {
pub fn quality_level(&self) -> u32 { pub fn quality_level(&self) -> u32 {
// TODO dynamic programming? // TODO dynamic programming?
return self.id * 1; // TODO largest number of geodes that can be opened return self.id * 1; // TODO largest number of geodes that can be opened
} }
} }

102
src/days/d20.rs Normal file
View file

@ -0,0 +1,102 @@
use std::fs;
const DECRYPTION_KEY: i64 = 811_589_153;
pub fn solve() {
let path = "res/20/input.txt";
let contents = fs::read_to_string(path).expect("I/O error, wrong path?");
let initial_arrangement: Vec<i64> = contents
.lines()
.filter(|line| *line != "")
.map(|line| line.parse::<i64>().unwrap())
.collect();
let size = initial_arrangement.len();
// list of indices
let mut work_arrangement: Vec<usize> = initial_arrangement
.iter()
.enumerate()
.map(|(i, _)| i)
.collect();
for (i, &n) in initial_arrangement.iter().enumerate() {
// position in current state
let work_i = work_arrangement.iter().position(|&elem| elem == i).unwrap();
mv(work_i, n, &mut work_arrangement);
//println!("{}\n", work_arrangement.iter().map(|i| initial_arrangement[*i].to_string()).collect::<Vec::<String>>().join(", "));
}
let offset = work_arrangement
.iter()
.position(|i| initial_arrangement[*i] == 0)
.unwrap();
let coord_1 = initial_arrangement[work_arrangement[(1000 + offset) % size]];
let coord_2 = initial_arrangement[work_arrangement[(2000 + offset) % size]];
let coord_3 = initial_arrangement[work_arrangement[(3000 + offset) % size]];
println!("Result 1: {}", coord_1 + coord_2 + coord_3);
// task 2
let decrypted_arrangement: Vec<i64> = initial_arrangement
.iter()
.map(|i| i * DECRYPTION_KEY)
.collect();
// list of indices
let mut work_arrangement: Vec<usize> = decrypted_arrangement
.iter()
.enumerate()
.map(|(i, _)| i)
.collect();
// do the whole thing 10x
for _ in 0..10 {
for (i, &n) in decrypted_arrangement.iter().enumerate() {
// position in current state
let work_i = work_arrangement.iter().position(|&elem| elem == i).unwrap();
mv(work_i, n, &mut work_arrangement);
//println!("{}\n", work_arrangement.iter().map(|i| decrypted_arrangement[*i].to_string()).collect::<Vec::<String>>().join(", "));
}
}
let offset = work_arrangement
.iter()
.position(|i| initial_arrangement[*i] == 0)
.unwrap();
let coord_1 = decrypted_arrangement[work_arrangement[(1000 + offset) % size]];
let coord_2 = decrypted_arrangement[work_arrangement[(2000 + offset) % size]];
let coord_3 = decrypted_arrangement[work_arrangement[(3000 + offset) % size]];
println!("Result 2: {}", coord_1 + coord_2 + coord_3);
}
fn mv(pos: usize, move_by: i64, arr: &mut Vec<usize>) {
// reduce move_by to modulo
let move_by = if move_by < 0 {
(move_by.abs() % (arr.len() as i64 - 1)) * -1
} else {
move_by % (arr.len() as i64 - 1)
};
let move_by = if pos as i64 + move_by <= 0 {
move_by + arr.len() as i64 - 1
} else if pos as i64 + move_by >= arr.len() as i64 - 1 {
move_by - arr.len() as i64 + 1
} else {
move_by
};
let mut curr_pos = pos;
let change = if move_by < 0 { -1 } else { 1 };
for _ in 0..move_by.abs() {
let other_pos = ((curr_pos + arr.len()) as i64 + change) as usize % arr.len();
let val = arr[curr_pos];
arr[curr_pos] = arr[other_pos];
arr[other_pos] = val;
curr_pos = other_pos;
}
}

View file

@ -1,7 +1,7 @@
pub mod days; pub mod days;
fn main() { fn main() {
days::d19::solve() days::d20::solve()
//_all_days() //_all_days()
} }