diff --git a/.gitea/workflows/build_and_run.yml b/.gitea/workflows/build_and_run.yml index b050cac..c898a80 100644 --- a/.gitea/workflows/build_and_run.yml +++ b/.gitea/workflows/build_and_run.yml @@ -11,7 +11,7 @@ jobs: name: Challenge for day strategy: matrix: - day_number: [1, 2, 3, 4, 5, 6] + day_number: [1, 2, 3, 4, 5, 6, 7] runs-on: rust-bookworm steps: - name: Check out repository code diff --git a/day7/Cargo.toml b/day7/Cargo.toml new file mode 100644 index 0000000..c71629c --- /dev/null +++ b/day7/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day7" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day7/src/main.rs b/day7/src/main.rs new file mode 100644 index 0000000..4669d97 --- /dev/null +++ b/day7/src/main.rs @@ -0,0 +1,100 @@ +use std::{env, fs}; + +fn read_input(path: &str) -> String { + fs::read_to_string(path).expect("Cannot read file.") +} + +fn add(a: u64, b: u64) -> u64 { + a + b +} + +fn mul(a: u64, b: u64) -> u64 { + a * b +} + +fn concat(a: u64, b: u64) -> u64 { + format!("{a}{b}").parse().unwrap() +} + +fn parse_input(input: &str) -> Vec<(u64, Vec)> { + input + .lines() + .filter(|line| !line.is_empty()) + .map(|line| { + let split_line = line.split_once(": ").unwrap(); + ( + split_line.0.parse().unwrap(), + split_line + .1 + .split_whitespace() + .map(|s| s.parse().unwrap()) + .rev() + .collect(), + ) + }) + .collect() +} + +fn is_valid(data: &mut Vec, acc: u64, target: u64, operators: &Vec<&fn(u64, u64) -> u64>) -> bool { + if data.is_empty() { + return target == acc; + } + + if acc > target { + return false; + } + + let old = data.pop().unwrap(); + for operator in operators { + if is_valid(data, operator(acc, old), target, operators) { + return true; + } + } + data.push(old); + false +} + +fn sum_valid(calibration_data: &Vec<(u64, Vec)>, operators: &Vec<&fn(u64, u64) -> u64>) -> u64 { + let mut sum_valid = 0; + let calibration_data = calibration_data.clone(); + + for calibration in calibration_data { + let mut x = calibration.1; + let acc = x.pop().unwrap(); + if is_valid(&mut x, acc, calibration.0, operators) { + sum_valid += calibration.0; + } + } + + sum_valid +} + +fn part_1(input: &Vec<(u64, Vec)>) -> u64 { + let valid_operators = vec![ + &(add as fn(u64, u64) -> u64), + &(mul as fn(u64, u64) -> u64) + ]; + + sum_valid(input, &valid_operators) +} + +fn part_2(input: &Vec<(u64, Vec)>) -> u64 { + let valid_operators = vec![ + &(add as fn(u64, u64) -> u64), + &(mul as fn(u64, u64) -> u64), + &(concat as fn(u64, u64) -> u64) + ]; + + sum_valid(input, &valid_operators) +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let calibration_data = parse_input(&input); + println!("[{}]", &arg); + println!("\t[Part 1] => Answer is '{}'.", part_1(&calibration_data)); + println!("\t[Part 2] => Answer is '{}'.", part_2(&calibration_data)); + } +}