From 48c6f5db008436f248e1865fd918202b0ab8fc13 Mon Sep 17 00:00:00 2001 From: Siphalor Date: Wed, 4 Dec 2024 22:18:21 +0100 Subject: [PATCH] Day four --- day-04-rust/.gitignore | 1 + day-04-rust/Cargo.lock | 7 ++ day-04-rust/Cargo.toml | 6 ++ day-04-rust/rust-toolchain.toml | 2 + day-04-rust/src/main.rs | 22 +++++++ day-04-rust/src/task1.rs | 109 ++++++++++++++++++++++++++++++++ day-04-rust/src/task2.rs | 39 ++++++++++++ 7 files changed, 186 insertions(+) create mode 100644 day-04-rust/.gitignore create mode 100644 day-04-rust/Cargo.lock create mode 100644 day-04-rust/Cargo.toml create mode 100644 day-04-rust/rust-toolchain.toml create mode 100644 day-04-rust/src/main.rs create mode 100644 day-04-rust/src/task1.rs create mode 100644 day-04-rust/src/task2.rs diff --git a/day-04-rust/.gitignore b/day-04-rust/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/day-04-rust/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/day-04-rust/Cargo.lock b/day-04-rust/Cargo.lock new file mode 100644 index 0000000..19aba27 --- /dev/null +++ b/day-04-rust/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day-04-rust" +version = "0.1.0" diff --git a/day-04-rust/Cargo.toml b/day-04-rust/Cargo.toml new file mode 100644 index 0000000..8d26b6c --- /dev/null +++ b/day-04-rust/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day-04-rust" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day-04-rust/rust-toolchain.toml b/day-04-rust/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/day-04-rust/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/day-04-rust/src/main.rs b/day-04-rust/src/main.rs new file mode 100644 index 0000000..99b4b6e --- /dev/null +++ b/day-04-rust/src/main.rs @@ -0,0 +1,22 @@ +#![feature(let_chains)] + +mod task1; +mod task2; + +fn main() { + let args = std::env::args().collect::>(); + if args.len() != 3 { + eprintln!("Usage: {} <1|2> ", args[0]); + std::process::exit(1); + } + + match args[1].as_str() { + "1" => { + task1::run(&*std::fs::read_to_string(&args[2]).expect("Failed to read from input")) + } + "2" => { + task2::run(&*std::fs::read_to_string(&args[2]).expect("Failed to read from input")) + } + _ => eprintln!("Unknown task {}", args[1]), + } +} diff --git a/day-04-rust/src/task1.rs b/day-04-rust/src/task1.rs new file mode 100644 index 0000000..137d1e2 --- /dev/null +++ b/day-04-rust/src/task1.rs @@ -0,0 +1,109 @@ +type Number = i32; + +pub fn run(input: &str) { + let lines = input.split('\n').collect::>(); + + + let mut max_column: Number = 0; + + let mut occurrences = 0; + for line in &lines { + max_column = max_column.max(line.len() as Number); + + let mut index = 0; + while let Some(match_index) = line[index..].find("XMAS") { + occurrences += 1; + index += match_index + 4; + } + index = 0; + while let Some(match_index) = line[index..].find("SAMX") { + occurrences += 1; + index += match_index + 4; + } + } + println!("After horizontal: {}", occurrences); + + { + let mut buffer = String::with_capacity(5); + for column in 0..max_column { + buffer.clear(); + + for line in &lines { + if perform_buffer_action(&mut buffer, line.chars().nth(column as usize)) { + occurrences += 1; + } + } + } + } + println!("After vertical: {}", occurrences); + + let max_line: Number = lines.len() as Number; + { + let mut buffer = String::with_capacity(5); + let mut r_buffer = String::with_capacity(5); + for start in 0..max_line { + buffer.clear(); + r_buffer.clear(); + + for i in 0..(max_line - start) { + if perform_buffer_action( + &mut buffer, + lines.get((start + i) as usize) + .and_then(|line| line.chars().nth(i as usize)) + ) { + occurrences += 1; + } + if perform_buffer_action ( + &mut r_buffer, + lines.get((start + i) as usize) + .and_then(|line| line.chars().nth((max_column - i - 1) as usize)) + ) { + occurrences += 1; + } + } + } + println!("After diagonal line starting: {}", occurrences); + + for start in 1..max_line { + buffer.clear(); + r_buffer.clear(); + + for i in 0..(max_column - start) { + if perform_buffer_action( + &mut buffer, + lines.get(i as usize) + .and_then(|line| line.chars().nth((start + i) as usize)) + ) { + occurrences += 1; + } + if perform_buffer_action( + &mut r_buffer, + lines.get(i as usize) + .and_then(|line| line.chars().nth((max_column - start - 1 - i) as usize)) + ) { + occurrences += 1; + } + } + } + println!("After diagonal column starting: {}", occurrences); + } + + println!("Result: {}", occurrences); +} + +fn perform_buffer_action(buffer: &mut String, char: Option) -> bool { + if let Some(ch) = char { + buffer.push(ch); + if buffer.len() > 4 { + buffer.remove(0); + } + if buffer == "XMAS" { + return true; + } else if buffer == "SAMX" { + return true; + } + } else { + buffer.clear(); + } + false +} diff --git a/day-04-rust/src/task2.rs b/day-04-rust/src/task2.rs new file mode 100644 index 0000000..0e6950e --- /dev/null +++ b/day-04-rust/src/task2.rs @@ -0,0 +1,39 @@ +pub fn run(input: &str) { + let lines = input + .split('\n') + .map(|line| line.chars().collect::>()) + .filter(|chars| !chars.is_empty()) + .collect::>(); + + if lines.is_empty() { + return; + } + let cols = lines[0].len(); + if lines.iter().any(|line| line.len() != cols) { + eprintln!("Invalid line length detected"); + return; + } + + let mut occurrences = 0; + for l in 1..(lines.len() - 1) { + for c in 1..(lines[l].len() - 1) { + let mid = lines[l][c]; + if mid != 'A' { + continue; + } + let top_left = lines[l - 1][c - 1]; + let top_right = lines[l - 1][c + 1]; + let bottom_left = lines[l + 1][c - 1]; + let bottom_right = lines[l + 1][c + 1]; + if ((top_left == 'M' && bottom_right == 'S') + || (top_left == 'S' && bottom_right == 'M')) + && ((top_right == 'M' && bottom_left == 'S') + || (top_right == 'S' && bottom_left == 'M')) + { + occurrences += 1; + } + } + } + + println!("X-MASes: {}", occurrences); +}