1+ import { delay , Console , Vector2D } from "../../utility.mjs" ;
2+
3+ const wallIndex = 1 ;
4+ const wallColor = "#999999" ;
5+ const positionColorIndex = 2 ;
6+ const positionColor = "#ffffff" ;
7+
8+ export default class {
9+ /**
10+ * @param {Console } solConsole Solution console.
11+ * @param {HTMLElement } visContainer Visualization container.
12+ */
13+ constructor ( solConsole , visContainer ) {
14+ this . isSolving = false ;
15+ this . isStopping = false ;
16+ this . solConsole = typeof solConsole !== "undefined" ? solConsole : new Console ( ) ;
17+ this . visContainer = visContainer ;
18+ }
19+
20+ /**
21+ * Parses the puzzle input.
22+ * @param {string } input Puzzle input.
23+ * @returns {string[] } Directions.
24+ */
25+ parse ( input ) {
26+ let consoleLine = this . solConsole . addLine ( "Parsing..." ) ;
27+
28+ let path = input . trim ( ) . split ( "," ) . map ( ( step , index ) => {
29+ if ( [ "n" , "s" , "ne" , "nw" , "se" , "sw" ] . indexOf ( step ) < 0 )
30+ throw new Error ( `Invalid data in step ${ index + 1 } ` ) ;
31+ return step ;
32+ } ) ;
33+
34+ consoleLine . innerHTML += " done." ;
35+ return path ;
36+ }
37+
38+ /**
39+ * Finds the distance to the end of the path (part 1) or the largest distance from the start along the path (part 2).
40+ * @param {number } part Puzzle part.
41+ * @param {string } input Puzzle input.
42+ * @param {boolean } visualization Enable visualization.
43+ * @returns {number } Distance to the end of the path (part 1) or the largest distance from the start along the path (part 2).
44+ */
45+ async solve ( part , input , visualization ) {
46+ try {
47+ this . isSolving = true ;
48+
49+ let directions = this . parse ( input ) ;
50+
51+ let positions = [ new Vector2D ( 0 , 0 ) ] ;
52+ let maxDistance = 0 , distance = 0 ;
53+ for ( let direction of directions ) {
54+ positions . push ( this . step ( positions [ positions . length - 1 ] , direction ) ) ;
55+ distance = this . distance ( positions [ 0 ] , positions [ positions . length - 1 ] ) ;
56+ maxDistance = Math . max ( maxDistance , distance ) ;
57+ }
58+
59+ if ( visualization ) {
60+ let visConsole = new Console ( ) ;
61+ this . visContainer . append ( visConsole . container ) ;
62+ if ( part == 1 )
63+ visConsole . addLine ( `Distance from the start to the end of the path: <span class="highlighted">${ distance } </span>.` ) ;
64+ else
65+ visConsole . addLine ( `Largest distance from the start along the path: <span class="highlighted">${ maxDistance } </span>.` ) ;
66+ }
67+
68+ return part == 1 ? distance : maxDistance ;
69+ }
70+
71+ finally {
72+ this . isSolving = false ;
73+ }
74+ }
75+
76+ /**
77+ * Finds the new position after the step.
78+ * @param {Vector2D } position Position before the step.
79+ * @param {string } direction Direction.
80+ * @returns {Vector2D } Position after the step.
81+ */
82+ step ( position , direction ) {
83+ if ( direction == "n" )
84+ return new Vector2D ( position . x , position . y - 1 ) ;
85+ if ( direction == "s" )
86+ return new Vector2D ( position . x , position . y + 1 ) ;
87+ if ( direction == "ne" )
88+ return new Vector2D ( position . x + 1 , position . x % 2 == 0 ? position . y - 1 : position . y ) ;
89+ if ( direction == "se" )
90+ return new Vector2D ( position . x + 1 , position . x % 2 == 0 ? position . y : position . y + 1 ) ;
91+ if ( direction == "nw" )
92+ return new Vector2D ( position . x - 1 , position . x % 2 == 0 ? position . y - 1 : position . y ) ;
93+ if ( direction == "sw" )
94+ return new Vector2D ( position . x - 1 , position . x % 2 == 0 ? position . y : position . y + 1 ) ;
95+
96+ throw new Error ( "Invalid direction" ) ;
97+ }
98+
99+ /**
100+ * Finds the distance between two positions.
101+ * @param {Vector2D } position1 Position 1.
102+ * @param {Vector2D } position2 Position 2.
103+ * @returns {number } Distance.
104+ */
105+ distance ( position1 , position2 ) {
106+ if ( position1 . y <= position2 . y )
107+ return Math . abs ( position2 . y - ( position1 . y - Math . floor ( ( Math . abs ( position1 . x - position2 . x ) + ( position1 . x % 2 == 0 ? 1 : 0 ) ) / 2 ) ) ) ;
108+ else
109+ return Math . abs ( position2 . y - ( position1 . y + Math . floor ( ( Math . abs ( position1 . x - position2 . x ) + ( position1 . x % 2 == 0 ? 0 : 1 ) ) / 2 ) ) ) ;
110+ }
111+
112+ /**
113+ * Stops solving the puzzle.
114+ */
115+ async stopSolving ( ) {
116+ this . isStopping = true ;
117+ while ( this . isSolving )
118+ await ( delay ( 10 ) ) ;
119+ this . isStopping = false ;
120+ }
121+ }
0 commit comments