88using System . Security ;
99using static AdventOfCode . Solutions . Utilities ;
1010using System . Runtime . CompilerServices ;
11+ using System . Security . Cryptography . X509Certificates ;
1112
1213namespace AdventOfCode . Solutions . Year2023
1314{
1415 [ DayInfo ( 23 , 2023 , "" ) ]
1516 class Day23 : ASolution
1617 {
18+ Dictionary < Coordinate2D , char > map ;
19+ int maxX ;
20+ int maxY ;
21+ Coordinate2D Start ;
22+ Coordinate2D Goal ;
23+ Node StartNode ;
24+ Node GoalNode ;
25+ Dictionary < Coordinate2D , Node > Nodes = new ( ) ;
26+ //Coordinate2D
27+
28+
1729 public Day23 ( ) : base ( )
1830 {
31+ ( map , maxX , maxY ) = Input . GenerateMap ( false ) ;
32+ Start = ( 1 , 0 ) ;
33+ Goal = ( maxX - 1 , maxY ) ;
34+
35+ StartNode = new ( ) { location = Start } ;
36+ GoalNode = new ( ) { location = Goal } ;
37+
38+ Nodes [ Start ] = StartNode ;
39+ Nodes [ Goal ] = GoalNode ;
1940
41+ var intersections = map . Where ( a => a . Key . Neighbors ( ) . Count ( b => map . ContainsKey ( b ) && "<>^v" . Contains ( map [ b ] ) ) >= 3 ) . Select ( a => a . Key ) . ToList ( ) ;
42+
43+ foreach ( var i in intersections )
44+ {
45+ Node tmp = new ( ) { location = i } ;
46+ Nodes [ i ] = tmp ;
47+ }
2048 }
2149
2250 protected override object SolvePartOne ( )
2351 {
24- return null ;
52+ return FindLongestPath ( Start , Goal , new ( ) ) ;
2553 }
2654
2755 protected override object SolvePartTwo ( )
2856 {
29- return null ;
57+ return FindLongestPath ( Start , Goal , new ( ) , false ) ;
58+ }
59+
60+ class Node
61+ {
62+ public Coordinate2D location ;
63+
64+ public List < ( Node Neighbor , int dist ) > Neighbors = new ( ) ;
65+
66+ public override int GetHashCode ( )
67+ {
68+ return location . GetHashCode ( ) ;
69+ }
70+
71+ }
72+
73+
74+ private int FindLongestPath ( Coordinate2D curLoc , Coordinate2D Goal , HashSet < Coordinate2D > visited , bool SlopesAreSlippery = true )
75+ {
76+ HashSet < Coordinate2D > locVisited = new ( visited ) ;
77+ if ( ! locVisited . Add ( curLoc ) ) return 0 ;
78+ int res = 1 ;
79+ if ( curLoc == Goal )
80+ {
81+ return res ;
82+ }
83+
84+ if ( SlopesAreSlippery )
85+ {
86+ switch ( map [ curLoc ] )
87+ {
88+ case '>' : return res + FindLongestPath ( curLoc . MoveDirection ( E ) , Goal , locVisited ) ;
89+ case '<' : return res + FindLongestPath ( curLoc . MoveDirection ( W ) , Goal , locVisited ) ;
90+ case '^' : return res + FindLongestPath ( curLoc . MoveDirection ( N , true ) , Goal , locVisited ) ;
91+ case 'v' : return res + FindLongestPath ( curLoc . MoveDirection ( S , true ) , Goal , locVisited ) ;
92+ default : break ;
93+ }
94+ }
95+
96+
97+ int runLength = 0 ;
98+
99+ List < Coordinate2D > validPaths = new ( ) ;
100+ while ( true ) {
101+ validPaths = curLoc . Neighbors ( ) . Where ( a => map . ContainsKey ( a ) && map [ a ] != '#' && ! locVisited . Contains ( a ) ) . ToList ( ) ;
102+
103+ if ( validPaths . Count == 0 )
104+ {
105+ if ( curLoc == Goal ) return runLength ;
106+ else return 0 ;
107+ }
108+ else if ( validPaths . Count >= 2 ) break ;
109+
110+ curLoc = validPaths . Single ( ) ;
111+ locVisited . Add ( curLoc ) ;
112+ runLength ++ ;
113+
114+ }
115+
116+ int maxLength = - 1 ;
117+ foreach ( var n in validPaths )
118+ {
119+ int path = FindLongestPath ( n , Goal , locVisited , SlopesAreSlippery ) ;
120+ if ( path > maxLength )
121+ {
122+ maxLength = path ;
123+ res = runLength + path + 1 ;
124+ }
125+ }
126+
127+
128+ return res ;
30129 }
31130 }
32- }
131+ }
0 commit comments