chore(day23): solution for day23 pt1/pt2 #22
							
								
								
									
										23
									
								
								day23/example.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								day23/example.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
#.#####################
 | 
			
		||||
#.......#########...###
 | 
			
		||||
#######.#########.#.###
 | 
			
		||||
###.....#.>.>.###.#.###
 | 
			
		||||
###v#####.#v#.###.#.###
 | 
			
		||||
###.>...#.#.#.....#...#
 | 
			
		||||
###v###.#.#.#########.#
 | 
			
		||||
###...#.#.#.......#...#
 | 
			
		||||
#####.#.#.#######.#.###
 | 
			
		||||
#.....#.#.#.......#...#
 | 
			
		||||
#.#####.#.#.#########v#
 | 
			
		||||
#.#...#...#...###...>.#
 | 
			
		||||
#.#.#v#######v###.###v#
 | 
			
		||||
#...#.>.#...>.>.#.###.#
 | 
			
		||||
#####v#.#.###v#.#.###.#
 | 
			
		||||
#.....#...#...#.#.#...#
 | 
			
		||||
#.#########.###.#.#.###
 | 
			
		||||
#...###...#...#...#.###
 | 
			
		||||
###.###.#.###v#####v###
 | 
			
		||||
#...#...#.#.>.>.#.>.###
 | 
			
		||||
#.###.###.#.###.#.#v###
 | 
			
		||||
#.....###...###...#...#
 | 
			
		||||
#####################.#
 | 
			
		||||
							
								
								
									
										141
									
								
								day23/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								day23/input.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
			
		||||
#.###########################################################################################################################################
 | 
			
		||||
#.#...#.......#...#.....#...#...#######...###...#...#.......#...#...#...#...#...#...#...###...###...###...............#.....#...#######...###
 | 
			
		||||
#.#.#.#.#####.#.#.#.###.#.#.#.#.#######.#.###.#.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#############.#.###.#.#.#######.#.###
 | 
			
		||||
#.#.#.#.#.....#.#.#...#.#.#...#...#.....#...#.#.#.#.#.....#...#.#.#.#.#.#.#.#.#...#...#.....#.#...#...#.............#.#...#...#.......#.#...#
 | 
			
		||||
#.#.#.#.#.#####.#.###.#.#.#######.#.#######.#.#.#.#.#####.#####.#.#.#.#.#.#.#.###############.#.#####.#############.#.###.###########.#.###.#
 | 
			
		||||
#...#...#.....#.#.###.#.#.#.......#.....#...#.#.#.#.#.>.>.#.....#.#.#.#.#.#.#...#.............#.#.....#...#.......#.#.....#...........#.#...#
 | 
			
		||||
#############.#.#v###.#.#.#.###########.#.###.#.#.#.#.#v###.#####.#.#.#.#.#.###.#.#############.#.#####.#.#.#####.#.#######.###########.#.###
 | 
			
		||||
#...###...###...#.>.#.#.#.#.#...###.....#.....#.#.#...#...#.#...#.#.#.#.#.#.###.#.#####...###...#...#...#.#...#...#.....#...#...###...#.#.###
 | 
			
		||||
#.#.###.#.#######v#.#.#.#.#.#.#.###.###########.#.#######.#.#.#.#.#.#.#.#.#.###.#.#####.#.###.#####.#.###.###.#.#######.#.###.#.###.#.#.#.###
 | 
			
		||||
#.#.#...#.#.....#.#.#.#.#.#...#...#.........#...#.###.....#.#.#.#.#.#.#.#.#.>.>.#.......#.#...#.....#...#.#...#.#.......#...#.#.....#.#.#.###
 | 
			
		||||
#.#.#.###.#.###.#.#.#.#.#.#######.#########.#.###.###.#####.#.#.#.#.#.#.#.###v###########.#.###.#######.#.#.###.#.#########.#.#######.#.#.###
 | 
			
		||||
#.#.#...#.#...#.#.#.#.#.#...#.....#...#...#.#...#...#.....#.#.#.#.#.#.#...###.#...........#...#.....#...#.#...#.#.........#.#.#.......#.#.###
 | 
			
		||||
#.#.###.#.###.#.#.#.#.#.###.#.#####.#.#.#.#.###.###.#####.#.#.#.#.#.#.#######.#.#############.#####.#.###.###.#.#########.#.#.#.#######.#.###
 | 
			
		||||
#.#.....#.#...#.#.#.#.#.#...#.....#.#...#.#...#.#...#.....#...#...#.#.#.......#.#.....#.....#.#.....#...#.###.#.#...#.....#...#.#...###.#.###
 | 
			
		||||
#.#######.#.###.#.#.#.#.#.#######.#.#####.###.#.#.###.#############.#.#.#######.#.###.#.###.#.#.#######.#.###.#.#.#.#.#########.#.#.###.#.###
 | 
			
		||||
#.#...###...###.#.#...#.#...#.....#.#...#...#.#.#...#...........###...#.......#.#.#...#...#.#.#.#...###.#.###.#.#.#.#.....#.....#.#.#...#...#
 | 
			
		||||
#.#.#.#########.#.#####.###.#.#####.#.#.###.#.#.###.###########.#############.#.#.#.#####.#.#.#.#.#.###.#.###.#.#.#.#####.#.#####.#.#.#####.#
 | 
			
		||||
#.#.#.........#...#.....#...#.#...#...#...#...#.....#####.......#...###.......#.#.#.#.....#.#.#.#.#.#...#.>.>.#.#.#.#.....#...#...#...###...#
 | 
			
		||||
#.#.#########.#####.#####.###.#.#.#######.###############.#######.#.###.#######.#.#.#.#####.#.#.#.#.#.#####v###.#.#.#.#######.#.#########.###
 | 
			
		||||
#...#.......#.#...#...#...###.#.#.>.>...#...#...#...###...###...#.#...#.......#.#.#...###...#.#.#.#.#...#...###...#...###.....#.###.......###
 | 
			
		||||
