Day seven

This commit is contained in:
2024-12-07 11:46:54 +01:00
parent 80b3a907bc
commit 79e5c9069e
8 changed files with 168 additions and 0 deletions

35
day-07-rust/src/common.rs Normal file
View File

@@ -0,0 +1,35 @@
use std::io::{Bytes, Read};
use std::iter::Peekable;
pub type Number = i64;
pub fn read_input_line<R: Read>(mut input: &mut Peekable<Bytes<R>>) -> Option<(Number, Vec<Number>)> {
let result = read_number(&mut input);
let mut parts = Vec::<Number>::with_capacity(20);
while let Some(Ok(ch)) = input.peek() {
match ch {
b'0'..=b'9' => parts.push(read_number(&mut input)),
b'\n' => {
input.next();
break
}
_ => {
input.next();
}
}
}
if parts.is_empty() {
None
} else {
Some((result, parts))
}
}
pub fn read_number<R: Read>(input: &mut Peekable<Bytes<R>>) -> Number {
let mut number: Number = 0;
while let Some(Ok(b'0'..=b'9')) = input.peek() {
number *= 10;
number += (input.next().unwrap().unwrap() - b'0') as Number;
}
number
}

20
day-07-rust/src/main.rs Normal file
View File

@@ -0,0 +1,20 @@
#![feature(let_chains)]
mod task1;
mod common;
mod task2;
fn main() {
let args = std::env::args().collect::<Vec<String>>();
if args.len() != 3 {
eprintln!("Usage: {} <1|2> <input file>", args[0]);
std::process::exit(1);
}
match args[1].as_str() {
"1" => task1::run(std::fs::File::open(&args[2]).expect("Failed to open input file")),
"2" => task2::run(std::fs::File::open(&args[2]).expect("Failed to open input file")),
_ => eprintln!("Unknown task: {}", args[1]),
}
}

44
day-07-rust/src/task1.rs Normal file
View File

@@ -0,0 +1,44 @@
use crate::common;
use crate::common::Number;
use std::io::{BufReader, Read};
use std::ops::Rem;
pub(crate) fn run<R: Read>(read: R) {
let mut reader = BufReader::new(read).bytes().peekable();
let mut total = 0;
while let Some((result, parts)) = common::read_input_line(&mut reader) {
if let Some(ops) = brute(result, &parts) {
println!("{:?} & {:?} => {}", ops, parts, result);
total += result;
}
}
println!("Result: {}", total);
}
fn brute(result: Number, parts: &[Number]) -> Option<Vec<char>> {
match parts.split_last() {
None => None,
Some((last, [])) => {
if result == *last {
Some(vec![])
} else {
None
}
}
Some((cur, parts)) => {
let test_result = result - cur;
if let Some(mut ops) = brute(test_result, parts) {
ops.push('+');
return Some(ops);
}
let test_result = result / cur;
if result.rem(cur) == 0 && let Some(mut ops) = brute(test_result, parts) {
ops.push('*');
return Some(ops);
}
None
}
}
}

53
day-07-rust/src/task2.rs Normal file
View File

@@ -0,0 +1,53 @@
use crate::common;
use crate::common::Number;
use std::io::{BufReader, Read};
use std::ops::Rem;
pub(crate) fn run<R: Read>(read: R) {
let mut reader = BufReader::new(read).bytes().peekable();
let mut total = 0;
while let Some((result, parts)) = common::read_input_line(&mut reader) {
if let Some(ops) = brute(result, &parts) {
println!("{:?} & {:?} => {}", ops, parts, result);
total += result;
}
}
println!("Result: {}", total);
}
fn brute(result: Number, parts: &[Number]) -> Option<Vec<char>> {
match parts.split_last() {
None => None,
Some((last, [])) => {
if result == *last {
Some(vec![])
} else {
None
}
}
Some((cur, parts)) => {
let test_result = result - cur;
if let Some(mut ops) = brute(test_result, parts) {
ops.push('+');
return Some(ops);
}
let test_result = result / cur;
if result.rem(cur) == 0 && let Some(mut ops) = brute(test_result, parts) {
ops.push('*');
return Some(ops);
}
let cur_str = cur.to_string();
let result_str = result.to_string();
if result_str.ends_with(cur_str.as_str()) {
let test_result = &result_str[..result_str.len() - cur_str.len()];
if !test_result.is_empty() && let Some(mut ops) = brute(test_result.parse().unwrap(), parts) {
ops.push('|');
return Some(ops);
}
}
None
}
}
}