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 {string[][] } Passphrases.
19+ */
20+ parse ( input ) {
21+ let consoleLine = this . solConsole . addLine ( "Parsing..." ) ;
22+
23+ let passphrases = input . trim ( ) . split ( / \r ? \n / ) . map ( ( line , index ) => {
24+ if ( ! / ^ [ \s a - z ] + $ / . test ( line ) )
25+ throw new Error ( `Invalid data in line ${ index + 1 } ` ) ;
26+ return line . split ( " " ) ;
27+ } ) ;
28+
29+ consoleLine . innerHTML += " done." ;
30+ return passphrases ;
31+ }
32+
33+
34+ /**
35+ * Finds the number of valid passphrases.
36+ * @param {number } part Puzzle part.
37+ * @param {string } input Puzzle input.
38+ * @param {boolean } visualization Enable visualization.
39+ * @returns {number } Number of valid passphrases.
40+ */
41+ async solve ( part , input , visualization ) {
42+ try {
43+ this . isSolving = true ;
44+
45+ let passphrases = this . parse ( input ) ;
46+
47+ let visConsole = new Console ( ) ;
48+ if ( visualization )
49+ this . visContainer . append ( visConsole . container ) ;
50+
51+ let numberOfValidPassphrases = 0 ;
52+ for ( let passphrase of passphrases ) {
53+ let passphraseWithSortedWords = passphrase . map ( e => e . split ( "" ) . sort ( ) . join ( "" ) )
54+ let invalidWordIndexPair = null ;
55+ for ( let i = 0 ; i < passphrase . length && invalidWordIndexPair == null ; i ++ ) {
56+ for ( let j = i + 1 ; j < passphrase . length && invalidWordIndexPair == null ; j ++ ) {
57+ if ( ( part == 1 && passphrase [ i ] == passphrase [ j ] ) || ( part == 2 && passphraseWithSortedWords [ i ] == passphraseWithSortedWords [ j ] ) )
58+ invalidWordIndexPair = [ i , j ] ;
59+ }
60+ }
61+
62+ if ( invalidWordIndexPair == null )
63+ numberOfValidPassphrases ++ ;
64+
65+ if ( visualization ) {
66+ visConsole . addLine ( passphrase . map ( ( e , i ) =>
67+ invalidWordIndexPair == null ? `<span class="highlighted">${ e } </span>` : ( invalidWordIndexPair . indexOf ( i ) >= 0 ? `<span class="error">${ e } </span>` : e ) ) . join ( " " ) ) ;
68+ visConsole . addLine ( ) ;
69+ }
70+ }
71+
72+ return numberOfValidPassphrases ;
73+ }
74+
75+ finally {
76+ this . isSolving = false ;
77+ }
78+ }
79+
80+ /**
81+ * Stops solving the puzzle.
82+ */
83+ async stopSolving ( ) {
84+ this . isStopping = true ;
85+ while ( this . isSolving )
86+ await ( delay ( 10 ) ) ;
87+ this . isStopping = false ;
88+ }
89+ }
0 commit comments