diff --git a/2022/day16.hs b/2022/day16.hs new file mode 100644 index 0000000..fea99aa --- /dev/null +++ b/2022/day16.hs @@ -0,0 +1,101 @@ +import qualified Data.Map as M +import qualified Data.Set as S +import Data.List.Split (splitOn) +import Debug.Trace (traceShowId, traceShow, trace) +import Data.Maybe (fromMaybe) + +import Bfs +import Data.List (maximumBy, permutations, delete) +import Data.Function (on) + +data Valve = V { flow' :: Int, neighs' :: [String] } deriving Show +type ZMap = M.Map String Valve + +data NzValve = NV { flow :: Int, dists :: M.Map String Int} deriving Show +type NzMap = M.Map String NzValve + +parseValve :: String -> (String, Valve) +parseValve xs = (name, V flow tunnels) where + name = words xs !! 1 + flow = read $ last $ splitOn "=" (head $ splitOn ";" xs) + valves = splitOn ", " $ last (splitOn "tunnels lead to valves " xs) + singleValve = splitOn "tunnel leads to valve " xs + tunnels = if length singleValve == 1 then valves else [last singleValve] + +search' :: ZMap -> String -> String -> Int +search' scan from to = dists M.! to where + dists = bfs f [(from,0)] M.empty + f x = neighs' (scan M.! x) + + +prepass :: ZMap -> NzMap +prepass xs = M.fromList $ concatMap f $ M.toList xs where + f (name, v@(V flow _)) = [(name, NV flow (M.fromList $ dists name)) | name == "AA" || flow > 0] + dists name = map (\target -> (target, search' xs name target)) (filter (/= name) allValves) + allValves = map fst . filter (\(name, V flow _) -> name == "AA" || flow > 0) $ M.toList xs + + + + +type Memo = M.Map (S.Set String, String, Int) Int +-- search :: Map -> S.Set String -> String -> Int -> Memo -> (Int, Memo) +-- search scan active location n memo +-- | n <= 0 = (0, M.empty) +-- | otherwise = (releasedPressure + fst best, snd best) where +-- valve = scan M.! location +-- openValve = [(S.insert location active, location, n-1) | S.notMember location active && flow valve > 0] +-- releasedPressure = sum $ map (flow . (scan M.!)) (S.toList active) +-- nop = [(active, location, n-1) | S.size active == M.size scan] +-- move = map (\(name, dist) -> (active, name, n-dist)) (dists $ scan M.! location) +-- actions = openValve ++ move ++ nop +-- trace x = if n>=15 then traceShow (fst x) x else x +-- best = trace $ maximumBy (compare `on` fst) $ map (\(a,l,n) -> search scan a l n memo) actions +-- -- best = maybe best' (\b -> (b,memo)) (M.lookup (active, location, n) memo) +-- -- best' = foldr f (0, memo) actions where +-- -- f (a,l, newN) (i,m) = let (result, memo') = search scan a l newN m; b = max i result in +-- -- trace (b, M.insertWith max (a,l, newN) b $ M.unionWith max m memo') + +perms :: Int -> NzMap -> [[String]] +perms limit m = perms' "AA" limit elems where + elems = filter (/= "AA") $ M.keys m + perms' :: String -> Int -> [String] -> [[String]] + perms' current remaining [] = [[]] + perms' current remaining as = do + a <- as + let distance = dists (m M.! current) M.! a + if distance < remaining then do + let l = delete a as + ls <- perms' a (remaining-distance) l + pure $ a:ls + else pure [a] + +execPerm :: NzMap -> [String] -> Int -> String -> Int -> Int +execPerm nzmap [] flowrate location remaining = remaining * flowrate +execPerm nzmap (target:qs) flowrate location remaining + | remaining < 0 = 0 + | distance >= remaining = remaining * flowrate + | otherwise = (distance * flowrate) + execPerm nzmap qs flowrate' target (remaining - distance) + where + valve = nzmap M.! location + distance = 1 + dists valve M.! target + flowrate' = flowrate + flow (nzmap M.! target) + + +traceMap :: (Show a, Show b) => (a -> a -> Bool) -> (a -> b) -> [a] -> [b] +traceMap cond f [] = [] +traceMap cond f [x] = [f x] +traceMap cond f (x:y:xs) + | cond x y = let result = f x in traceShow (result, x) (result: traceMap cond f (y:xs)) + | otherwise = f x : traceMap cond f (y:xs) + +main :: IO () +main = do + x <- prepass . M.fromList . map parseValve . lines <$> getContents + mapM_ print x + + let all = perms 30 x + let exec p = execPerm x p 0 "AA" 30 + let result = traceMap (\a b -> take 2 a /= take 2 b) exec all + putStr "part 1: " + print $ maximum result + -- print $ fst $ search x S.empty "AA" 30 M.empty diff --git a/2022/inputs/day16 b/2022/inputs/day16 new file mode 100644 index 0000000..949deb7 --- /dev/null +++ b/2022/inputs/day16 @@ -0,0 +1,56 @@ +Valve JI has flow rate=21; tunnels lead to valves WI, XG +Valve DM has flow rate=3; tunnels lead to valves JX, NG, AW, BY, PF +Valve AZ has flow rate=0; tunnels lead to valves FJ, VC +Valve YQ has flow rate=0; tunnels lead to valves TE, OP +Valve WI has flow rate=0; tunnels lead to valves JI, VC +Valve NE has flow rate=0; tunnels lead to valves ZK, AA +Valve FM has flow rate=0; tunnels lead to valves LC, DU +Valve QI has flow rate=0; tunnels lead to valves TE, JW +Valve OY has flow rate=0; tunnels lead to valves XS, VF +Valve XS has flow rate=18; tunnels lead to valves RR, OY, SV, NQ +Valve NU has flow rate=0; tunnels lead to valves IZ, BD +Valve JX has flow rate=0; tunnels lead to valves DM, ZK +Valve WT has flow rate=23; tunnels lead to valves OV, QJ +Valve KM has flow rate=0; tunnels lead to valves TE, OL +Valve NG has flow rate=0; tunnels lead to valves II, DM +Valve FJ has flow rate=0; tunnels lead to valves AZ, II +Valve QR has flow rate=0; tunnels lead to valves ZK, KI +Valve KI has flow rate=9; tunnels lead to valves ZZ, DI, TL, AJ, QR +Valve ON has flow rate=0; tunnels lead to valves LC, QT +Valve AW has flow rate=0; tunnels lead to valves DM, AA +Valve HI has flow rate=0; tunnels lead to valves TE, VC +Valve XG has flow rate=0; tunnels lead to valves II, JI +Valve II has flow rate=19; tunnels lead to valves LF, NG, OL, FJ, XG +Valve VC has flow rate=24; tunnels lead to valves WI, HI, AZ +Valve VJ has flow rate=0; tunnels lead to valves UG, AA +Valve IZ has flow rate=0; tunnels lead to valves VF, NU +Valve EJ has flow rate=0; tunnels lead to valves ZK, LC +Valve DU has flow rate=12; tunnels lead to valves TC, UG, FM +Valve ZK has flow rate=10; tunnels lead to valves JX, EJ, JW, QR, NE +Valve XF has flow rate=25; tunnels lead to valves OP, VT +Valve LC has flow rate=4; tunnels lead to valves FM, EJ, ON, AJ, PF +Valve SV has flow rate=0; tunnels lead to valves XS, IY +Valve LF has flow rate=0; tunnels lead to valves II, OV +Valve DI has flow rate=0; tunnels lead to valves KI, BY +Valve OP has flow rate=0; tunnels lead to valves YQ, XF +Valve NQ has flow rate=0; tunnels lead to valves TC, XS +Valve QJ has flow rate=0; tunnels lead to valves VT, WT +Valve IY has flow rate=22; tunnel leads to valve SV +Valve AJ has flow rate=0; tunnels lead to valves LC, KI +Valve TE has flow rate=11; tunnels lead to valves QI, HI, KM, YQ +Valve ZZ has flow rate=0; tunnels lead to valves KI, AA +Valve VT has flow rate=0; tunnels lead to valves XF, QJ +Valve OL has flow rate=0; tunnels lead to valves KM, II +Valve TC has flow rate=0; tunnels lead to valves NQ, DU +Valve TL has flow rate=0; tunnels lead to valves VF, KI +Valve QT has flow rate=0; tunnels lead to valves AA, ON +Valve BY has flow rate=0; tunnels lead to valves DM, DI +Valve OV has flow rate=0; tunnels lead to valves LF, WT +Valve VN has flow rate=0; tunnels lead to valves RR, BD +Valve VF has flow rate=13; tunnels lead to valves OY, IZ, TL +Valve BD has flow rate=17; tunnels lead to valves NU, VN +Valve UG has flow rate=0; tunnels lead to valves VJ, DU +Valve PF has flow rate=0; tunnels lead to valves LC, DM +Valve RR has flow rate=0; tunnels lead to valves XS, VN +Valve AA has flow rate=0; tunnels lead to valves QT, ZZ, AW, VJ, NE +Valve JW has flow rate=0; tunnels lead to valves ZK, QI diff --git a/2022/inputs/day16.test b/2022/inputs/day16.test new file mode 100644 index 0000000..9f30acc --- /dev/null +++ b/2022/inputs/day16.test @@ -0,0 +1,10 @@ +Valve AA has flow rate=0; tunnels lead to valves DD, II, BB +Valve BB has flow rate=13; tunnels lead to valves CC, AA +Valve CC has flow rate=2; tunnels lead to valves DD, BB +Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE +Valve EE has flow rate=3; tunnels lead to valves FF, DD +Valve FF has flow rate=0; tunnels lead to valves EE, GG +Valve GG has flow rate=0; tunnels lead to valves FF, HH +Valve HH has flow rate=22; tunnel leads to valve GG +Valve II has flow rate=0; tunnels lead to valves AA, JJ +Valve JJ has flow rate=21; tunnel leads to valve II