1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! # Mirage Maintenance
//!
//! We can solve this problem using
//! [binomial coefficients](https://en.wikipedia.org/wiki/Binomial_coefficient).
//!
//! For example consider an sequence of 3 arbitrary values:
//!
//! ```none
//!    1st:  a        b         c
//!    2nd:    b - a     c - b
//!    3rd:      c - 2b + a
//!
//!    Part 1: (c - 2b + a) + (c - b) + (c) = a - 3b + 3c
//!    Part 2: a - (b - a) + (c - 2b + a) = 3a - 3b + c
//! ```
//!
//! Looking at the coefficient of each value:
//!
//! ```none
//!     Part 1: [1, -3, 3]
//!     Part 2: [3, -3, 1]
//! ```
//!
//! Doing this for values of a few different lengths:
//!
//! ```none
//!    Part 1: [-1, 4, -6, 4]
//!    Part 2: [4, -6, 4, -1]
//!
//!    Part 1: [1, -5, 10, -10, 5]
//!    Part 2: [5, -10, 10, -5, 1]
//!
//!    Part 1: [-1, 6, -15, 20, -15, 6]
//!    Part 2: [6, -15, 20, -15, 6, -1]
//! ```
//!
//! Let `n` be the number of values and `k` the index of each value. The coefficient for each value
//! is `(n k)` if `k` is even or `-(n k)` if `k` is odd. For part one we then flip the sign of the
//! sum when `n` is odd.
use crate::util::parse::*;

type Input = (i64, i64);

pub fn parse(input: &str) -> Input {
    // Determine how many numbers are on each row. Assume each row has the same amount.
    let (prefix, _) = input.split_once('\n').unwrap();
    let row = prefix.iter_signed::<i64>().count() as i64;

    // Calculate [Pascal's Triangle](https://en.wikipedia.org/wiki/Pascal%27s_triangle)
    // for the required row, flipping the sign on each second coefficient.
    let mut coefficient = 1;
    let mut triangle = vec![1];

    for i in 0..row {
        coefficient = (coefficient * (i - row)) / (i + 1);
        triangle.push(coefficient);
    }

    // Use adjusted binomial coefficients to calculate answers for each row.
    let mut part_one = 0;
    let mut part_two = 0;

    for line in input.lines() {
        for (k, value) in line.iter_signed::<i64>().enumerate() {
            part_one += value * triangle[k];
            part_two += value * triangle[k + 1];
        }
    }

    (part_one, part_two)
}

pub fn part1(input: &Input) -> i64 {
    input.0.abs()
}

pub fn part2(input: &Input) -> i64 {
    input.1.abs()
}