#####.#####.#.#.#.###.#.#####.#.###v###.###.#.#.#.#.###.#####.#.#.###.#######.#.#.#######.###.#.#.#.###.#.###############.#####.###.#########
 | 
			
		||||
#...#.....#...#.#.###...#####...#...###.....#.#.#.#.#...#...#.#...#...#.......#.#.#.....#.....#.#.#.....#...#...........#.#...#...#...#.....#
 | 
			
		||||
#.#.#####.#####.#.###############.###########.#.#.#.#.###.#.#.#####.###.#######.#.#.###.#######.#.#########.#.#########.#.#.#.###.###.#.###.#
 | 
			
		||||
#.#.......#...#.#.#...#...###...#.....#.......#.#.#...#...#...#.....###.......#...#...#.#.....#.#...#...###...#.........#...#.#...###...#...#
 | 
			
		||||
#.#########.#.#.#.#.#.#.#.###.#.#####.#.#######.#.#####.#######.#############.#######.#.#.###.#.###.#.#.#######.#############.#.#########.###
 | 
			
		||||
#.........#.#.#.#.#.#.#.#...#.#.......#.#.......#.......###.....#...#.........###...#.#.#.#...#.....#.#.#...###.............#...#...#...#...#
 | 
			
		||||
#########.#.#.#.#.#.#.#.###.#.#########.#.#################.#####.#.#.###########.#.#.#.#.#.#########.#.#.#.###############.#####.#.#.#.###.#
 | 
			
		||||
#.........#.#.#.#.#.#.#...#.#.......###.#.#...#...#...#...#.....#.#.#.......#...#.#...#.#.#...#.......#.#.#...#.............#...#.#...#.....#
 | 
			
		||||
#.#########.#.#.#.#.#.###.#.#######v###.#.#.#.#.#.#.#.#.#.#####v#.#.#######.#.#.#.#####.#.###.#.#######.#.###.#.#############.#.#.###########
 | 
			
		||||
#...........#.#.#...#.#...#...#...>.>.#.#...#.#.#...#.#.#...#.>.>.#.#...###.#.#.#.....#.#.#...#.......#.#...#.#...#...#...###.#.#...........#
 | 
			
		||||
#############.#.#####.#.#####.#.###v#.#.#####.#.#####.#.###.#.#v###.#.#.###v#.#.#####.#.#.#.#########.#.###.#.###v#.#.#.#.###.#.###########.#
 | 
			
		||||
#...#...#.....#.....#.#.#.....#.#...#.#.....#.#...###...#...#.#...#.#.#.#.>.>.#.#...#.#.#.#...#.......#...#.#.#.>.>.#...#...#.#...#.........#
 | 
			
		||||
#.#.#.#.#.#########.#.#.#.#####.#.###.#####.#.###.#######.###.###.#.#.#.#.#v###.#.#.#.#.#.###.#.#########.#.#.#.#v#########.#.###.#.#########
 | 
			
		||||
#.#...#.#.#####...#.#.#.#.#.....#...#...#...#.#...#.....#...#...#.#...#...#.###...#...#...#...#.......###...#...#.#...#...#.#.#...#...#...###
 | 
			
		||||
#.#####.#.#####.#.#.#.#.#.#.#######.###.#.###.#.###.###.###.###.#.#########.###############.#########.###########.#.#.#.#.#.#.#.#####.#.#.###
 | 
			
		||||
#.....#...###...#.#.#...#...#.....#...#.#.#...#.....#...###.....#.....#.....#...#...#...###...#.......#...#...###.#.#...#...#.#...###...#...#
 | 
			
		||||
#####.#######.###.#.#########.###.###.#.#.#.#########.###############.#.#####.#.#.#.#.#.#####.#.#######.#.#.#.###.#.#########.###.#########.#
 | 
			
		||||
#.....#...#...###...#...#.....###...#.#.#.#.#...#...#...#.............#...#...#...#...#.....#.#.....#...#...#...#.#.###...###...#.#...#.....#
 | 
			
		||||
#.#####.#.#.#########.#.#.#########.#.#.#.#.#.#.#.#.###.#.###############.#.###############.#.#####.#.#########.#.#.###.#.#####.#.#.#.#.#####
 | 
			
		||||
#.....#.#...#####.....#.#.........#...#.#.#.#.#...#.#...#...............#...#...............#.#.....#.#.....#...#.#.#...#.#...#.#.#.#.#...###
 | 
			
		||||
#####.#.#########.#####.#########.#####.#.#.#.#####.#.#################.#####.###############.#.#####.#.###.#.###.#.#.###.#.#.#.#.#.#.###v###
 | 
			
		||||
#...#.#.........#.#...#...........#...#...#.#.....#.#.#.................#.....#.....#.......#.#.....#...#...#.....#.#.###.#.#.#.#.#.#.#.>.###
 | 
			
		||||
#.#.#v#########.#.#.#.#############.#.#####.#####.#.#.#.#################.#####.###.#.#####.#.#####.#####.#########.#.###.#.#.#.#.#.#.#.#v###
 | 
			
		||||
#.#.#.>...#.....#...#...............#.....#.#...#.#...#.#...#...........#.#.....###...#.....#.......#...#.........#.#...#.#.#...#.#.#...#...#
 | 
			
		||||
#.#.#v###.#.#############################.#.#.#.#.#####.#.#.#.#########.#.#.###########.#############.#.#########.#.###.#.#.#####.#.#######.#
 | 
			
		||||
#.#.#...#.#.......#.......................#...#...#...#...#...#...#.....#.#.#...........#...#...###...#...........#.#...#.#.#.....#.#.......#
 | 
			
		||||
#.#.###.#.#######.#.###############################.#.#########.#.#.#####.#.#.###########.#.#.#.###.###############.#.###.#.#.#####.#.#######
 | 
			
		||||
