day 13: rust
This commit is contained in:
parent
5fa40357cd
commit
e1d2cb5f72
22
13/README.md
Normal file
22
13/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# [Day 13](https://adventofcode.com/2023/day/13)
|
||||||
|
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
|
||||||
|
|
||||||
|
Today's language: **Rust**
|
||||||
|
|
||||||
|
Lines of code: **84**
|
||||||
|
|
||||||
|
Execution time: **0,002 s**
|
||||||
|
|
||||||
|
Once again, binary encoding is used to transform every line and every column of each pattern into one unsigned int.
|
||||||
|
The columns and lines are stored in one vector each. This means the same function can be used to find the reflection axis for both.
|
||||||
|
|
||||||
|
For task 2, we don't check whether two lines are equal, but whether they differ by 0 or 1 bit.
|
||||||
|
|
||||||
|
This approach is super fast since it has 0 heap allocations in loops and comparing two ints is way faster than comparing two strings.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
rustc day13.rs
|
||||||
|
./day13RUN
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- binary encoding ftw -->
|
94
13/day13.rs
Normal file
94
13/day13.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
|
||||||
|
fn get_diff_bits_count(a: u32, b: u32) -> usize { // return 0 if equal, 1 if 1 bit is different, else 2
|
||||||
|
let diff = a ^ b;
|
||||||
|
if diff == 0 { return 0 }
|
||||||
|
if (diff & diff.overflowing_sub(1).0) == 0 { return 1 }
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_reflection_axis(pattern: &Vec<u32>, has_smack: bool) -> Option<usize> {
|
||||||
|
for i in 1..pattern.len() {
|
||||||
|
let mut found_smack = false;
|
||||||
|
let diff = get_diff_bits_count(pattern[i-1], pattern[i]);
|
||||||
|
if has_smack && diff == 1 {
|
||||||
|
found_smack = true;
|
||||||
|
}
|
||||||
|
if diff == 0 || found_smack { // find two identical neighbors (or differing by 1 for task 2
|
||||||
|
let mut matching = true;
|
||||||
|
for j in 1..i.min(pattern.len() - i) { // check top and bottom if equal (or diff by 1 bit if has_smack)
|
||||||
|
let diff = get_diff_bits_count(pattern[i-1-j], pattern[i+j]);
|
||||||
|
if diff == 0 { continue; }
|
||||||
|
if has_smack && diff == 1 && !found_smack { // allow only one smack
|
||||||
|
found_smack = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
matching = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if matching && (!has_smack || (has_smack && found_smack)) { // require smack for task 2
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_task(horizontal: &Vec<u32>, vertical: &Vec<u32>, has_smack: bool) -> usize {
|
||||||
|
let mut mirror_sum: usize = 0;
|
||||||
|
if let Some(x) = find_reflection_axis(&horizontal, has_smack) {
|
||||||
|
mirror_sum += x * 100;
|
||||||
|
}
|
||||||
|
if let Some(x) = find_reflection_axis(&vertical, has_smack) {
|
||||||
|
mirror_sum += x;
|
||||||
|
}
|
||||||
|
return mirror_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let input = "example.txt";
|
||||||
|
let input = "input.txt";
|
||||||
|
let lines = read_lines(&input);
|
||||||
|
let mut horizontal: Vec<u32> = Vec::new();
|
||||||
|
let mut vertical: Vec<u32> = Vec::new();
|
||||||
|
horizontal.reserve(20);
|
||||||
|
vertical.reserve(20);
|
||||||
|
let mut mirror_sum1: usize = 0;
|
||||||
|
let mut mirror_sum2: usize = 0;
|
||||||
|
let convert = |c| -> u32 { if c == '#' { 1 } else { 0 } };
|
||||||
|
for line in lines.map(|r| r.ok().unwrap()) {
|
||||||
|
if line.len() == 0 {
|
||||||
|
if horizontal.len() != 0 { // skip first time
|
||||||
|
mirror_sum1 += do_task(&horizontal, &vertical, false);
|
||||||
|
mirror_sum2 += do_task(&horizontal, &vertical, true);
|
||||||
|
}
|
||||||
|
horizontal.clear();
|
||||||
|
vertical.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if horizontal.len() == 0 { // 0 for each column
|
||||||
|
(0..line.len()).for_each(|_| vertical.push(0));
|
||||||
|
}
|
||||||
|
horizontal.push(0);
|
||||||
|
for (i, n) in line.chars().map(|c| convert(c)).enumerate() {
|
||||||
|
*horizontal.last_mut().unwrap() |= (n << i);
|
||||||
|
vertical[i] |= (n << (horizontal.len()-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mirror_sum1 += do_task(&horizontal, &vertical, false);
|
||||||
|
mirror_sum2 += do_task(&horizontal, &vertical, true);
|
||||||
|
println!("Sum: (1): {}", mirror_sum1);
|
||||||
|
println!("Sum: (2): {}", mirror_sum2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -13,5 +13,8 @@ This is a repository for my solutions for the [advent of code 2023](https://adve
|
|||||||
| [07](07) | Rust | 210 | 0,007 s | not pretty, but pretty fast |
|
| [07](07) | Rust | 210 | 0,007 s | not pretty, but pretty fast |
|
||||||
| [08](08) | Rust | 101 | 0,039 s | |
|
| [08](08) | Rust | 101 | 0,039 s | |
|
||||||
| [09](09) | Rust | 88 | 0,003 s | implemented triangle datatype |
|
| [09](09) | Rust | 88 | 0,003 s | implemented triangle datatype |
|
||||||
|
| [10](10) | Rust | 136 | 0,003 s | lots of bitwise operations |
|
||||||
|
| [11](11) | Rust | 66 | 0,005 s | |
|
||||||
|
| [13](13) | Rust | 84 | 0,002 s | binary encoding ftw |
|
||||||
|
|
||||||
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