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 {Instruction[] } Instruction.
19+ */
20+ parse ( input ) {
21+ let consoleLine = this . solConsole . addLine ( "Parsing..." ) ;
22+
23+ let instructions = input . trim ( ) . split ( / \r ? \n / ) . map ( ( line , index ) => {
24+ let match = line . match ( / ^ ( [ a - z ] + ) ( d e c | i n c ) ( - ? \d + ) i f ( [ a - z ] + ) ( > | < | > = | < = | = = | ! = ) ( - ? \d + ) $ / ) ;
25+ if ( match == null )
26+ throw new Error ( `Invalid data in line ${ index + 1 } ` ) ;
27+ return new Instruction ( match [ 1 ] , match [ 2 ] , parseInt ( match [ 3 ] ) , match [ 4 ] , match [ 5 ] , parseInt ( match [ 6 ] ) )
28+ } ) ;
29+
30+ consoleLine . innerHTML += " done." ;
31+ return instructions ;
32+ }
33+
34+ /**
35+ * Finds the largest register value after completing the instructions (part 1) or the highest value held in any register during this process (part 2).
36+ * @param {number } part Puzzle part.
37+ * @param {string } input Puzzle input.
38+ * @param {boolean } visualization Enable visualization.
39+ * @returns {number } Largest register value after completing the instructions (part 1) or the highest value held in any register during this process (part 2).
40+ */
41+ async solve ( part , input , visualization ) {
42+ try {
43+ this . isSolving = true ;
44+
45+ let instructions = this . parse ( input ) ;
46+
47+ let visConsole = new Console ( ) ;
48+ let solConsoleLine1 , solConsoleLine2 ;
49+ if ( visualization ) {
50+ this . visContainer . append ( visConsole . container ) ;
51+ this . solConsole . addLine ( `Number of instructions: ${ instructions . length } .` ) ;
52+ solConsoleLine1 = this . solConsole . addLine ( ) ;
53+ if ( part == 2 )
54+ solConsoleLine2 = this . solConsole . addLine ( ) ;
55+ }
56+
57+ let registers = { } ;
58+ for ( let instruction of instructions ) {
59+ if ( ! ( instruction . arithmeticRegister in registers ) )
60+ registers [ instruction . arithmeticRegister ] = 0 ;
61+ if ( ! ( instruction . conditionRegister in registers ) )
62+ registers [ instruction . conditionRegister ] = 0 ;
63+ }
64+
65+ let registerNames = Object . keys ( registers ) ;
66+ if ( visualization )
67+ registerNames . forEach ( e => visConsole . addLine ( ) ) ;
68+
69+ let maxRegisterValue = 0 ;
70+ for ( let instructionIndex = 0 ; instructionIndex < instructions . length ; instructionIndex ++ ) {
71+ if ( this . isStopping )
72+ return ;
73+
74+ let instruction = instructions [ instructionIndex ] ;
75+ if ( ( instruction . conditionOperator == ">" && registers [ instruction . conditionRegister ] > instruction . conditionValue ) ||
76+ ( instruction . conditionOperator == "<" && registers [ instruction . conditionRegister ] < instruction . conditionValue ) ||
77+ ( instruction . conditionOperator == ">=" && registers [ instruction . conditionRegister ] >= instruction . conditionValue ) ||
78+ ( instruction . conditionOperator == "<=" && registers [ instruction . conditionRegister ] <= instruction . conditionValue ) ||
79+ ( instruction . conditionOperator == "==" && registers [ instruction . conditionRegister ] == instruction . conditionValue ) ||
80+ ( instruction . conditionOperator == "!=" && registers [ instruction . conditionRegister ] != instruction . conditionValue ) ) {
81+
82+ if ( instruction . arithmeticOperator == "inc" )
83+ registers [ instruction . arithmeticRegister ] += instruction . arithmeticValue ;
84+ if ( instruction . arithmeticOperator == "dec" )
85+ registers [ instruction . arithmeticRegister ] -= instruction . arithmeticValue ;
86+
87+ if ( part == 2 )
88+ maxRegisterValue = Math . max ( maxRegisterValue , registers [ instruction . arithmeticRegister ] ) ;
89+ }
90+
91+ if ( visualization ) {
92+ solConsoleLine1 . innerHTML = `Instruction: ${ instructionIndex + 1 } .` ;
93+ if ( part == 2 )
94+ solConsoleLine2 . innerHTML = `Max register value: ${ maxRegisterValue } .` ;
95+ for ( let i = 0 ; i < registerNames . length ; i ++ )
96+ visConsole . lines [ i ] . innerHTML = `${ registerNames [ i ] } = ${ registers [ registerNames [ i ] ] } ` ;
97+ await delay ( 1 ) ;
98+ }
99+ }
100+
101+ if ( part == 1 ) {
102+ maxRegisterValue = Math . max ( ...Object . values ( registers ) ) ;
103+ if ( visualization ) {
104+ let maxValueRegisterIndex = registerNames . findIndex ( e => registers [ e ] == maxRegisterValue ) ;
105+ visConsole . lines [ maxValueRegisterIndex ] . classList . add ( "highlighted" ) ;
106+ visConsole . container . scrollTop = visConsole . lines [ maxValueRegisterIndex ] . offsetTop - visConsole . container . offsetHeight / 2 ;
107+ }
108+ }
109+
110+ return maxRegisterValue ;
111+ }
112+
113+ finally {
114+ this . isSolving = false ;
115+ }
116+ }
117+
118+ /**
119+ * Stops solving the puzzle.
120+ */
121+ async stopSolving ( ) {
122+ this . isStopping = true ;
123+ while ( this . isSolving )
124+ await ( delay ( 10 ) ) ;
125+ this . isStopping = false ;
126+ }
127+ }
128+
129+ /**
130+ * Puzzle instruction class.
131+ */
132+ class Instruction {
133+ /**
134+ * @param {string } arithmeticRegister Arithmetic register.
135+ * @param {string } arithmeticOperator Arithmetic operator.
136+ * @param {number } arithmeticValue Arithmetic value.
137+ * @param {string } conditionRegister Condition register.
138+ * @param {string } conditionOperator Condition operator.
139+ * @param {number } conditionValue Condition value.
140+ */
141+ constructor ( arithmeticRegister , arithmeticOperator , arithmeticValue , conditionRegister , conditionOperator , conditionValue ) {
142+ /**
143+ * Arithmetic register.
144+ * @type {string }
145+ */
146+ this . arithmeticRegister = arithmeticRegister ;
147+ /**
148+ * Arithmetic operator.
149+ * @type {string }
150+ */
151+ this . arithmeticOperator = arithmeticOperator ;
152+ /**
153+ * Arithmetic value.
154+ * @type {number }
155+ */
156+ this . arithmeticValue = arithmeticValue ;
157+ /**
158+ * Condition register.
159+ * @type {string }
160+ */
161+ this . conditionRegister = conditionRegister ;
162+ /**
163+ * Condition operator.
164+ * @type {string }
165+ */
166+ this . conditionOperator = conditionOperator ;
167+ /**
168+ * Condition value.
169+ * @type {number }
170+ */
171+ this . conditionValue = conditionValue ;
172+ }
173+ }
0 commit comments