#.#.....#.........#...#...#.........###...#...#...#.#.#.........#...#...#...#.#...........#.#.#...#.........#.....#...###.#.#.#.....#.#.....#
 | 
			
		||||
#.###################.#.#.#.#######.###.#.#.#.#.#.#.#.#.#############.#.#####.#.###########.#.###.#########.#.###.#######.#.#.#.#####.#.###.#
 | 
			
		||||
#...#...###.....#...#...#.#.#.......#...#...#.#.#.#.#.#.............#.#.....#...#...........#.#...#.........#...#.....###...#...#...#...#...#
 | 
			
		||||
###.#.#.###.###.#.#.#####.#.#.#######.#######.#.#.#.#.#############.#.#####.#####.###########.#.###.###########.#####.###########.#.#####.###
 | 
			
		||||
#...#.#...#...#.#.#.#.....#.#.....###.#.......#.#...#...#...#...###...#.....#...#.......#...#.#.###.......###...#.....#...#.....#.#...###...#
 | 
			
		||||
#.###.###.###.#.#.#.#.#####.#####.###.#.#######.#######.#.#.#.#.#######.#####.#.#######.#.#.#.#.#########v###.###.#####.#.#.###.#.###.#####.#
 | 
			
		||||
#.....###.....#.#.#.#.......#...#...#.#.....###.......#.#.#...#.#.......#####.#.........#.#.#.#...#.....>.>.#...#.#...#.#.#.#...#...#.###...#
 | 
			
		||||
###############.#.#.#########.#.###.#.#####.#########.#.#.#####.#.###########.###########.#.#.###.#.#####v#.###.#.#.#.#.#.#.#.#####.#.###v###
 | 
			
		||||
#...............#.#.#.......#.#.....#.#.....#...#...#.#.#.....#.#...........#...#...#...#.#.#.#...#.....#.#.....#.#.#.#.#.#.#...#...#...>.###
 | 
			
		||||
#.###############.#.#.#####.#.#######.#.#####.#.#.#.#.#.#####.#.###########.###.#.#.#.#.#.#.#.#.#######.#.#######.#.#.#.#.#.###.#.#######v###
 | 
			
		||||
#...#.....#...###.#.#.....#.#.#...###.#.#...#.#.#.#.#.#.#...#.#.###.........###...#...#.#.#...#...#.....#.....#...#.#...#.#...#.#.#.....#.###
 | 
			
		||||
###.#.###.#.#.###.#.#####.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###v###################.#.#######.#.#########.#.###.#####.###.#.#.#.###.#.###
 | 
			
		||||
###...###.#.#.#...#.#.....#...#.#.#...#.#.#.#.#.#.#.#.#.#.#...#...>.>.........#...#.....#.....#...#...#.......#.....#.....#...#...#...#...###
 | 
			
		||||
#########v#.#.#.###.#.#########.#.#.###.#.#.#.#.#.#.#.#.#.#########v#########.#.#.#.#########.#.#####.#.#############.#####.#########.#######
 | 
			
		||||
#...#...#.>.#.#...#.#.........#.#.#.#...#.#.#.#.#.#.#.#.#.#.........###.......#.#.#.....#.....#.....#.#...#.........#...#...#.........#...###
 | 
			
		||||
#.#.#.#.#v###.###.#.#########.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###########.#######.#.#####.#.#########.#.###.#.#######.###.#.###.#########.#.###
 | 
			
		||||
#.#...#...###.....#.#...#.....#.#...#...#.#.#.#.#.#...#...#...#.....#...#.....#.#.#.....#.......###.#.###...#...#...#...#...#.#...#.....#...#
 | 
			
		||||
#.#################.#.#.#.#####.#######.#.#.#.#.#.###########.#.###.#.###.###.#.#.#.###########.###.#.#######.#.#.###.#####.#.#.#.#.#######.#
 | 
			
		||||
#.............#.....#.#.#.....#.....###...#.#.#.#.###...#...#...#...#...#.#...#.#.#.#.....#...#...#.#.#.......#...###...#...#...#...#.......#
 | 
			
		||||
#############.#.#####.#.#####v#####.#######.#.#.#.###.#.#.#.#####.#####.#.#.###.#.#v#.###.#.#.###.#.#.#.###############.#.###########.#######
 | 
			
		||||
#.............#.#...#.#...#.>.>.....#.....#.#.#.#.#...#...#.......#####.#.#.....#.>.>.###.#.#.....#.#.#.......#.....###.#...#.......#.......#
 | 
			
		||||
#.#############.#.#.#.###.#.#v#######.###.#.#.#.#.#.###################.#.#########v#####.#.#######.#.#######.#.###.###.###.#.#####.#######.#
 | 
			
		||||
#.........#...#...#.#.###.#.#.........#...#...#...#.......#.........#...#...#.......#...#...#...###.#.#.....#...#...#...#...#.....#.........#
 | 
			
		||||
#########.#.#.#####.#.###.#.###########.#################.#.#######.#.#####.#.#######.#.#####.#.###.#.#.###.#####.###.###.#######.###########
 | 
			
		||||
#.........#.#.#...#...###...#.........#.#...#...#.......#...#...#...#.#.....#.......#.#.......#...#...#...#.#...#...#.....#...###...........#
 | 
			
		||||
#.#########.#.#.#.###########.#######.#.#.#.#.#.#.#####.#####.#.#.###.#.###########.#.###########.#######.#.#.#.###.#######.#.#############.#
 | 
			
		||||
#...#...#...#.#.#.#...#.......#...###...#.#.#.#.#.....#...#...#...###...#...###...#.#.#...........#...#...#...#.....#...###.#.#...#.......#.#
 | 
			
		||||
###.#.#.#.###.#.#v#.#.#.#######.#.#######.#.#.#.#####.###.#.#############.#.###.#.#.#.#.###########.#.#.#############.#.###.#.#.#.#.#####.#.#
 | 
			
		||||
