diff --git a/13/README.md b/13/README.md new file mode 100644 index 0000000..db46866 --- /dev/null +++ b/13/README.md @@ -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 +``` + + diff --git a/13/day13.rs b/13/day13.rs new file mode 100644 index 0000000..1703c29 --- /dev/null +++ b/13/day13.rs @@ -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, has_smack: bool) -> Option { + 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, vertical: &Vec, 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 = Vec::new(); + let mut vertical: Vec = 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

(filename: P) -> io::Lines> +where P: AsRef, { + return match std::fs::File::open(filename) { + Err(why) => panic!("Could not open file. {}", why), + Ok(file) => std::io::BufReader::new(file).lines() + }; +} + diff --git a/README.md b/README.md index 08fd4e3..afaa9dc 100644 --- a/README.md +++ b/README.md @@ -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