Day seven
This commit is contained in:
1
day-07-rust/.gitignore
vendored
Normal file
1
day-07-rust/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
target/
|
||||||
7
day-07-rust/Cargo.lock
generated
Normal file
7
day-07-rust/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day-07-rust"
|
||||||
|
version = "0.1.0"
|
||||||
6
day-07-rust/Cargo.toml
Normal file
6
day-07-rust/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day-07-rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
2
day-07-rust/rust-toolchain.toml
Normal file
2
day-07-rust/rust-toolchain.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
35
day-07-rust/src/common.rs
Normal file
35
day-07-rust/src/common.rs
Normal 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
20
day-07-rust/src/main.rs
Normal 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
44
day-07-rust/src/task1.rs
Normal 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
53
day-07-rust/src/task2.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user