A input/day7/example => input/day7/example +9 -0
@@ 0,0 1,9 @@
+190: 10 19
+3267: 81 40 27
+83: 17 5
+156: 15 6
+7290: 6 8 6 15
+161011: 16 10 13
+192: 17 8 14
+21037: 9 7 18 13
+292: 11 6 16 20
A src/day7/mod.rs => src/day7/mod.rs +184 -0
@@ 0,0 1,184 @@
+use std::{
+ fs::File,
+ io::{BufRead, BufReader},
+ path::Path,
+ str::FromStr,
+};
+
+pub fn solve(input: &Path) -> anyhow::Result<()> {
+ println!("part one: {}", part_one(input)?);
+ println!("part two: {}", part_two(input)?);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Equation {
+ answer: u64,
+ inputs: Vec<u64>,
+}
+
+impl FromStr for Equation {
+ type Err = Box<dyn std::error::Error>;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut parts = s.split(":");
+
+ Ok(Equation {
+ answer: parts.next().unwrap().parse()?,
+ inputs: parts
+ .next()
+ .unwrap()
+ .split_whitespace()
+ .map(|n| -> u64 { n.parse().unwrap() })
+ .collect(),
+ })
+ }
+}
+
+fn part_one(input: &Path) -> anyhow::Result<u64> {
+ let reader = BufReader::new(File::open(input)?);
+
+ let mut equations = vec![];
+ for line in reader.lines() {
+ equations.push(Equation::from_str(&line?).unwrap());
+ }
+
+ Ok(equations
+ .iter()
+ .filter(|eq| check_equation_one(eq))
+ .map(|eq| eq.answer)
+ .collect::<Vec<u64>>()
+ .iter()
+ .sum())
+}
+
+fn check_equation_one(eq: &Equation) -> bool {
+ let positions = eq.inputs.len() - 1;
+
+ if positions == 1 {
+ if eq.inputs[0] + eq.inputs[1] == eq.answer {
+ return true;
+ }
+ if eq.inputs[0] * eq.inputs[1] == eq.answer {
+ return true;
+ }
+ return false;
+ }
+
+ let operators = ["+", "*"];
+
+ let combinations: Vec<String> = (operators.len()..positions).fold(
+ operators
+ .iter()
+ .flat_map(|c| operators.iter().map(move |&d| d.to_owned() + *c))
+ .collect(),
+ |a, _| {
+ a.into_iter()
+ .flat_map(|c| operators.iter().map(move |&d| d.to_owned() + &*c))
+ .collect()
+ },
+ );
+
+ for combination in combinations {
+ let combination: Vec<char> = combination.chars().collect();
+ let mut current: Option<u64> = None;
+ for (i, input) in eq.inputs.iter().enumerate() {
+ if current.is_none() {
+ current = Some(*input);
+ continue;
+ }
+
+ match combination[i - 1] {
+ '+' => current = Some(current.unwrap() + input),
+ '*' => current = Some(current.unwrap() * input),
+ _ => panic!(),
+ }
+ }
+ if current.unwrap() == eq.answer {
+ return true;
+ }
+ }
+
+ false
+}
+
+fn part_two(input: &Path) -> anyhow::Result<u64> {
+ let reader = BufReader::new(File::open(input)?);
+
+ let mut equations = vec![];
+ for line in reader.lines() {
+ equations.push(Equation::from_str(&line?).unwrap());
+ }
+
+ Ok(equations
+ .iter()
+ .filter(|eq| check_equation_two(eq))
+ .map(|eq| eq.answer)
+ .collect::<Vec<u64>>()
+ .iter()
+ .sum())
+}
+
+fn check_equation_two(eq: &Equation) -> bool {
+ let positions = eq.inputs.len() - 1;
+
+ if positions == 1 {
+ if eq.inputs[0] + eq.inputs[1] == eq.answer {
+ return true;
+ }
+ if eq.inputs[0] * eq.inputs[1] == eq.answer {
+ return true;
+ }
+ if (eq.inputs[0].to_string() + &eq.inputs[1].to_string())
+ .parse::<u64>()
+ .unwrap()
+ == eq.answer
+ {
+ return true;
+ }
+ return false;
+ }
+
+ let operators = ["+", "*", "|"];
+
+ let combinations: Vec<String> = (operators.len()..positions + 1).fold(
+ operators
+ .iter()
+ .flat_map(|c| operators.iter().map(move |&d| d.to_owned() + *c))
+ .collect(),
+ |a, _| {
+ a.into_iter()
+ .flat_map(|c| operators.iter().map(move |&d| d.to_owned() + &*c))
+ .collect()
+ },
+ );
+
+ for combination in combinations {
+ let combination: Vec<char> = combination.chars().collect();
+ let mut current: Option<u64> = None;
+ for (i, input) in eq.inputs.iter().enumerate() {
+ if current.is_none() {
+ current = Some(*input);
+ continue;
+ }
+
+ match combination[i - 1] {
+ '+' => current = Some(current.unwrap() + input),
+ '*' => current = Some(current.unwrap() * input),
+ '|' => {
+ current = Some(
+ (current.unwrap().to_string() + &input.to_string())
+ .parse()
+ .unwrap(),
+ )
+ }
+ _ => panic!(),
+ }
+ }
+ if current.unwrap() == eq.answer {
+ return true;
+ }
+ }
+
+ false
+}
M src/main.rs => src/main.rs +8 -0
@@ 12,6 12,7 @@ mod day3;
mod day4;
mod day5;
mod day6;
+mod day7;
#[derive(Parser)]
struct Args {
@@ 45,6 46,10 @@ enum DayArgs {
#[arg(short)]
input: PathBuf,
},
+ Day7 {
+ #[arg(short)]
+ input: PathBuf,
+ },
}
fn main() -> anyhow::Result<()> {
@@ 69,6 74,9 @@ fn main() -> anyhow::Result<()> {
DayArgs::Day6 { input } => {
day6::solve(&input)?;
}
+ DayArgs::Day7 { input } => {
+ day7::solve(&input)?;
+ }
}
Ok(())