Skip to content

Commit 5174d83

Browse files
committed
Solution for Day 15.
1 parent 856b705 commit 5174d83

File tree

3 files changed

+180
-1
lines changed

3 files changed

+180
-1
lines changed

inputs/Day15.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Generator A starts with 289
2+
Generator B starts with 629

instructions/Day15.txt

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
--- Day 15: Dueling Generators ---
2+
3+
Here, you encounter a pair of dueling generators. The generators, called
4+
generator A and generator B, are trying to agree on a sequence of
5+
numbers. However, one of them is malfunctioning, and so the sequences
6+
don't always match.
7+
8+
As they do this, a judge waits for each of them to generate its next
9+
value, compares the lowest 16 bits of both values, and keeps track of
10+
the number of times those parts of the values match.
11+
12+
The generators both work on the same principle. To create its next
13+
value, a generator will take the previous value it produced, multiply it
14+
by a factor (generator A uses 16807; generator B uses 48271), and then
15+
keep the remainder of dividing that resulting product by 2147483647.
16+
That final remainder is the value it produces next.
17+
18+
To calculate each generator's first value, it instead uses a specific
19+
starting value as its "previous value" (as listed in your puzzle input).
20+
21+
For example, suppose that for starting values, generator A uses 65,
22+
while generator B uses 8921. Then, the first five pairs of generated
23+
values are:
24+
25+
--Gen. A-- --Gen. B--
26+
1092455 430625591
27+
1181022009 1233683848
28+
245556042 1431495498
29+
1744312007 137874439
30+
1352636452 285222916
31+
32+
In binary, these pairs are (with generator A's value first in each
33+
pair):
34+
35+
00000000000100001010101101100111
36+
00011001101010101101001100110111
37+
38+
01000110011001001111011100111001
39+
01001001100010001000010110001000
40+
41+
00001110101000101110001101001010
42+
01010101010100101110001101001010
43+
44+
01100111111110000001011011000111
45+
00001000001101111100110000000111
46+
47+
01010000100111111001100000100100
48+
00010001000000000010100000000100
49+
50+
Here, you can see that the lowest (here, rightmost) 16 bits of the third
51+
value match: 1110001101001010. Because of this one match, after
52+
processing these five pairs, the judge would have added only 1 to its
53+
total.
54+
55+
To get a significant sample, the judge would like to consider 40 million
56+
pairs. (In the example above, the judge would eventually find a total of
57+
588 pairs that match in their lowest 16 bits.)
58+
59+
After 40 million pairs, what is the judge's final count?
60+
61+
Your puzzle answer was 638.
62+
63+
--- Part Two ---
64+
65+
In the interest of trying to align a little better, the generators get
66+
more picky about the numbers they actually give to the judge.
67+
68+
They still generate values in the same way, but now they only hand a
69+
value to the judge when it meets their criteria:
70+
71+
Generator A looks for values that are multiples of 4.
72+
Generator B looks for values that are multiples of 8.
73+
Each generator functions completely independently: they both go through
74+
values entirely on their own, only occasionally handing an acceptable
75+
value to the judge, and otherwise working through the same sequence of
76+
values as before until they find one.
77+
78+
The judge still waits for each generator to provide it with a value
79+
before comparing them (using the same comparison method as before). It
80+
keeps track of the order it receives values; the first values from each
81+
generator are compared, then the second values from each generator, then
82+
the third values, and so on.
83+
84+
Using the example starting values given above, the generators now
85+
produce the following first five values each:
86+
87+
--Gen. A-- --Gen. B--
88+
1352636452 1233683848
89+
1992081072 862516352
90+
530830436 1159784568
91+
1980017072 1616057672
92+
740335192 412269392
93+
94+
These values have the following corresponding binary values:
95+
96+
01010000100111111001100000100100
97+
01001001100010001000010110001000
98+
99+
01110110101111001011111010110000
100+
00110011011010001111010010000000
101+
102+
00011111101000111101010001100100
103+
01000101001000001110100001111000
104+
105+
01110110000001001010100110110000
106+
01100000010100110001010101001000
107+
108+
00101100001000001001111001011000
109+
00011000100100101011101101010000
110+
111+
Unfortunately, even though this change makes more bits similar on
112+
average, none of these values' lowest 16 bits match. Now, it's not until
113+
the 1056th pair that the judge finds the first match:
114+
115+
--Gen. A-- --Gen. B--
116+
1023762912 896885216
117+
118+
00111101000001010110000111100000
119+
00110101011101010110000111100000
120+
121+
This change makes the generators much slower, and the judge is getting
122+
impatient; it is now only willing to consider 5 million pairs. (Using
123+
the values from the example above, after five million pairs, the judge
124+
would eventually find a total of 309 pairs that match in their lowest 16
125+
bits.)
126+
127+
After 5 million pairs, but using this new generator logic, what is the
128+
judge's final count?
129+
130+
Your puzzle answer was 343.
131+

src/day15.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,55 @@
11
#include "default_includes.hpp"
22
#include "solution.hpp"
33

4+
template<uint64_t factor>
5+
static constexpr uint64_t gen_next(uint64_t prev)
6+
{
7+
return ((prev * factor) % 0x7FFFFFFFu);
8+
}
9+
10+
template<uint64_t factor, uint64_t criteria>
11+
static constexpr uint64_t gen_next_p2(uint64_t prev)
12+
{
13+
uint64_t val = gen_next<factor>(prev);
14+
while ((val % criteria) != 0u) { val = gen_next<factor>(val); }
15+
return val;
16+
}
17+
18+
static constexpr bool is_match(uint64_t x, uint64_t y)
19+
{
20+
return (x & 0xFFFFu) == (y & 0xFFFFu);
21+
}
22+
423
template<>
524
void solve<Day15>(std::istream& ins, std::ostream& outs)
625
{
7-
if (!ins.good()) { outs << "Failed to open input file!" << std::endl; }
26+
NOT_USED(ins);
27+
28+
const uint64_t input1{289u};
29+
const uint64_t input2{629u};
30+
31+
uint64_t val1{input1};
32+
uint64_t val1_p2{input1};
33+
uint64_t val2{input2};
34+
uint64_t val2_p2{input2};
35+
size_t matches{0u};
36+
size_t matches_p2{0u};
37+
38+
for (auto i = 0; i < 40000000; ++i)
39+
{
40+
val1 = gen_next<16807>(val1);
41+
val2 = gen_next<48271>(val2);
42+
if (is_match(val1, val2)) { ++matches; }
43+
44+
if (i < 5000000)
45+
{
46+
val1_p2 = gen_next_p2<16807, 4>(val1_p2);
47+
val2_p2 = gen_next_p2<48271, 8>(val2_p2);
48+
if (is_match(val1_p2, val2_p2)) { ++matches_p2; }
49+
}
50+
}
51+
52+
outs << "(Part 1) Number of matches = " << matches << std::endl
53+
<< "(Part 2) Number of matches = " << matches_p2 << std::endl;
854
}
955

0 commit comments

Comments
 (0)