#...#.#.#.#...#.#.>.#.#.....#...#...#...#.#.#.#.#...#.#...#.......#...#...#.#...#.#...#.....#.....#.#...#.....###...#.#.#...#.#.#.#...###...#
 | 
			
		||||
#.###.#.#.#.###.#v###.#####.#.#####.#.#.#.#.#.#.#.#.#.#.#########.#.#.#.###.#.###.#########.#.###.#.#####.###.###.#.#.#.#.###.#.#.###v#######
 | 
			
		||||
#.....#.#.#...#.#.#...#...#...###...#.#.#.#.#.#.#.#...#.#.......#.#.#.#...#.#...#.###...#...#.#...#...#...###...#.#...#.#...#.#.#...>.###...#
 | 
			
		||||
#######.#.###.#.#.#.###.#.#######.###.#.#.#.#.#.#.#####.#.#####.#.#.#.###.#.###.#.###.#.#v###.#.#####.#.#######.#.#####.###.#.#.#####v###.#.#
 | 
			
		||||
#...###...###...#.#...#.#...#...#.###.#.#.#.#.#.#.....#.#.#.....#.#.#.#...#...#.#.#...#.>.>.#.#.....#...#.......#.#.....#...#.#...#...###.#.#
 | 
			
		||||
#.#.#############.###.#.###.#.#.#v###.#.#.#.#.#.#####.#.#.#.#####v#.#.#.#####.#.#.#.#####v#.#.#####.#####.#######.#.#####.###.###.#.#####.#.#
 | 
			
		||||
#.#.#...#.....#...###.#.#...#.#.>.>.#.#.#.#.#.#...#...#.#.#.#...>.>.#.#.....#.#.#.#.#.....#...#.....#...#.....#...#.....#...#.#...#.......#.#
 | 
			
		||||
#.#.#.#.#.###.#.#####.#.#.###.###v#.#.#.#.#.#.###.#.###.#.#.#.###v###.#####.#.#.#.#.#.#########.#####.#.#####.#.#######.###.#.#.###########.#
 | 
			
		||||
#.#.#.#.#...#.#...#...#.#...#.#...#...#.#.#.#.###...#...#.#.#.#...###...#...#.#.#.#.#.......#...###...#...###.#.......#.#...#.#.#.....#...#.#
 | 
			
		||||
#.#.#.#.###.#.###.#.###.###.#.#.#######.#.#.#.#######.###.#.#.#.#######.#.###.#.#.#.#######.#.#####.#####.###.#######.#.#.###.#.#.###.#.#.#.#
 | 
			
		||||
#.#...#.#...#.#...#...#...#...#.......#.#.#.#...#.....#...#...#.......#.#...#...#...#...#...#.......#.....#...#...#...#.#.###...#...#...#...#
 | 
			
		||||
#.#####.#.###.#.#####.###.###########.#.#.#.###.#.#####.#############.#.###.#########.#.#.###########.#####.###.#.#.###.#.#########.#########
 | 
			
		||||
#.#...#...###...#.....#...#...........#...#.....#...#...#...#...#...#.#.#...#...#...#.#.#...#.........#...#...#.#.#...#...#####...#.........#
 | 
			
		||||
#.#.#.###########.#####.###.#######################.#.###.#.#.#.#.#.#.#.#.###.#.#.#.#.#.###.#.#########.#.###v#.#.###.#########.#.#########.#
 | 
			
		||||
#...#.........###.....#...#.......###...#.........#...#...#...#...#.#.#...#...#...#...#.....#.....#...#.#.#.>.>.#...#.#.........#...........#
 | 
			
		||||
#############.#######.###.#######.###.#.#.#######.#####.###########.#.#####.#####################.#.#.#.#.#.#v#####.#.#.#####################
 | 
			
		||||
#.............#...###.....#.....#.....#...#...#...#.....#.......#...#.#...#.................#.....#.#...#...#...###...#.#...#...#.......#...#
 | 
			
		||||
#.#############.#.#########.###.###########.#.#.###.#####.#####.#.###.#.#.#################.#.#####.###########.#######.#.#.#.#.#.#####.#.#.#
 | 
			
		||||
#.#.....#...###.#.....#...#...#...........#.#...###.......#...#.#...#.#.#.#.........#...#...#...#...#.......#...#...###...#...#...#...#...#.#
 | 
			
		||||
#.#.###.#.#.###.#####.#.#.###.###########.#.###############.#.#.###.#.#.#.#.#######.#.#.#.#####.#.###.#####.#.###.#.###############.#.#####.#
 | 
			
		||||
#...###...#...#...#...#.#.###.........#...#.......#.........#.#.#...#.#.#.#.......#.#.#.#.#...#...###.....#.#.....#...#.............#.....#.#
 | 
			
		||||
#############.###.#.###.#.###########.#.#########.#.#########.#.#.###.#.#.#######.#.#.#.#.#.#.###########.#.#########.#.#################.#.#
 | 
			
		||||
#...###.......#...#...#.#.#...........#.....#.....#.........#...#.....#.#.........#.#.#.#.#.#.............#...#.......#.................#.#.#
 | 
			
		||||
#.#.###v#######.#####.#.#.#.###############.#.#############.###########.###########.#.#.#.#.#################.#.#######################.#.#.#
 | 
			
		||||
#.#...#.>.#.....#.....#.#.#...............#.#...#...#######.....#...###...........#.#.#.#.#.#.......#...#####...###.....#...#...###.....#.#.#
 | 
			
		||||
#.###.#v#.#.#####.#####.#.###############.#.###.#.#.###########.#.#.#############.#.#.#.#.#.#.#####.#.#.###########.###.#.#.#.#.###.#####.#.#
 | 
			
		||||
#...#...#...#.....#...#.#...#.............#.#...#.#.###.........#.#.#...###.......#...#...#...###...#.#...#...#...#...#.#.#.#.#...#.....#...#
 | 
			
		||||
