Skip to content

Commit

Permalink
day 7
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesPatrickGill committed Dec 7, 2024
1 parent 597c59a commit 50e532a
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 4](./src/bin/04.rs) | `81.9µs` | `51.3µs` |
| [Day 5](./src/bin/05.rs) | `379.0µs` | `816.9µs` |
| [Day 6](./src/bin/06.rs) | `331.5µs` | `311.0ms` |
| [Day 7](./src/bin/07.rs) | `900.4µs` | `2.8ms` |

**Total: 313.35ms**
**Total: 317.05ms**
<!--- benchmarking table --->
9 changes: 9 additions & 0 deletions data/examples/07.txt
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/bin/06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,6 @@ mod tests {
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
assert_eq!(result, Some(6));
}
}
227 changes: 227 additions & 0 deletions src/bin/07.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
use std::collections::{HashSet, VecDeque};

use itertools::Itertools;

advent_of_code::solution!(7);

#[derive(Debug, Eq, Hash, PartialEq, Clone)]
struct Equation {
target: i64,
numbers: Vec<i64>,
}

pub fn part_one(input: &str) -> Option<i64> {
let equations = input
.lines()
.map(|line| {
let (target_str, numbers_str) = line.split_once(": ").unwrap();
let numbers: Vec<i64> = numbers_str
.split(" ")
.map(|num_str| num_str.parse().unwrap())
.collect_vec();
Equation {
numbers,
target: target_str.parse().unwrap(),
}
})
.collect_vec();

let result: i64 = equations.into_iter().fold(0, |acc, eq| {
if solve_equation(&eq).is_some() {
acc + eq.target
} else {
acc
}
});

Some(result)
}

fn solve_equation(equation: &Equation) -> Option<HashSet<VecDeque<char>>> {
let mut solutions = HashSet::new();
if equation.numbers.len() == 2 {
if equation.numbers[0] + equation.numbers[1] == equation.target {
solutions.insert(vec!['+'].into());
};

if equation.numbers[0] * equation.numbers[1] == equation.target {
solutions.insert(vec!['*'].into());
};

return if solutions.is_empty() {
None
} else {
Some(solutions)
};
}

let mut numbers_clone = equation.numbers.clone();
let last = numbers_clone.pop().unwrap();

if last < equation.target {
let add_eq_target = equation.target - last;
let add_smaller_eq = Equation {
target: add_eq_target,
numbers: numbers_clone.clone(),
};
let add_smaller_solutions = solve_equation(&add_smaller_eq);
if let Some(sols) = add_smaller_solutions {
for sol in sols {
let mut new_sol = sol.clone();
new_sol.push_back('+');
solutions.insert(new_sol);
}
}
}

if equation.target % last == 0 {
let mult_eq_target = equation.target / last;
let mult_smaller_eq = Equation {
target: mult_eq_target,
numbers: numbers_clone.clone(),
};
let mult_smaller_solutions = solve_equation(&mult_smaller_eq);
if let Some(sols) = mult_smaller_solutions {
for sol in sols {
let mut new_sol = sol.clone();
new_sol.push_back('*');
solutions.insert(new_sol);
}
};
}

if solutions.is_empty() {
None
} else {
Some(solutions)
}
}

pub fn part_two(input: &str) -> Option<i64> {
let equations = input
.lines()
.map(|line| {
let (target_str, numbers_str) = line.split_once(": ").unwrap();
let numbers: Vec<i64> = numbers_str
.split(" ")
.map(|num_str| num_str.parse().unwrap())
.collect_vec();
Equation {
numbers,
target: target_str.parse().unwrap(),
}
})
.collect_vec();

let result: i64 = equations.into_iter().fold(0, |acc, eq| {
if solve_equation_2(&eq).is_some() {
acc + eq.target
} else {
acc
}
});

Some(result)
}

fn solve_equation_2(equation: &Equation) -> Option<HashSet<VecDeque<char>>> {
let mut solutions = HashSet::new();
if equation.numbers.len() == 2 {
if equation.numbers[0] + equation.numbers[1] == equation.target {
solutions.insert(vec!['+'].into());
};

if equation.numbers[0] * equation.numbers[1] == equation.target {
solutions.insert(vec!['*'].into());
};

let concat = format!("{}{}", equation.numbers[0], equation.numbers[1])
.parse::<i64>()
.unwrap();
if concat == equation.target {
solutions.insert(vec!['|'].into());
};

return if solutions.is_empty() {
None
} else {
Some(solutions)
};
}

let mut numbers_clone = equation.numbers.clone();
let last = numbers_clone.pop().unwrap();

if last < equation.target {
let add_eq_target = equation.target - last;
let add_smaller_eq = Equation {
target: add_eq_target,
numbers: numbers_clone.clone(),
};
let add_smaller_solutions = solve_equation_2(&add_smaller_eq);
if let Some(sols) = add_smaller_solutions {
for sol in sols {
let mut new_sol = sol.clone();
new_sol.push_back('+');
solutions.insert(new_sol);
}
}
};

if equation.target % last == 0 {
let mult_eq_target = equation.target / last;
let mult_smaller_eq = Equation {
target: mult_eq_target,
numbers: numbers_clone.clone(),
};
let mult_smaller_solutions = solve_equation_2(&mult_smaller_eq);
if let Some(sols) = mult_smaller_solutions {
for sol in sols {
let mut new_sol = sol.clone();
new_sol.push_back('*');
solutions.insert(new_sol);
}
};
};

let target_as_str = equation.target.to_string();
if target_as_str.ends_with(&last.to_string()) {
let new_target = &target_as_str[..target_as_str.len() - last.to_string().len()];
if !new_target.is_empty() {
let concat_smaller_eq = Equation {
target: new_target.parse().unwrap(),
numbers: numbers_clone.clone(),
};
let concat_smaller_solutions = solve_equation_2(&concat_smaller_eq);
if let Some(sols) = concat_smaller_solutions {
for sol in sols {
let mut new_sol = sol.clone();
new_sol.push_back('|');
solutions.insert(new_sol);
}
};
};
};
if solutions.is_empty() {
None
} else {
Some(solutions)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(3749));
}

#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
}
}

0 comments on commit 50e532a

Please sign in to comment.