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
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! # [Day 15: Dueling Generators](http://adventofcode.com/2017/day/15)
//!
//! Here, you encounter a pair of dueling <span title="I guess they *are* a little
//! banjo-shaped. Why do you ask?">generators</span>. The generators, called
//! *generator A* and *generator B*, are trying to agree on a sequence of numbers.
//! However, one of them is malfunctioning, and so the sequences don't always
//! match.
//!
//! As they do this, a *judge* waits for each of them to generate its next
//! value, compares the lowest 16 bits of both values, and keeps track of
//! the number of times those parts of the values match.

/// The generators both work on the same principle. To create its next
/// value, a generator will take the previous value it produced, multiply it
/// by a *factor* (generator A uses `16807`; generator B uses `48271`), and
/// then keep the remainder of dividing that resulting product by
/// `2147483647`. That final remainder is the value it produces next.
///
/// To calculate each generator's first value, it instead uses a specific
/// starting value as its "previous value" (as listed in your puzzle input).
///
/// For example, suppose that for starting values, generator A uses `65`,
/// while generator B uses `8921`. Then, the first five pairs of generated
/// values are:
///
/// ```text
/// --Gen. A--  --Gen. B--
///    1092455   430625591
/// 1181022009  1233683848
///  245556042  1431495498
/// 1744312007   137874439
/// 1352636452   285222916
/// ```
///
/// In binary, these pairs are (with generator A's value first in each
/// pair):
///
/// ```text
/// 00000000000100001010101101100111
/// 00011001101010101101001100110111
///
/// 01000110011001001111011100111001
/// 01001001100010001000010110001000
///
/// 00001110101000101110001101001010
/// 01010101010100101110001101001010
///
/// 01100111111110000001011011000111
/// 00001000001101111100110000000111
///
/// 01010000100111111001100000100100
/// 00010001000000000010100000000100
/// ```
///
/// ```
/// # use advent_solutions::advent2017::day15::Generator;
/// let a = Generator::new(16807, 65)
///     .take(5)
///     .collect::<Vec<_>>();
/// let b = Generator::new(48271, 8921)
///     .take(5)
///     .collect::<Vec<_>>();
///
/// assert_eq!(a, [1092455, 1181022009, 245556042, 1744312007, 1352636452]);
/// assert_eq!(b, [430625591, 1233683848, 1431495498, 137874439, 285222916]);
/// ```
pub struct Generator {
    factor: u32,
    v: u32,
}

impl Generator {
    pub fn new(factor: u32, v: u32) -> Generator {
        Generator { factor, v }
    }
}

impl Iterator for Generator {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
         self.v = (((self.v as u64) * (self.factor as u64)) % 0x7FFF_FFFF) as u32;
         Some(self.v)
    }
}

/// Here, you can see that the lowest (here, rightmost) 16 bits of the third
/// value match: `1110001101001010`. Because of this one match, after
/// processing these five pairs, the judge would have added only `1` to its
/// total.
///
/// To get a significant sample, the judge would like to consider *40
/// million* pairs. (In the example above, the judge would eventually find a
/// total of `588` pairs that match in their lowest 16 bits.)
///
/// ```
/// # use advent_solutions::advent2017::day15::part1;
/// assert_eq!(part1(&((16807, 65), (48271, 8921))), 588);
/// ```
///
/// After 40 million pairs, *what is the judge's final count*?
pub fn part1(&((a_f, a_s), (b_f, b_s)): &((u32, u32), (u32, u32))) -> usize {
    Generator::new(a_f, a_s)
        .zip(Generator::new(b_f, b_s))
        .take(40_000_000)
        .filter(|&(a, b)| (a & 0xFFFF) == (b & 0xFFFF))
        .count()
}

/// In the interest of trying to align a little better, the generators get
/// more picky about the numbers they actually give to the judge.
///
/// They still generate values in the same way, but now they only hand a
/// value to the judge when it meets their *criteria*:
///
/// -   Generator A looks for values that are multiples of `4`.
/// -   Generator B looks for values that are multiples of `8`.
///
/// Each generator functions completely *independently*: they both go
/// through values entirely on their own, only occasionally handing an
/// acceptable value to the judge, and otherwise working through the same
/// sequence of values as before until they find one.
///
/// The judge still waits for each generator to provide it with a value
/// before comparing them (using the same comparison method as before). It
/// keeps track of the order it receives values; the first values from each
/// generator are compared, then the second values from each generator, then
/// the third values, and so on.
///
/// Using the example starting values given above, the generators now
/// produce the following first five values each:
///
/// --Gen. A--  --Gen. B--
/// 1352636452  1233683848
/// 1992081072   862516352
///  530830436  1159784568
/// 1980017072  1616057672
///  740335192   412269392
///
/// ```
/// # use advent_solutions::advent2017::day15::Generator;
/// let a = Generator::new(16807, 65)
///     .filter(|x| x % 4 == 0)
///     .take(5)
///     .collect::<Vec<_>>();
/// let b = Generator::new(48271, 8921)
///     .filter(|x| x % 8 == 0)
///     .take(5)
///     .collect::<Vec<_>>();
///
/// assert_eq!(a, [1352636452, 1992081072, 530830436, 1980017072, 740335192]);
/// assert_eq!(b, [1233683848, 862516352, 1159784568, 1616057672, 412269392]);
/// ```
///
/// These values have the following corresponding binary values:
///
/// 01010000100111111001100000100100
/// 01001001100010001000010110001000
///
/// 01110110101111001011111010110000
/// 00110011011010001111010010000000
///
/// 00011111101000111101010001100100
/// 01000101001000001110100001111000
///
/// 01110110000001001010100110110000
/// 01100000010100110001010101001000
///
/// 00101100001000001001111001011000
/// 00011000100100101011101101010000
///
/// Unfortunately, even though this change makes more bits similar on
/// average, none of these values' lowest 16 bits match. Now, it's not until
/// the 1056th pair that the judge finds the first match:
///
/// --Gen. A--  --Gen. B--
/// 1023762912   896885216
///
/// 00111101000001010110000111100000
/// 00110101011101010110000111100000
///
/// This change makes the generators much slower, and the judge is getting
/// impatient; it is now only willing to consider *5 million* pairs. (Using
/// the values from the example above, after five million pairs, the judge
/// would eventually find a total of `309` pairs that match in their lowest
/// 16 bits.)
///
/// ```
/// # use advent_solutions::advent2017::day15::part2;
/// assert_eq!(part2(&((16807, 65), (48271, 8921))), 309);
/// ```
///
/// After 5 million pairs, but using this new generator logic, *what is the
/// judge's final count*?
pub fn part2(&((a_f, a_s), (b_f, b_s)): &((u32, u32), (u32, u32))) -> usize {
    Generator::new(a_f, a_s)
        .filter(|x| x % 4 == 0)
        .zip(Generator::new(b_f, b_s)
            .filter(|x| x % 8 == 0)
        )
        .take(5_000_000)
        .filter(|&(a, b)| (a & 0xFFFF) == (b & 0xFFFF))
        .count()
}

pub fn parse_input(input: &str) -> ((u32, u32), (u32, u32)) {
    let mut starts = input.lines()
        .map(|line| line[24..].parse::<u32>().expect("Could not parse input"));

    let a_s = starts.next().expect("Could not find a_s");
    let b_s = starts.next().expect("Could not find b_s");
    assert!(starts.next().is_none(), "More than 2 lines");

    ((16807, a_s), (48271, b_s))
}

test_day!("15", 567, 323);