Compare commits
No commits in common. "9b26cc5c66f0fdb07802a5f2d0b5d8e2f42b2d8d" and "fdd09b72c7fb3ea655560b2b98921a356b44707e" have entirely different histories.
9b26cc5c66
...
fdd09b72c7
|
|
@ -5,9 +5,8 @@ import Debug.Trace (traceShowId, traceShow, trace)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
import Bfs
|
import Bfs
|
||||||
import Data.List (maximumBy, permutations, delete, singleton)
|
import Data.List (maximumBy, permutations, delete)
|
||||||
import Data.Function (on)
|
import Data.Function (on)
|
||||||
import Control.Monad.Trans.State (State, get, put, evalState)
|
|
||||||
|
|
||||||
data Valve = V { flow' :: Int, neighs' :: [String] } deriving Show
|
data Valve = V { flow' :: Int, neighs' :: [String] } deriving Show
|
||||||
type ZMap = M.Map String Valve
|
type ZMap = M.Map String Valve
|
||||||
|
|
@ -64,7 +63,7 @@ perms limit m = perms' "AA" limit elems where
|
||||||
perms' current remaining as = do
|
perms' current remaining as = do
|
||||||
a <- as
|
a <- as
|
||||||
let distance = dists (m M.! current) M.! a
|
let distance = dists (m M.! current) M.! a
|
||||||
[a] : if distance < remaining then do
|
if distance < remaining then do
|
||||||
let l = delete a as
|
let l = delete a as
|
||||||
ls <- perms' a (remaining-distance) l
|
ls <- perms' a (remaining-distance) l
|
||||||
pure $ a:ls
|
pure $ a:ls
|
||||||
|
|
@ -89,54 +88,14 @@ traceMap cond f (x:y:xs)
|
||||||
| cond x y = let result = f x in traceShow (result, x) (result: traceMap cond f (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)
|
| otherwise = f x : traceMap cond f (y:xs)
|
||||||
|
|
||||||
type EleMemo = M.Map (S.Set String) Int
|
|
||||||
eleLookup :: NzMap -> S.Set String -> State EleMemo Int
|
|
||||||
eleLookup nzmap permutation = do
|
|
||||||
mmap <- get
|
|
||||||
case M.lookup permutation mmap of
|
|
||||||
Just x -> pure x
|
|
||||||
Nothing -> do
|
|
||||||
let valves = M.fromList $ filter (\(name, valve) -> S.notMember name permutation) (M.toList nzmap)
|
|
||||||
let elePerms = traceShow ("elephant", permutation) $ perms 26 valves
|
|
||||||
let exec p = execPerm nzmap p 0 "AA" 26
|
|
||||||
let flow = maximum $ map exec elePerms
|
|
||||||
put $ M.insert permutation flow mmap
|
|
||||||
pure flow
|
|
||||||
|
|
||||||
part2 :: NzMap -> [String] -> State EleMemo Int
|
|
||||||
part2 nzmap permutation = do
|
|
||||||
let me = execPerm nzmap permutation 0 "AA" 26
|
|
||||||
elephant <- eleLookup nzmap (S.fromList permutation)
|
|
||||||
pure $ me + elephant
|
|
||||||
-- case elephant of
|
|
||||||
-- Just ele -> pure $ me + ele
|
|
||||||
-- Nothing -> do
|
|
||||||
-- let valves = M.fromList $ filter (\(name, valve) -> S.notMember name permset) (M.toList nzmap)
|
|
||||||
-- let elePerms = traceShow ("elephant", permutation) $ perms 26 valves
|
|
||||||
-- let exec p = execPerm nzmap p 0 "AA" 26
|
|
||||||
-- let ele = maximum $ map exec elePerms
|
|
||||||
-- put $ M.insert permset ele state
|
|
||||||
-- pure $ me + ele
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
x <- prepass . M.fromList . map parseValve . lines <$> getContents
|
x <- prepass . M.fromList . map parseValve . lines <$> getContents
|
||||||
mapM_ print x
|
mapM_ print x
|
||||||
|
|
||||||
-- let all = perms 30 x
|
let all = perms 30 x
|
||||||
-- let exec p = execPerm x p 0 "AA" 30
|
let exec p = execPerm x p 0 "AA" 30
|
||||||
-- let result = traceMap (\a b -> take 2 a /= take 2 b) exec all
|
let result = traceMap (\a b -> take 2 a /= take 2 b) exec all
|
||||||
-- putStr "part 1: "
|
putStr "part 1: "
|
||||||
-- print $ maximum result
|
|
||||||
-- print $ fst $ search x S.empty "AA" 30 M.empty
|
|
||||||
|
|
||||||
putStr "part 2: "
|
|
||||||
-- let initialEle = maximumBy (compare `on` fst) $ map (\p -> (execPerm x p 0 "AA" 26, [S.fromList p])) (perms 26 x)
|
|
||||||
-- print initialEle
|
|
||||||
|
|
||||||
|
|
||||||
let all = perms 26 x
|
|
||||||
let action = mapM (part2 x) all
|
|
||||||
let result = evalState action M.empty
|
|
||||||
print $ maximum result
|
print $ maximum result
|
||||||
pure ()
|
-- print $ fst $ search x S.empty "AA" 30 M.empty
|
||||||
|
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
import qualified Data.Set as S
|
|
||||||
import Debug.Trace (traceShow)
|
|
||||||
|
|
||||||
type Coord = (Integer, Integer)
|
|
||||||
type Rock = [Coord]
|
|
||||||
|
|
||||||
rockFix :: Rock -> Rock
|
|
||||||
rockFix xs = let maxy = maximum (map snd xs) in map (\(x,y) -> (x+2, y-maxy)) xs
|
|
||||||
|
|
||||||
rocks :: [Rock]
|
|
||||||
rocks = map rockFix
|
|
||||||
[ [(0,0), (1,0), (2,0), (3,0)]
|
|
||||||
, [(1,0), (0,1), (1,1), (2,1), (1,2)]
|
|
||||||
, [(2,0), (2,1), (0,2), (1,2), (2,2)]
|
|
||||||
, [(0,0), (0,1), (0,2), (0,3)]
|
|
||||||
, [(0,0), (0,1), (1,0), (1,1)]
|
|
||||||
]
|
|
||||||
|
|
||||||
simulate :: [Rock] -> Maybe Rock -> String -> S.Set Coord -> Integer -> S.Set Coord
|
|
||||||
simulate [] _ _ _ _ = error "finite stream of rocks"
|
|
||||||
simulate (r:rs) Nothing jets occupied 0 = occupied
|
|
||||||
simulate (r:rs) Nothing jets occupied n = simulate rs (Just next) jets occupied (n-1) where
|
|
||||||
height = minimum (1 : map snd (S.toList occupied)) - 4
|
|
||||||
next = map (\(x,y) -> (x, y+height)) r
|
|
||||||
simulate (r:rs) (Just rock) (j:js) occupied remaining = if valid dropped
|
|
||||||
then simulate (r:rs) (Just dropped) js occupied remaining
|
|
||||||
else simulate (r:rs) Nothing js occupied' remaining
|
|
||||||
where
|
|
||||||
pushF = case j of
|
|
||||||
'>' -> \(x,y) -> (x+1, y)
|
|
||||||
'<' -> \(x,y) -> (x-1, y)
|
|
||||||
_ -> error ("invalid char" ++ show j)
|
|
||||||
dropF (x,y) = (x, y+1)
|
|
||||||
valid = all (\c@(x,y) -> c `S.notMember` occupied
|
|
||||||
&& x >= 0 && x < 7 && y <= 0)
|
|
||||||
pushed = if valid (map pushF rock) then map pushF rock else rock
|
|
||||||
dropped = map dropF pushed
|
|
||||||
occupied' = foldr S.insert occupied pushed
|
|
||||||
|
|
||||||
|
|
||||||
-- simulate2 :: [Rock] -> String -> [Rock] -> Maybe Rock -> String -> S.Set Coord -> Integer -> Integer -> Integer
|
|
||||||
-- simulate2 origR origJ [] _ _ _ _ _ = error "finite stream of rocks"
|
|
||||||
-- simulate2 origR origJ (r:rs) Nothing jets occupied 0 iters = undefined
|
|
||||||
-- simulate2 origR origJ (r:rs) Nothing jets occupied n iters = if iters > 0 && matchesR && matchesJ
|
|
||||||
-- then let h = minimum (map snd (S.toList occupied)) in
|
|
||||||
-- let repetitions = n `div` iters in
|
|
||||||
-- let addedHeight = h * repetitions in addedHeight + simulate2 origR origJ (r:rs) Nothing jets occupied (n `mod` iters) 0
|
|
||||||
-- else simulate2 origR origJ rs (Just next) jets occupied (n-1) (iters+1) where
|
|
||||||
-- height = minimum (1 : map snd (S.toList occupied)) - 4
|
|
||||||
-- next = map (\(x,y) -> (x, y+height)) r
|
|
||||||
-- matchesR = origR == take (length origR) (r:rs)
|
|
||||||
-- matchesJ = origJ == take (length origJ) jets
|
|
||||||
-- simulate2 origR origJ (r:rs) (Just rock) (j:js) occupied remaining iters = if valid dropped
|
|
||||||
-- then simulate2 origR origJ (r:rs) (Just dropped) js occupied remaining iters
|
|
||||||
-- else simulate2 origR origJ (r:rs) Nothing js occupied' remaining iters
|
|
||||||
-- where
|
|
||||||
-- pushF = case j of
|
|
||||||
-- '>' -> \(x,y) -> (x+1, y)
|
|
||||||
-- '<' -> \(x,y) -> (x-1, y)
|
|
||||||
-- _ -> error ("invalid char" ++ show j)
|
|
||||||
-- dropF (x,y) = (x, y+1)
|
|
||||||
-- valid = all (\c@(x,y) -> c `S.notMember` occupied
|
|
||||||
-- && x >= 0 && x < 7 && y <= 0)
|
|
||||||
-- pushed = if valid (map pushF rock) then map pushF rock else rock
|
|
||||||
-- dropped = map dropF pushed
|
|
||||||
-- occupied' = foldr S.insert occupied pushed
|
|
||||||
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main = do
|
|
||||||
jets <- head . lines <$> getContents
|
|
||||||
let height set = -(minimum $ map snd (S.toList set)) + 1
|
|
||||||
|
|
||||||
putStr "part 1: "
|
|
||||||
let tower = simulate (cycle rocks) Nothing (cycle jets) S.empty 2022
|
|
||||||
print (height tower)
|
|
||||||
|
|
||||||
-- part 2
|
|
||||||
let repIters = lcm (fromIntegral $ length jets) (fromIntegral $ length rocks) :: Integer
|
|
||||||
putStr "repeated: " >> print repIters
|
|
||||||
|
|
||||||
let initial = simulate (cycle rocks) Nothing (cycle jets) S.empty repIters
|
|
||||||
let repeated = simulate (cycle rocks) Nothing (cycle jets) S.empty (2*repIters)
|
|
||||||
|
|
||||||
let diff ls = zipWith (-) (tail ls) ls
|
|
||||||
print $ diff $ map (\i -> height $ simulate (cycle rocks) Nothing (cycle jets) S.empty (i*repIters)) [1..20]
|
|
||||||
|
|
||||||
let initHeight = height initial
|
|
||||||
let repHeight = height repeated - initHeight
|
|
||||||
putStr "repeated structure height: " >> print (initHeight, repHeight)
|
|
||||||
let remIters = 1000000000000 `mod` repIters
|
|
||||||
let remaining = simulate (cycle rocks) Nothing (cycle jets) S.empty remIters
|
|
||||||
let remHeight = if remIters > 0 then -(minimum $ map snd (S.toList remaining)) + 1 else 0
|
|
||||||
-- let tower = simulate2 rocks jets (cycle rocks) Nothing (cycle jets) S.empty 2022 0
|
|
||||||
|
|
||||||
putStr "part 2: "
|
|
||||||
let repNum = 1000000000000 `div` repIters
|
|
||||||
print $ (repNum * repHeight) + remHeight
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
||||||
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
|
|
||||||
Loading…
Reference in New Issue