###.#########.#####.#.#.###.#.#############.#.###.#.###.#########.#.#.#.###.#####################.###.###.#.#.#.#.###.#.#.#.#.###.#####.#####
 | 
			
		||||
#...#.......#.....#.#.#.#...#.....#...#...#...###.#...#.......#...#...#...#.........#...#...#...#.....#...#.#.#.#.###.#.#.#.#.#...#.....#...#
 | 
			
		||||
#.###.#####.#####.#.#.#.#.#######.#.#.#.#.#######.###.#######.#.#########.#########.#.#.#.#.#.#.#######.###.#.#.#.###.#.#.#.#.#.###v#####.#.#
 | 
			
		||||
#.....#.....#...#...#...#...#.....#.#...#.#.......#...#.......#...#.......#.........#.#.#.#.#.#.#...###.###.#.#.#.#...#.#.#.#.#.#.>.###...#.#
 | 
			
		||||
#######.#####.#.###########.#.#####.#####.#.#######.###.#########.#.#######.#########.#.#.#.#.#.#.#.###v###.#.#.#.#.###.#.#.#.#.#.#v###.###.#
 | 
			
		||||
#.......#.....#.#...#.......#.......#.....#.......#.###.....#...#.#...#...#.....###...#.#.#.#.#.#.#.#.>.>...#.#.#...###.#.#.#.#...#...#.#...#
 | 
			
		||||
#.#######.#####.#.#.#.###############.###########.#.#######.#.#.#.###.#.#.#####.###.###.#.#.#.#.#.#.#.#v#####.#.#######.#.#.#.#######.#.#.###
 | 
			
		||||
#.......#.#.....#.#.#.....#.....#.....#...#...#...#...#...#.#.#.#.#...#.#.#...#.#...###.#.#...#.#.#...#.....#.#.......#.#.#.#...#.....#.#...#
 | 
			
		||||
#######.#.#.#####.#.#####.#.###.#.#####.#.#.#.#.#####.#.#.#.#.#.#.#.###.#.#.#.#v#.#####.#.#####.#.#########.#.#######.#.#.#.###.#.#####.###.#
 | 
			
		||||
#.......#.#...#...#...#...#...#.#.#...#.#.#.#.#...#...#.#.#.#.#.#.#...#.#.#.#.>.>.###...#.....#.#.###.......#.#.......#.#.#.#...#.......#...#
 | 
			
		||||
#.#######.###.#.#####.#.#####.#.#v#.#.#.#.#.#.###.#.###.#.#v#.#.#.###.#.#.#.###v#####.#######.#.#.###.#######.#.#######.#.#.#.###########.###
 | 
			
		||||
#...#...#...#.#.#.....#.#...#.#.>.>.#.#.#...#.#...#...#.#.>.>.#.#.#...#.#...###.....#...#...#.#.#.#...#.....#.#.....###...#.#...#.........###
 | 
			
		||||
###.#.#.###.#.#.#.#####.#.#.#.###v###.#.#####.#.#####.#.###v###.#.#.###.###########.###.#.#.#.#.#.#.###.###.#.#####.#######.###.#.###########
 | 
			
		||||
###.#.#.#...#...#.....#...#...###.#...#.....#...#.....#.###...#...#.....#...#...#...#...#.#.#.#.#.#...#.#...#...#...#...###.....#...........#
 | 
			
		||||
###.#.#.#.###########.###########.#.#######.#####.#####.#####.###########.#.#.#.#.###.###.#.#.#.#.###.#.#.#####.#.###.#.###################.#
 | 
			
		||||
#...#.#.#.#...........###...#.....#...#...#.....#.#.....#####.......#.....#...#.#...#.#...#...#...###...#.....#.#.###.#.#...#...#...........#
 | 
			
		||||
#.###.#.#.#.#############.#.#.#######.#.#.#####.#.#.###############.#.#########.###.#.#.#####################.#.#.###.#.#.#.#.#.#.###########
 | 
			
		||||
#...#.#.#.#.#...........#.#.#.#.....#.#.#.#.....#...#...............#...#...###.....#.#...#.................#.#.#.#...#...#.#.#.#.........###
 | 
			
		||||
###.#.#.#.#.#.#########.#.#.#.#.###.#.#.#.#.#########.#################.#.#.#########.###.#.###############.#.#.#.#.#######.#.#.#########.###
 | 
			
		||||
###.#.#.#.#.#.#.......#...#.#...#...#.#.#.#...#...#...#...#.......#...#...#.........#.....#...............#...#...#...#.....#.#.#...#...#...#
 | 
			
		||||
###.#.#.#.#.#.#.#####.#####.#####.###.#.#.###.#.#.#.###.#.#.#####.#.#.#############.#####################.###########.#.#####.#.#.#.#v#.###.#
 | 
			
		||||
###.#.#.#.#...#.....#.#...#.#...#.###...#.....#.#.#...#.#...#.....#.#.#.............###...#...#.....#...#.#.......#...#...#...#.#.#.>.#.....#
 | 
			
		||||
###.#.#.#.#########.#.#.#.#.#.#.#.#############.#.###.#.#####.#####.#.#.###############.#.#.#.#.###.#.#.#.#.#####.#.#####.#.###.#.###v#######
 | 
			
		||||
###...#...#.....#...#...#...#.#.#...........###.#.###...#.....###...#.#.......#.......#.#.#.#.#...#...#.#.#.....#...###...#...#...#...#...###
 | 
			
		||||
###########.###.#.###########.#.###########.###.#.#######.#######.###.#######.#.#####.#.#.#.#.###.#####.#.#####.#######.#####.#####.###.#.###
 | 
			
		||||
#.......###...#...#...###.....#.............#...#.......#.......#.#...#...#...#.#.....#.#.#.#.###.....#...#...#.......#.......#...#.....#...#
 | 
			
		||||
