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