day14: rust
This commit is contained in:
parent
5dfbe7c237
commit
3d5270034b
22
14/README.md
Normal file
22
14/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# [Day 14](https://adventofcode.com/2023/day/14)
|
||||||
|
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
|
||||||
|
|
||||||
|
Today's language: **Rust**
|
||||||
|
|
||||||
|
Lines of code: **84**
|
||||||
|
|
||||||
|
Execution time: **0,171 s**
|
||||||
|
|
||||||
|
This solution uses a single function for the tilting procedure.
|
||||||
|
Different tilting directions are achieved by "remapping" `x` and `y` through captures.
|
||||||
|
|
||||||
|
For task 2, a cycle is searched by comparing the rocks after each nwse-tilt with all previous results.
|
||||||
|
After finding two equal states, only `(1.000.000.000 - cycle_start) % cycle_length` cycles have to be performed to get the correct result.
|
||||||
|
This approach requires making copies of the 2D array in a loop, which involves expensive heap allocations.
|
||||||
|
It is still pretty fast.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
rustc day14.rs
|
||||||
|
./day14
|
||||||
|
```
|
||||||
|
<!-- no bruteforce in < 90 lines -->
|
107
14/day14.rs
Normal file
107
14/day14.rs
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
type Rocks = Vec<Vec<u8>>;
|
||||||
|
|
||||||
|
// tilt so that all 'O' characters want to DECREMENT their Y index
|
||||||
|
// using custom `at` function that "remaps" x and y, this function can be used for all directions
|
||||||
|
fn tilt<F>(rocks: &mut Rocks, at: F, x_len: usize, y_len: usize)
|
||||||
|
where F: Fn(&mut Rocks, usize, usize) -> &mut u8 {
|
||||||
|
for x in 0..x_len {
|
||||||
|
let mut next_y: usize = 0; // lowest reachable position
|
||||||
|
for y in 0..y_len {
|
||||||
|
match *at(rocks, x, y) as char {
|
||||||
|
'#' => next_y = y + 1,
|
||||||
|
'O' => {
|
||||||
|
if next_y != y {
|
||||||
|
*at(rocks, x, next_y) = 'O' as u8;
|
||||||
|
*at(rocks, x, y) = '.' as u8;
|
||||||
|
}
|
||||||
|
while next_y < y_len - 1 {
|
||||||
|
next_y += 1;
|
||||||
|
if *at(rocks, x, next_y) != '#' as u8 { break }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --> y
|
||||||
|
// |
|
||||||
|
// V
|
||||||
|
// x
|
||||||
|
// West is the orientation that looks like the input
|
||||||
|
// When printing with one of these, the rocks want to roll to the left side
|
||||||
|
fn west_at(rocks: &mut Rocks, x: usize, y: usize) -> &mut u8 { &mut rocks[x][y] }
|
||||||
|
fn east_at(rocks: &mut Rocks, x: usize, y: usize) -> &mut u8 { let ylen = rocks[0].len(); &mut rocks[x][ylen - y - 1] }
|
||||||
|
fn south_at (rocks: &mut Rocks, x: usize, y: usize) -> &mut u8 { let xlen = rocks.len(); let ylen = rocks[0].len(); &mut rocks[xlen - y - 1][ylen - x - 1] }
|
||||||
|
fn north_at (rocks: &mut Rocks, x: usize, y: usize) -> &mut u8 { let ylen = rocks[0].len(); &mut rocks[y][ylen - x - 1] }
|
||||||
|
|
||||||
|
fn print<F>(rocks: &mut Rocks, at: F, x_len: usize, y_len: usize)
|
||||||
|
where F: Fn(&mut Rocks, usize, usize) -> &mut u8 {
|
||||||
|
(0..x_len).for_each(|x| { (0..y_len).for_each(|y| print!("{}", *at(rocks, x, y) as char)); println!() });
|
||||||
|
}
|
||||||
|
fn weigh<F>(rocks: &mut Rocks, at: F, x_len: usize, y_len: usize) -> usize
|
||||||
|
where F: Fn(&mut Rocks, usize, usize) -> &mut u8 {
|
||||||
|
let mut weight: usize = 0;
|
||||||
|
(0..x_len).for_each(|x| (0..y_len).for_each(|y| if *at(rocks, x, y) == 'O' as u8 { weight += y_len - y }) );
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let input = "example.txt";
|
||||||
|
let input = "input.txt";
|
||||||
|
let lines = read_lines(&input);
|
||||||
|
let mut original: Rocks = Vec::new();
|
||||||
|
for line in lines.map(|r| r.ok().unwrap()) {
|
||||||
|
original.push(line.chars().map(|c| c as u8).collect());
|
||||||
|
}
|
||||||
|
let ew_xlen = original.len();
|
||||||
|
let ew_ylen = original[0].len();
|
||||||
|
let ns_xlen = ew_ylen;
|
||||||
|
let ns_ylen = ew_xlen;
|
||||||
|
|
||||||
|
// TASK 1
|
||||||
|
let mut rocks = original.clone();
|
||||||
|
tilt(&mut rocks, north_at, ns_xlen, ns_ylen);
|
||||||
|
println!("Load on north support beams (1): {}", weigh(&mut rocks, north_at, ns_xlen, ns_ylen));
|
||||||
|
// print(&mut rocks, west_at, ew_xlen, ew_ylen);
|
||||||
|
|
||||||
|
// TASK 2
|
||||||
|
rocks = original.clone();
|
||||||
|
// find a cycle
|
||||||
|
let mut rocks_store: Vec<Rocks> = Vec::new();
|
||||||
|
let mut cycle_start: usize = 0;
|
||||||
|
let mut cycle_length: usize = 0;
|
||||||
|
for i in 0..1_000_000_000 as usize {
|
||||||
|
tilt(&mut rocks, north_at, ns_xlen, ns_ylen);
|
||||||
|
tilt(&mut rocks, west_at, ew_xlen, ew_ylen);
|
||||||
|
tilt(&mut rocks, south_at, ns_xlen, ns_ylen);
|
||||||
|
tilt(&mut rocks, east_at, ew_xlen, ew_ylen);
|
||||||
|
if let Some(j) = rocks_store.iter().position(|r| r.eq(&rocks)) {
|
||||||
|
cycle_start = j;
|
||||||
|
cycle_length = i - j;
|
||||||
|
println!("Cycle found! rocks at {} == rocks at {}", i, j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rocks_store.push(rocks.clone());
|
||||||
|
}
|
||||||
|
// do the cycles that remain after the ... Cycle
|
||||||
|
for _ in 0..(1_000_000_000 as usize - cycle_start) % cycle_length - 1 {
|
||||||
|
tilt(&mut rocks, north_at, ns_xlen, ns_ylen);
|
||||||
|
tilt(&mut rocks, west_at, ew_xlen, ew_ylen);
|
||||||
|
tilt(&mut rocks, south_at, ns_xlen, ns_ylen);
|
||||||
|
tilt(&mut rocks, east_at, ew_xlen, ew_ylen);
|
||||||
|
}
|
||||||
|
// tilt(&mut rocks, north_at, ns_xlen, ns_ylen);
|
||||||
|
println!("Load on north support beams (2): {}", weigh(&mut rocks, north_at, ns_xlen, ns_ylen));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_lines<P>(filename: P) -> io::Lines<io::BufReader<std::fs::File>>
|
||||||
|
where P: AsRef<std::path::Path>, {
|
||||||
|
return match std::fs::File::open(filename) {
|
||||||
|
Err(why) => panic!("Could not open file. {}", why),
|
||||||
|
Ok(file) => std::io::BufReader::new(file).lines()
|
||||||
|
};
|
||||||
|
}
|
@ -16,5 +16,6 @@ This is a repository for my solutions for the [advent of code 2023](https://adve
|
|||||||
| [10](10) | Rust | 136 | 0,003 s | lots of bitwise operations |
|
| [10](10) | Rust | 136 | 0,003 s | lots of bitwise operations |
|
||||||
| [11](11) | Rust | 66 | 0,005 s | |
|
| [11](11) | Rust | 66 | 0,005 s | |
|
||||||
| [13](13) | Rust | 84 | 0,002 s | binary encoding ftw |
|
| [13](13) | Rust | 84 | 0,002 s | binary encoding ftw |
|
||||||
|
| [14](14) | Rust | 84 | 0,171 s | no bruteforce in < 90 lines |
|
||||||
|
|
||||||
Lines of code are without blank lines and comments
|
Lines of code are without blank lines and comments
|
||||||
|
Loading…
Reference in New Issue
Block a user