#.#####.#####.#####.#.###.###################.#########.#######.#.#.###.#.#.###.#.#####.#.#.#.#######.#####.#.#######.#########.#.#########.#
 | 
			
		||||
#.....#.......#...#.#...#.........#...###...#...#.......#...#...#.#...#.#...#...#.#...#.#.#.#.#...#...#...#.#.###...#...###.....#...........#
 | 
			
		||||
#####.#########.#.#.###.#########v#.#.###.#.###.#.#######.#.#.###.###.#.#####.###.#.#.#.#.#.#.#.#.#.###.#.#.#.###.#.###.###.#################
 | 
			
		||||
#.....#.......#.#.#.###...#...#.>.>.#...#.#.#...#...#.....#...###...#.#.....#.#...#.#.#.#.#.#.#.#.#...#.#.#.#.#...#.....#...#.....#.....#####
 | 
			
		||||
#.#####.#####.#.#.#.#####.#.#.#.#######.#.#.#.#####.#.#############.#.#####v#.#.###.#.#.#.#.#.#.#.###v#.#.#.#.#.#########.###.###.#.###.#####
 | 
			
		||||
#.....#.#.....#.#.#.#####.#.#...#.......#.#.#...#...#.........###...#.#...>.>.#.#...#.#.#...#.#.#...>.>.#.#.#.#.........#...#.#...#.###...###
 | 
			
		||||
#####.#.#.#####.#.#.#####.#.#####.#######.#.###.#.###########v###.###.#.#######.#.###.#.#####.#.#########.#.#.#########.###.#.#.###.#####.###
 | 
			
		||||
#####...#.....#.#...#.....#.....#.......#.#...#.#...#...#...>.>.#.###.#.....###.#.###.#.###...#.......#...#.#.#.......#.#...#.#.....#...#...#
 | 
			
		||||
#############.#.#####.#########.#######.#.###.#.###.#.#.#.#####.#.###.#####.###.#.###.#.###.#########.#.###.#.#.#####.#.#.###.#######.#.###.#
 | 
			
		||||
#.............#...#...#...#.....#.......#.#...#...#.#.#.#.....#.#.#...#.....#...#...#.#...#.....#.....#...#.#.#.....#.#.#...#.#.......#.....#
 | 
			
		||||
#.###############.#.###.#.#.#####.#######.#.#####.#.#.#.#####.#.#.#.###.#####.#####.#.###.#####.#.#######.#.#.#####.#.#.###.#.#.#############
 | 
			
		||||
#.................#.....#...#####.........#.......#...#.......#...#.....#####.......#.....#####...#######...#.......#...###...#.............#
 | 
			
		||||
###########################################################################################################################################.#
 | 
			
		||||
							
								
								
									
										236
									
								
								day23/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								day23/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,236 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	_ "embed"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var log = aoc.Log
 | 
			
		||||
 | 
			
		||||
func main() { aoc.MustResult(aoc.Runner(run)) }
 | 
			
		||||
 | 
			
		||||
type result struct {
 | 
			
		||||
	valuePT1 int
 | 
			
		||||
	valuePT2 int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r result) String() string { return fmt.Sprintf("%#v", r) }
 | 
			
		||||
 | 
			
		||||
