1+ import { delay , Console } from "../../utility.mjs" ;
2+
3+ export default class {
4+ /**
5+ * @param {Console } solConsole Solution console.
6+ * @param {HTMLElement } visContainer Visualization container.
7+ */
8+ constructor ( solConsole , visContainer ) {
9+ this . isSolving = false ;
10+ this . isStopping = false ;
11+ this . solConsole = typeof solConsole !== "undefined" ? solConsole : new Console ( ) ;
12+ this . visContainer = visContainer ;
13+ }
14+
15+ /**
16+ * Parses the puzzle input.
17+ * @param {string } input Puzzle input.
18+ * @returns {{
19+ * generatorAStartingValue: number,
20+ * generatorBStartingValue: number
21+ * }} Generator A starting value and generator B starting value.
22+ */
23+ parse ( input ) {
24+ let consoleLine = this . solConsole . addLine ( "Parsing..." ) ;
25+
26+ let lines = input . trim ( ) . split ( / \r ? \n / ) ;
27+
28+ if ( lines . length != 2 )
29+ throw new Error ( "Invalid input data" ) ;
30+ let match = lines [ 0 ] . match ( / ^ G e n e r a t o r A s t a r t s w i t h ( \d + ) $ / ) ;
31+ if ( match == null )
32+ throw new Error ( `Invalid data in line 1` ) ;
33+ let startingValueA = parseInt ( match [ 1 ] ) ;
34+ match = lines [ 1 ] . match ( / ^ G e n e r a t o r B s t a r t s w i t h ( \d + ) $ / ) ;
35+ if ( match == null )
36+ throw new Error ( `Invalid data in line 1` ) ;
37+ let startingValueB = parseInt ( match [ 1 ] ) ;
38+
39+ consoleLine . innerHTML += " done." ;
40+ return { startingValueA, startingValueB} ;
41+ }
42+
43+
44+ /**
45+ * Finds the number of times the lowest 16 bits of the generator value pairs match.
46+ * @param {number } part Puzzle part.
47+ * @param {string } input Puzzle input.
48+ * @param {boolean } visualization Enable visualization.
49+ * @returns {number } Number of times the lowest 16 bits of the generator value pairs match.
50+ */
51+ async solve ( part , input , visualization ) {
52+ try {
53+ this . isSolving = true ;
54+
55+ let { startingValueA, startingValueB} = this . parse ( input ) ;
56+ let factorA = 16807 , factorB = 48271 , divisor = 2147483647 , numberOfPairs = ( startingValueA == 65 && startingValueB == 8921 ) ? ( part == 1 ? 5 : 1056 ) : ( part == 1 ? 40000000 : 5000000 ) ;
57+
58+ let visConsole = new Console ( ) ;
59+ if ( visualization )
60+ this . visContainer . append ( visConsole . container ) ;
61+
62+ let valueA = startingValueA , valueB = startingValueB ;
63+ let numberOfMatches = 0 ;
64+ for ( let i = 0 ; i < numberOfPairs ; i ++ ) {
65+ if ( part == 1 ) {
66+ valueA = ( valueA * factorA ) % divisor ;
67+ valueB = ( valueB * factorB ) % divisor ;
68+ }
69+ else {
70+ for ( valueA = ( valueA * factorA ) % divisor ; valueA % 4 != 0 ; valueA = ( valueA * factorA ) % divisor ) ;
71+ for ( valueB = ( valueB * factorB ) % divisor ; valueB % 8 != 0 ; valueB = ( valueB * factorB ) % divisor ) ;
72+ }
73+
74+ if ( ( valueA & 0xFFFF ) == ( valueB & 0xFFFF ) )
75+ numberOfMatches ++ ;
76+ }
77+
78+ if ( visualization )
79+ visConsole . addLine ( `The first ${ numberOfPairs } generator value pairs have <span class="highlighted">${ numberOfMatches } </span> match${ numberOfMatches == 1 ? "" : "es" } of the lowest 16 bits.` ) ;
80+
81+ return numberOfMatches ;
82+ }
83+
84+ finally {
85+ this . isSolving = false ;
86+ }
87+ }
88+
89+ /**
90+ * Stops solving the puzzle.
91+ */
92+ async stopSolving ( ) {
93+ this . isStopping = true ;
94+ while ( this . isSolving )
95+ await ( delay ( 10 ) ) ;
96+ this . isStopping = false ;
97+ }
98+ }
0 commit comments