day 21: this is so ugly
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		@@ -158,3 +158,9 @@ executable day20
 | 
				
			|||||||
  hs-source-dirs: src
 | 
					  hs-source-dirs: src
 | 
				
			||||||
  main-is:        Day20.hs
 | 
					  main-is:        Day20.hs
 | 
				
			||||||
  build-depends:  containers
 | 
					  build-depends:  containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					executable day21
 | 
				
			||||||
 | 
					  import:         common
 | 
				
			||||||
 | 
					  hs-source-dirs: src
 | 
				
			||||||
 | 
					  main-is:        Day21.hs
 | 
				
			||||||
 | 
					  build-depends:  containers
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,15 @@
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        packages.default = self'.packages.aoc2024;
 | 
					        packages.default = self'.packages.aoc2024;
 | 
				
			||||||
 | 
					        apps =
 | 
				
			||||||
 | 
					          let
 | 
				
			||||||
 | 
					            name = n: "day${(if n < 10 then "0" else "" ) + toString n}";
 | 
				
			||||||
 | 
					          in
 | 
				
			||||||
 | 
					          with pkgs.lib; genAttrs (map name (range 1 21))
 | 
				
			||||||
 | 
					            (n: {
 | 
				
			||||||
 | 
					              type = "app";
 | 
				
			||||||
 | 
					              program = "${self'.packages.aoc2024}/bin/${n}";
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										79
									
								
								src/Day21.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/Day21.hs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					module Main where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Data.List (foldl', minimumBy, nub)
 | 
				
			||||||
 | 
					import qualified Data.Map as M
 | 
				
			||||||
 | 
					import Data.Ord (comparing)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- TODO: ugloid and slow solution, please clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Vec = (Int, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Table = M.Map (Char, Char) [String]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Memo = M.Map (Char, Char, Int) Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					coord :: Char -> Vec
 | 
				
			||||||
 | 
					-- keypad
 | 
				
			||||||
 | 
					coord '0' = (1, 3)
 | 
				
			||||||
 | 
					coord 'A' = (2, 3)
 | 
				
			||||||
 | 
					coord '1' = (0, 2)
 | 
				
			||||||
 | 
					coord '2' = (1, 2)
 | 
				
			||||||
 | 
					coord '3' = (2, 2)
 | 
				
			||||||
 | 
					coord '4' = (0, 1)
 | 
				
			||||||
 | 
					coord '5' = (1, 1)
 | 
				
			||||||
 | 
					coord '6' = (2, 1)
 | 
				
			||||||
 | 
					coord '7' = (0, 0)
 | 
				
			||||||
 | 
					coord '8' = (1, 0)
 | 
				
			||||||
 | 
					coord '9' = (2, 0)
 | 
				
			||||||
 | 
					-- direction
 | 
				
			||||||
 | 
					coord 'a' = (2, 0)
 | 
				
			||||||
 | 
					coord '^' = (1, 0)
 | 
				
			||||||
 | 
					coord '<' = (0, 1)
 | 
				
			||||||
 | 
					coord 'v' = (1, 1)
 | 
				
			||||||
 | 
					coord '>' = (2, 1)
 | 
				
			||||||
 | 
					coord _ = error "what?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					path :: Char -> Char -> [String]
 | 
				
			||||||
 | 
					path a b =
 | 
				
			||||||
 | 
					  let ((x1, y1), (x2, y2)) = (coord a, coord b)
 | 
				
			||||||
 | 
					      moves =
 | 
				
			||||||
 | 
					        replicate (abs (y2 - y1)) (if y2 > y1 then 'v' else '^')
 | 
				
			||||||
 | 
					          ++ replicate (abs (x2 - x1)) (if x2 > x1 then '>' else '<')
 | 
				
			||||||
 | 
					   in if
 | 
				
			||||||
 | 
					        | a == '<' || x1 == 0 && y2 == 3 -> [reverse moves ++ "a"]
 | 
				
			||||||
 | 
					        | b == '<' || y1 == 3 && x2 == 0 -> [moves ++ "a"]
 | 
				
			||||||
 | 
					        | otherwise -> nub [reverse moves ++ "a", moves ++ "a"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					seqc :: Table -> Int -> String -> Int
 | 
				
			||||||
 | 
					seqc table n = fst . seqc' M.empty (n + 1) 'A'
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    seqc' :: Memo -> Int -> Char -> String -> (Int, Memo)
 | 
				
			||||||
 | 
					    seqc' memo 0 _ s = (length s, memo)
 | 
				
			||||||
 | 
					    seqc' memo n start s = foldl' loop (0, memo) $ zip (start : s) s
 | 
				
			||||||
 | 
					      where
 | 
				
			||||||
 | 
					        loop :: (Int, Memo) -> (Char, Char) -> (Int, Memo)
 | 
				
			||||||
 | 
					        loop (total, memo) (a, b) = case (a, b, n) `M.lookup` memo of
 | 
				
			||||||
 | 
					          Just x -> (total + x, memo)
 | 
				
			||||||
 | 
					          Nothing ->
 | 
				
			||||||
 | 
					            let paths = table M.! (a, b)
 | 
				
			||||||
 | 
					                (x, memo') =
 | 
				
			||||||
 | 
					                  minimumBy
 | 
				
			||||||
 | 
					                    (comparing fst)
 | 
				
			||||||
 | 
					                    (map (seqc' memo (n - 1) 'a') paths)
 | 
				
			||||||
 | 
					             in (total + x, M.insert (a, b, n) x memo')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					complexity :: Table -> Int -> String -> Int
 | 
				
			||||||
 | 
					complexity table n s = a * b
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    a = read $ init s
 | 
				
			||||||
 | 
					    b = seqc table n s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main :: IO ()
 | 
				
			||||||
 | 
					main =
 | 
				
			||||||
 | 
					  do
 | 
				
			||||||
 | 
					    input <- words <$> readFile "./inputs/day21.in"
 | 
				
			||||||
 | 
					    let keys = "A0123456789a<v>^"
 | 
				
			||||||
 | 
					        table = M.fromList [((a, b), path a b) | a <- keys, b <- keys]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    putStr "Part 1: " >> print (sum $ map (complexity table 2) input)
 | 
				
			||||||
 | 
					    putStr "Part 2: " >> print (sum $ map (complexity table 25) input)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user