func run(scan *bufio.Scanner) (*result, error) {
 | 
			
		||||
	var m aoc.Map[int16, rune]
 | 
			
		||||
 | 
			
		||||
	start := Point{0, 0}
 | 
			
		||||
	target := Point{0, 0}
 | 
			
		||||
	var text string
 | 
			
		||||
	for scan.Scan() {
 | 
			
		||||
		text = scan.Text()
 | 
			
		||||
		if start == target {
 | 
			
		||||
			start[1] = int16(strings.IndexRune(text, '.'))
 | 
			
		||||
		}
 | 
			
		||||
		m = append(m, []rune(text))
 | 
			
		||||
	}
 | 
			
		||||
	target[0] = int16(len(m) - 1)
 | 
			
		||||
	target[1] = int16(strings.IndexRune(text, '.'))
 | 
			
		||||
 | 
			
		||||
	result := &result{}
 | 
			
		||||
 | 
			
		||||
	result.valuePT1 = search(&graph{m: m, start: start, target: target, neighbors: part1nbs})
 | 
			
		||||
	result.valuePT2 = search(&graph{m: m, start: start, target: target, neighbors: part2nbs})
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Point = aoc.Point[int16]
 | 
			
		||||
type Map = aoc.Map[int16, rune]
 | 
			
		||||
 | 
			
		||||
// diretion of path steps
 | 
			
		||||
type direction int8
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	U = Point{-1, 0}
 | 
			
		||||
	R = Point{0, 1}
 | 
			
		||||
	D = Point{1, 0}
 | 
			
		||||
	L = Point{0, -1}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var directions = []Point{U, R, D, L}
 | 
			
		||||
 | 
			
		||||
var dirIDX = func() map[Point]direction {
 | 
			
		||||
	m := make(map[Point]direction, len(directions))
 | 
			
		||||
	for k, v := range directions {
 | 
			
		||||
		m[v] = direction(k)
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}()
 | 
			
		||||
 | 
			
		||||
var arrows = []rune{'^', '>', 'v', '<'}
 | 
			
		||||
 | 
			
		||||
var arrowIDX = func() map[rune]Point {
 | 
			
		||||
	m := make(map[rune]Point, len(arrows))
 | 
			
		||||
	for k, v := range arrows {
 | 
			
		||||
		m[v] = directions[k]
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}()
 | 
			
		||||
 | 
			
		||||
// position on the map
 | 
			
		||||
type position struct {
 | 
			
		||||
	loc       Point
 | 
			
		||||
	direction Point
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p position) step(to Point) position {
 | 
			
		||||
	return position{p.loc.Add(to), to}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// implements FindPath graph interface
 | 
			
		||||
type graph struct {
 | 
			
		||||
	m      Map
 | 
			
		||||
	start  Point
 | 
			
		||||
	target Point
 | 
			
		||||
 | 
			
		||||
	neighbors func(g *graph, current position) []position
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Neighbors returns valid steps from given position. if at target returns none.
 | 
			
		||||
func (g *graph) Neighbors(current position) []position {
 | 
			
		||||
	return g.neighbors(g, current)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cost calculates heat cost to neighbor from map
 | 
			
		||||
func (g *graph) Cost(a, b position) int16 {
 | 
			
		||||
	return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (g *graph) Target(a position, c int16) bool {
 | 
			
		||||
	return a.loc == g.target
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (g *graph) Seen(a position) position {
 | 
			
		||||
	a.direction = Point{}
 | 
			
		||||
	return a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func match[T comparable](match T, lis ...T) bool {
 | 
			
		||||
	for _, b := range lis {
 | 
			
		||||
		if b == match {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func search(g *graph) int {
 | 
			
		||||
	costs, paths := aoc.FindPaths[int16, position](g, position{loc: g.start}, position{loc: g.target})
 | 
			
		||||
 | 
			
		||||
	for i, path := range paths {
 | 
			
		||||
		log("path length = ", costs[i])
 | 
			
		||||
		printGraph(g.m, path)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return int(aoc.Max(0, costs...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// printGraph with the path overlay
 | 
			
		||||
func printGraph(m Map, path []position) {
 | 
			
		||||
	pts := make(map[Point]position, len(path))
 | 
			
		||||
	for _, pt := range path {
 | 
			
		||||
		pts[pt.loc] = pt
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for r, row := range m {
 | 
			
		||||
		for c, x := range row {
 | 
			
		||||
			if _, ok := pts[Point{int16(r), int16(c)}]; ok {
 | 
			
		||||
				if x == '.' {
 | 
			
		||||
					fmt.Print("*")
 | 
			
		||||
				} else {
 | 
			
		||||
					fmt.Print(string(x))
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Print(".")
 | 
			
		||||
			_ = x
 | 
			
		||||
			// fmt.Print(string(x))
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Println("")
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opposite(d Point) Point {
 | 
			
		||||
	return directions[(dirIDX[d]+2)%4]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func part1nbs(g *graph, current position) []position {
 | 
			
		||||
	var nbs []position
 | 
			
		||||
 | 
			
		||||
	if current.loc == g.start {
 | 
			
		||||
		return []position{
 | 
			
		||||
			{current.loc.Add(D), D},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if current.loc == g.target {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// only one direction on arrow.
 | 
			
		||||
	_, r, _ := g.m.Get(current.loc)
 | 
			
		||||
	if match(r, arrows...) {
 | 
			
		||||
		to := arrowIDX[r]
 | 
			
		||||
		if next := current.step(to); g.m.Valid(next.loc) {
 | 
			
		||||
			_, r, _ := g.m.Get(next.loc)
 | 
			
		||||
			d := arrows[(dirIDX[to]+2)%4] // flow from opposite direction
 | 
			
		||||
			if !match(r, rune(d), '#') {
 | 
			
		||||
				nbs = append(nbs, next)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nbs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, to := range directions {
 | 
			
		||||
		if next := current.step(to); g.m.Valid(next.loc) {
 | 
			
		||||
			_, r, _ := g.m.Get(next.loc)
 | 
			
		||||
			d := arrows[(dirIDX[to]+2)%4] // flow from opposite direction
 | 
			
		||||
			if !match(r, rune(d), '#') {
 | 
			
		||||
				nbs = append(nbs, next)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nbs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func part2nbs(g *graph, current position) []position {
 | 
			
		||||
	var nbs []position
 | 
			
		||||
 | 
			
		||||
	if current.loc == g.start {
 | 
			
		||||
		return []position{
 | 
			
		||||
			{current.loc.Add(D), D},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if current.loc == g.target {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, to := range directions {
 | 
			
		||||
		if next := current.step(to); g.m.Valid(next.loc) {
 | 
			
		||||
			if next.direction == opposite(current.direction) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			_, r, _ := g.m.Get(next.loc)
 | 
			
		||||
			if r == '#' {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nbs = append(nbs, next)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nbs
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								day23/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								day23/main_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	_ "embed"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed example.txt
 | 
			
		||||
var example []byte
 | 
			
		||||
 | 
			
		||||
//go:embed input.txt
 | 
			
		||||
var input []byte
 | 
			
		||||
 | 
			
		||||
func TestExample(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
	scan := bufio.NewScanner(bytes.NewReader(example))
 | 
			
		||||
 | 
			
		||||
	result, err := run(scan)
 | 
			
		||||
	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
	t.Log(result)
 | 
			
		||||
	// is.Equal(result.valuePT1, 94)
 | 
			
		||||
	is.Equal(result.valuePT2, 154)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// func TestSolution(t *testing.T) {
 | 
			
		||||
// 	is := is.New(t)
 | 
			
		||||
// 	scan := bufio.NewScanner(bytes.NewReader(input))
 | 
			
		||||
 | 
			
		||||
// 	result, err := run(scan)
 | 
			
		||||
// 	is.NoErr(err)
 | 
			
		||||
 | 
			
		||||
// 	t.Log(result)
 | 
			
		||||
// 	is.True(result.valuePT1 > 1918)
 | 
			
		||||
// 	is.Equal(result.valuePT1, 2074)
 | 
			
		||||
// 	is.Equal(result.valuePT2, 0)
 | 
			
		||||
// }
 | 
			
		||||
							
								
								
									
										7
									
								
								grids.go
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								grids.go
									
									
									
									
									
								
							@ -2,7 +2,9 @@ package aoc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"cmp"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/exp/maps"
 | 
			
		||||
)
 | 
			
		||||
@ -110,7 +112,7 @@ func (m *cmap[C, N]) String() string {
 | 
			
		||||
	for k, nbs := range m.neighbors {
 | 
			
		||||
		fmt.Fprintln(b, k)
 | 
			
		||||
		for to, v := range nbs {
 | 
			
		||||
			fmt.Fprintln(b, "  ", to, k)
 | 
			
		||||
			fmt.Fprintln(b, "  ", to, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -136,13 +138,14 @@ func CompressMap[C number, N comparable](p pather[C, N], start N) pather[C, N] {
 | 
			
		||||
				to[b] = to[n] + p.Cost(n, b)
 | 
			
		||||
				delete(to, n)
 | 
			
		||||
				visited[a] = to
 | 
			
		||||
				continue
 | 
			
		||||
			} else if to, ok := visited[b]; ok {
 | 
			
		||||
				to[a] = to[n] + p.Cost(n, a)
 | 
			
		||||
				delete(to, n)
 | 
			
		||||
				visited[b] = to
 | 
			
		||||
			}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		visited[n] = make(map[N]C)
 | 
			
		||||
		next = append(next, nbs...)
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
package aoc_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
@ -27,7 +25,6 @@ func TestRepeat(t *testing.T) {
 | 
			
		||||
	is.Equal(aoc.Repeat(5, 3), []int{5, 5, 5})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func TestTranspose(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,11 @@
 | 
			
		||||
package aoc_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLCM(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								search.go
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								search.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
			
		||||
package aoc
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"maps"
 | 
			
		||||
	"math/bits"
 | 
			
		||||
	"sort"
 | 
			
		||||
)
 | 
			
		||||
@ -322,3 +323,105 @@ func (h *fibHeap[T]) cascadingCut(y *fibTree[T]) {
 | 
			
		||||
		h.cascadingCut(y.parent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindPath uses the A* path finding algorithem.
 | 
			
		||||
// g is the graph source that implements the pather interface.
 | 
			
		||||
//
 | 
			
		||||
//	C is an numeric type for calculating cost/potential
 | 
			
		||||
//	N is the node values. is comparable for storing in visited table for pruning.
 | 
			
		||||
//
 | 
			
		||||
// start, end are nodes that dileniate the start and end of the search path.
 | 
			
		||||
// The returned values are the calculated cost and the path taken from start to end.
 | 
			
		||||
func FindPaths[C integer, N comparable](g pather[C, N], start, end N) ([]C, [][]N) {
 | 
			
		||||
	var zero C
 | 
			
		||||
	// closed := make(map[N]bool)
 | 
			
		||||
 | 
			
		||||
	var potentialFn = func(N) C { var zero C; return zero }
 | 
			
		||||
	if p, ok := g.(interface{ Potential(N) C }); ok {
 | 
			
		||||
		potentialFn = p.Potential
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type node struct {
 | 
			
		||||
		cost      C
 | 
			
		||||
		potential C
 | 
			
		||||
		parent    *node
 | 
			
		||||
		position  N
 | 
			
		||||
		closed    map[N]bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	NewPath := func(n *node) []N {
 | 
			
		||||
		var path []N
 | 
			
		||||
		for n.parent != nil {
 | 
			
		||||
			path = append(path, n.position)
 | 
			
		||||
			n = n.parent
 | 
			
		||||
		}
 | 
			
		||||
		path = append(path, n.position)
 | 
			
		||||
 | 
			
		||||
		Reverse(path)
 | 
			
		||||
		return path
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	less := func(b, a *node) bool {
 | 
			
		||||
		return b.cost+b.potential < a.cost+a.potential
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pq := PriorityQueue(less)
 | 
			
		||||
	pq.Insert(&node{position: start, closed: make(map[N]bool)})
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		Log("queue max depth = ", pq.maxDepth, "total enqueue = ", pq.totalEnqueue, "total dequeue = ", pq.totalDequeue)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	var seenFn = func(a N) N { return a }
 | 
			
		||||
	if s, ok := g.(interface{ Seen(N) N }); ok {
 | 
			
		||||
		seenFn = s.Seen
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var targetFn = func(n N, c C) bool { return true }
 | 
			
		||||
	if s, ok := g.(interface{ Target(N, C) bool }); ok {
 | 
			
		||||
		targetFn = s.Target
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var paths [][]N
 | 
			
		||||
	var costs []C
 | 
			
		||||
 | 
			
		||||
	for !pq.IsEmpty() {
 | 
			
		||||
		current := pq.ExtractMin()
 | 
			
		||||
		cost, potential, n := current.cost, current.potential, current.position
 | 
			
		||||
 | 
			
		||||
		seen := seenFn(n)
 | 
			
		||||
		if current.closed[seen] {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		current.closed[seen] = true
 | 
			
		||||
 | 
			
		||||
		if cost > 0 && potential == zero && cost > Max(0, costs...) && targetFn(current.position, cost) {
 | 
			
		||||
			paths = append([][]N(nil), NewPath(current))
 | 
			
		||||
			costs = append([]C(nil), cost)
 | 
			
		||||
			Log("new record = ", cost)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, nb := range g.Neighbors(n) {
 | 
			
		||||
			seen := seenFn(nb)
 | 
			
		||||
			if current.closed[seen] {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cost := g.Cost(n, nb) + current.cost
 | 
			
		||||
			next := &node{
 | 
			
		||||
				position:  nb,
 | 
			
		||||
				parent:    current,
 | 
			
		||||
				cost:      cost,
 | 
			
		||||
				potential: potentialFn(nb),
 | 
			
		||||
				closed:    maps.Clone(current.closed),
 | 
			
		||||
			}
 | 
			
		||||
			// check if path is in open list
 | 
			
		||||
			if _, open := current.closed[seen]; !open {
 | 
			
		||||
				next.closed[seen] = false // add to open list
 | 
			
		||||
				pq.Insert(next)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return costs, paths
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,12 @@
 | 
			
		||||
package aoc_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/matryer/is"
 | 
			
		||||
	aoc "go.sour.is/advent-of-code"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestSet(t *testing.T) {
 | 
			
		||||
	is := is.New(t)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user