@@ -91,6 +91,97 @@ const daySolvers: { [key: string]: DaySolver } = {
9191 console . log ( `Part 1: Number of times position 0 was reached: ${ zeroCount1 } ` ) ;
9292 console . log ( `Part 2: Number of times position 0 was crossed: ${ zeroCount2 } ` ) ;
9393 } ,
94+ '02' : ( input : DayInput ) => {
95+ const ranges = input . trim ( ) . split ( ',' ) ;
96+ const invalidNumbers : number [ ] = [ ] ;
97+ const part2InvalidNumbers : number [ ] = [ ] ;
98+
99+ function isNumberInvalid ( num : number ) : boolean {
100+ const strNum = num . toString ( ) ;
101+
102+ // Odd length numbers can't be invalid based on the criteria.
103+ if ( strNum . length % 2 === 1 ) {
104+ return false ;
105+ }
106+
107+ const start = strNum . slice ( 0 , strNum . length / 2 ) ;
108+ const end = strNum . slice ( strNum . length / 2 ) ;
109+
110+ return start === end ;
111+ }
112+
113+ function isNumberInvalidPart2 ( num : number ) : boolean {
114+ const strNum = num . toString ( ) ;
115+ const strNumLength = strNum . length ;
116+ let isInvalid = false ;
117+
118+ // The maximum split point is half the length of the number.
119+ const maxSplitPoint = Math . floor ( strNumLength / 2 ) ;
120+ const splitPoints = new Set < number > (
121+ Array . from (
122+ { length : maxSplitPoint } ,
123+ ( _ , i ) => i + 1
124+ )
125+ ) ;
126+
127+ // console.log(`Checking number: ${num} with split points: ${Array.from(splitPoints).join(', ')}`);
128+
129+ splitPoints . forEach ( ( splitLength ) => {
130+ // If we already found the number to be invalid, skip further checks.
131+ if ( isInvalid ) {
132+ return ;
133+ }
134+
135+ // If the split point doesn't divide the number evenly, skip it.
136+ if ( strNumLength % splitLength !== 0 ) {
137+ return ;
138+ }
139+
140+ const numPieces : number = strNumLength / splitLength ;
141+
142+ // Split the number into pieces of the current split length.
143+ const pieces : string [ ] = [ ] ;
144+
145+ /*
146+ * We need to slice the string into pieces of 'splitLength' size.
147+ * For example, if strNum is "121212" and splitLength is 2,
148+ * we want to get ["12", "12", "12"].
149+ */
150+ for ( let i = 0 ; i < numPieces ; i ++ ) {
151+ const start = i * splitLength ;
152+ const end = start + splitLength ;
153+ pieces . push ( strNum . slice ( start , end ) ) ;
154+ }
155+
156+ debugLog ( `Number ${ num } split into pieces of length ${ splitLength } : ${ pieces . join ( ', ' ) } ` ) ;
157+ isInvalid = pieces . every ( ( piece ) => piece == pieces [ 0 ] ) ;
158+ if ( isInvalid ) {
159+ debugLog ( `Number ${ num } is invalid with split length ${ splitLength } (pieces: ${ pieces . join ( ', ' ) } )` ) ;
160+ return ;
161+ }
162+ } ) ;
163+
164+ return isInvalid ;
165+ }
166+
167+ ranges . forEach ( ( range ) => {
168+ const [ start , end ] = range . split ( '-' ) . map ( Number ) ;
169+ for ( let i = start ; i <= end ; i ++ ) {
170+ if ( isNumberInvalid ( i ) ) {
171+ invalidNumbers . push ( i ) ;
172+ }
173+
174+ if ( isNumberInvalidPart2 ( i ) ) {
175+ part2InvalidNumbers . push ( i ) ;
176+ }
177+ }
178+ } ) ;
179+
180+ debugLog ( `Part 2 invalid numbers: ${ part2InvalidNumbers . join ( ', ' ) } ` ) ;
181+
182+ console . log ( `Part 1: Sum of invalid numbers: ${ invalidNumbers . reduce ( ( a , b ) => a + b , 0 ) } ` ) ;
183+ console . log ( `Part 2: Sum of invalid numbers (advanced criteria): ${ part2InvalidNumbers . reduce ( ( a , b ) => a + b , 0 ) } ` ) ;
184+ } ,
94185} ;
95186
96187// Set up the CLI program.
0 commit comments