chore(day23): solution for day23 pt1/pt2
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Go Test / build (pull_request) Successful in 36s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Go Test / build (pull_request) Successful in 36s
				
			This commit is contained in:
		
							parent
							
								
									951c2c298a
								
							
						
					
					
						commit
						0dc039f032
					
				
							
								
								
									
										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 (
 | 
					import (
 | 
				
			||||||
	"cmp"
 | 
						"cmp"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/exp/maps"
 | 
						"golang.org/x/exp/maps"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -110,7 +112,7 @@ func (m *cmap[C, N]) String() string {
 | 
				
			|||||||
	for k, nbs := range m.neighbors {
 | 
						for k, nbs := range m.neighbors {
 | 
				
			||||||
		fmt.Fprintln(b, k)
 | 
							fmt.Fprintln(b, k)
 | 
				
			||||||
		for to, v := range nbs {
 | 
							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)
 | 
									to[b] = to[n] + p.Cost(n, b)
 | 
				
			||||||
				delete(to, n)
 | 
									delete(to, n)
 | 
				
			||||||
				visited[a] = to
 | 
									visited[a] = to
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
			} else if to, ok := visited[b]; ok {
 | 
								} else if to, ok := visited[b]; ok {
 | 
				
			||||||
				to[a] = to[n] + p.Cost(n, a)
 | 
									to[a] = to[n] + p.Cost(n, a)
 | 
				
			||||||
				delete(to, n)
 | 
									delete(to, n)
 | 
				
			||||||
				visited[b] = to
 | 
									visited[b] = to
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		visited[n] = make(map[N]C)
 | 
							visited[n] = make(map[N]C)
 | 
				
			||||||
		next = append(next, nbs...)
 | 
							next = append(next, nbs...)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,6 @@
 | 
				
			|||||||
package aoc_test
 | 
					package aoc_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/matryer/is"
 | 
						"github.com/matryer/is"
 | 
				
			||||||
@ -27,7 +25,6 @@ func TestRepeat(t *testing.T) {
 | 
				
			|||||||
	is.Equal(aoc.Repeat(5, 3), []int{5, 5, 5})
 | 
						is.Equal(aoc.Repeat(5, 3), []int{5, 5, 5})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestTranspose(t *testing.T) {
 | 
					func TestTranspose(t *testing.T) {
 | 
				
			||||||
	is := is.New(t)
 | 
						is := is.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,11 @@
 | 
				
			|||||||
package aoc_test
 | 
					package aoc_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/matryer/is"
 | 
				
			||||||
 | 
						aoc "go.sour.is/advent-of-code"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestLCM(t *testing.T) {
 | 
					func TestLCM(t *testing.T) {
 | 
				
			||||||
	is := is.New(t)
 | 
						is := is.New(t)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										103
									
								
								search.go
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								search.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
package aoc
 | 
					package aoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"maps"
 | 
				
			||||||
	"math/bits"
 | 
						"math/bits"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -322,3 +323,105 @@ func (h *fibHeap[T]) cascadingCut(y *fibTree[T]) {
 | 
				
			|||||||
		h.cascadingCut(y.parent)
 | 
							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
 | 
					package aoc_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/matryer/is"
 | 
				
			||||||
 | 
						aoc "go.sour.is/advent-of-code"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSet(t *testing.T) {
 | 
					func TestSet(t *testing.T) {
 | 
				
			||||||
	is := is.New(t)
 | 
						is := is.New(t)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user