day 13: rust

This commit is contained in:
matthias@arch 2023-12-13 16:29:03 +01:00
parent 5fa40357cd
commit e1d2cb5f72
3 changed files with 119 additions and 0 deletions

22
13/README.md Normal file
View 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
View 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()
};
}

View File

@ -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 |
| [08](08) | Rust | 101 | 0,039 s | |
| [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