Skip to main content

aoc/year2015/
day15.rs

1//! # Science for Hungry People
2//!
3//! Brute force solution trying every possible combination of ingredients. The loop conditions are
4//! calculated so that the ingredients always sum to 100. Solves part one and two simultaneously.
5//!
6//! As an optimization we check halfway through the loops to see if any ingredient will never be
7//! greater than zero to skip large numbers of combinations.
8use std::array::from_fn;
9
10use crate::util::iter::*;
11use crate::util::parse::*;
12
13type Ingredient = [i32; 5];
14type Input = (i32, i32);
15
16pub fn parse(input: &str) -> Input {
17    let recipe: Vec<Ingredient> = input.iter_signed().chunk::<5>().collect();
18    let mut part_one = 0;
19    let mut part_two = 0;
20
21    for a in 0..101 {
22        let first: Ingredient = from_fn(|i| a * recipe[0][i]);
23
24        'outer: for b in 0..(101 - a) {
25            let second: Ingredient = from_fn(|i| first[i] + b * recipe[1][i]);
26
27            // Check if any ingredient can never be greater than zero.
28            // This makes the entire score zero, so we can skip.
29            for ((x, y), z) in second.iter().zip(recipe[2]).zip(recipe[3]).take(4) {
30                if x + y.max(z) * (100 - a - b) <= 0 {
31                    continue 'outer;
32                }
33            }
34
35            for c in 0..(101 - a - b) {
36                let d = 100 - a - b - c;
37                let third: Ingredient = from_fn(|i| second[i] + c * recipe[2][i]);
38                let fourth: Ingredient = from_fn(|i| third[i] + d * recipe[3][i]);
39
40                let score: i32 = fourth[..4].iter().map(|&x| x.max(0)).product();
41                let calories = fourth[4];
42
43                part_one = part_one.max(score);
44                if calories == 500 {
45                    part_two = part_two.max(score);
46                }
47            }
48        }
49    }
50
51    (part_one, part_two)
52}
53
54pub fn part1(input: &Input) -> i32 {
55    input.0
56}
57
58pub fn part2(input: &Input) -> i32 {
59    input.1
60}