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 {Program[] } Programs.
19+ */
20+ parse ( input ) {
21+ let consoleLine = this . solConsole . addLine ( "Parsing..." ) ;
22+
23+ let programs = [ ] ;
24+ input . trim ( ) . split ( / \r ? \n / ) . forEach ( ( line , index ) => {
25+ let match = line . match ( / ^ ( \d + ) < - > ( \d + ( , \d + ) * ) $ / ) ;
26+ if ( match == null )
27+ throw new Error ( `Invalid data in line ${ index + 1 } ` ) ;
28+ let program = programs . find ( e => e . id == parseInt ( match [ 1 ] ) ) ;
29+ if ( program == undefined )
30+ programs . push ( program = new Program ( parseInt ( match [ 1 ] ) ) ) ;
31+
32+ for ( let connectedProgramId of match [ 2 ] . split ( ", " ) . map ( e => parseInt ( e ) ) ) {
33+ let connectedProgram = programs . find ( e => e . id == connectedProgramId ) ;
34+ if ( connectedProgram == undefined )
35+ programs . push ( connectedProgram = new Program ( connectedProgramId ) ) ;
36+ program . connections . push ( connectedProgram ) ;
37+ connectedProgram . connections . push ( program ) ;
38+ }
39+ } ) ;
40+
41+ consoleLine . innerHTML += " done." ;
42+ return programs ;
43+ }
44+
45+ /**
46+ * Finds the number of programs in the group that contains program ID 0 (part 1) or the number of program groups (part 2).
47+ * @param {number } part Puzzle part.
48+ * @param {string } input Puzzle input.
49+ * @param {boolean } visualization Enable visualization.
50+ * @returns {number } Number of programs in the group that contains program ID 0 (part 1) or the number of program groups (part 2).
51+ */
52+ async solve ( part , input , visualization ) {
53+ try {
54+ this . isSolving = true ;
55+
56+ let programs = this . parse ( input ) . sort ( ( a , b ) => a - b ) ;
57+ if ( programs [ 0 ] . id != 0 )
58+ throw new Error ( "Program 0 not found" ) ;
59+
60+ let visConsole = new Console ( ) ;
61+ if ( visualization )
62+ this . visContainer . append ( visConsole . container ) ;
63+
64+ let addGroupIdsToSet = ( program , idSet ) => {
65+ if ( ! idSet . has ( program . id ) ) {
66+ idSet . add ( program . id ) ;
67+ program . connections . forEach ( e => addGroupIdsToSet ( e , idSet ) ) ;
68+ }
69+ }
70+
71+ let groups = [ ] ;
72+ while ( programs . length > 0 ) {
73+ let idSet = new Set ( ) ;
74+ addGroupIdsToSet ( programs [ 0 ] , idSet ) ;
75+ groups . push ( programs . filter ( e => idSet . has ( e . id ) ) . sort ( ( a , b ) => a - b ) ) ;
76+ programs = programs . filter ( e => ! idSet . has ( e . id ) ) ;
77+ }
78+
79+ if ( visualization ) {
80+ if ( part == 1 )
81+ visConsole . addLine ( `Group (<span class="highlighted">${ groups [ 0 ] . length } </span> program${ groups . length == 1 ? "" : "s" } ): ${ groups [ 0 ] . map ( e => e . id ) . join ( ", " ) } .` ) ;
82+ else {
83+ for ( let i = 0 ; i < groups . length ; i ++ ) {
84+ visConsole . addLine ( `Group ${ i + 1 } : ${ groups [ i ] . map ( e => e . id ) . join ( ", " ) } .` ) ;
85+ visConsole . addLine ( ) ;
86+ }
87+ }
88+ }
89+
90+ return part == 1 ? groups [ 0 ] . length : groups . length ;
91+ }
92+
93+ finally {
94+ this . isSolving = false ;
95+ }
96+ }
97+
98+ /**
99+ * Stops solving the puzzle.
100+ */
101+ async stopSolving ( ) {
102+ this . isStopping = true ;
103+ while ( this . isSolving )
104+ await ( delay ( 10 ) ) ;
105+ this . isStopping = false ;
106+ }
107+ }
108+
109+ /**
110+ * Puzzle program class.
111+ */
112+ class Program {
113+ /**
114+ * @param {number } id ID.
115+ */
116+ constructor ( id ) {
117+ /**
118+ * ID.
119+ * @type {number }
120+ */
121+ this . id = id ;
122+ /**
123+ * Connections.
124+ * @type {Program[] }
125+ */
126+ this . connections = [ ] ;
127+ }
128+ }
0 commit comments