@@ -6,18 +6,71 @@ export async function part1(inputFile: string) {
6
6
}
7
7
8
8
export async function part2 ( inputFile : string ) {
9
- return await day23 ( inputFile ) ;
9
+ return await day23 ( inputFile , findLargestParty ) ;
10
10
}
11
11
12
- async function day23 ( inputFile : string , calcFn ?: ( lines : string [ ] ) => number ) {
12
+ async function day23 ( inputFile : string , calcFn ?: ( lines : string [ ] ) => number | string ) {
13
13
const inputPath = path . join ( __dirname , inputFile ) ;
14
14
const lines = await readInputLineByLine ( inputPath ) ;
15
15
16
16
return calcFn ?.( lines ) ;
17
17
}
18
18
19
19
function findComputerTriplets ( lines : string [ ] ) {
20
- const adjacencyList : { [ key : string ] : Set < string > } = { } ;
20
+ const adjacencyList = getAdjacencyList ( lines ) ;
21
+
22
+ return getTrianglesStartingWithT ( adjacencyList ) ;
23
+ }
24
+
25
+ // Bron–Kerbosch Algorithm:
26
+ // It operates on three sets:
27
+ // - R (Current Clique): Nodes included in the current clique.
28
+ // - P (Candidates): Nodes that can be added to the current clique.
29
+ // - X (Excluded): Nodes already considered and excluded from the current clique.
30
+ // At each step:
31
+ // - If P and X are empty, R is a maximal clique.
32
+ // - A pivot is selected to reduce the search space and optimize performance.
33
+ // Recursive calls refine these sets to explore possible cliques.
34
+
35
+ function findLargestParty ( lines : string [ ] ) {
36
+ const adjacencyList = getAdjacencyList ( lines ) ;
37
+
38
+ const findLargestParties = ( adjacencyList : { [ key : string ] : Set < string > } ) => {
39
+ const parties : string [ ] [ ] = [ ] ;
40
+
41
+ const bronKerbosch = ( r : Set < string > , p : Set < string > , x : Set < string > ) => {
42
+ if ( p . size === 0 && x . size === 0 ) {
43
+ parties . push ( [ ...r ] ) ;
44
+ return ;
45
+ }
46
+
47
+ const pivot = p . size > 0 ? [ ...p ] [ 0 ] : null ;
48
+ const pivotNeighbors = pivot ? adjacencyList [ pivot ] : new Set ( ) ;
49
+
50
+ for ( const node of [ ...p ] . filter ( ( n ) => ! pivotNeighbors . has ( n ) ) ) {
51
+ bronKerbosch (
52
+ new Set ( [ ...r , node ] ) ,
53
+ new Set ( [ ...p ] . filter ( ( n ) => adjacencyList [ node ] . has ( n ) ) ) ,
54
+ new Set ( [ ...x ] . filter ( ( n ) => adjacencyList [ node ] . has ( n ) ) ) ,
55
+ ) ;
56
+ p . delete ( node ) ;
57
+ x . add ( node ) ;
58
+ }
59
+ }
60
+
61
+ bronKerbosch ( new Set ( ) , new Set ( Object . keys ( adjacencyList ) ) , new Set ( ) ) ;
62
+ return parties ;
63
+ }
64
+
65
+ const findLargestParty = ( parties : string [ ] [ ] ) => {
66
+ return parties . reduce ( ( max , party ) => ( party . length > max . length ? party : max ) , [ ] ) ;
67
+ }
68
+
69
+ return findLargestParty ( findLargestParties ( adjacencyList ) ) . sort ( ) . join ( "," ) ;
70
+ }
71
+
72
+ function getAdjacencyList ( lines : string [ ] ) {
73
+ const adjacencyList : { [ key : string ] : Set < string > } = { } ;
21
74
for ( const connection of lines ) {
22
75
const [ a , b ] = connection . split ( "-" ) ;
23
76
if ( ! adjacencyList [ a ] )
@@ -28,7 +81,10 @@ function findComputerTriplets(lines: string[]) {
28
81
adjacencyList [ a ] . add ( b ) ;
29
82
adjacencyList [ b ] . add ( a ) ;
30
83
}
84
+ return adjacencyList ;
85
+ }
31
86
87
+ function getTrianglesStartingWithT ( adjacencyList : { [ p : string ] : Set < string > } ) {
32
88
const triangles : Set < string > = new Set ( ) ;
33
89
let trianglesStartingWithT = 0 ;
34
90
for ( const [ node , neighbors ] of Object . entries ( adjacencyList ) ) {
@@ -46,7 +102,6 @@ function findComputerTriplets(lines: string[]) {
46
102
}
47
103
}
48
104
}
49
-
50
105
[ ...triangles ] . forEach ( ( triangle : string ) => {
51
106
const split = triangle . split ( "," )
52
107
if ( split . some ( s => s . startsWith ( "t" ) ) ) {
0 commit comments