do
content <- input 7
let run = Aoc.run content
run (pure 1243729) strategy
run (pure 4443914) $ \s -> do
let fstats = filemap s
let smallestDir = used fstats >>= return . calculation >>= return . (\x -> M.filter(>=x) fstats) >>= return . snd . minimumBy (compare `on` snd) . M.toAscList
fromJust smallestDir
where
needed = 30000000
total = 70000000
calculation x = needed - (total - x)
used = M.lookup "/"
strategy = sum . map snd . M.toAscList . M.filter (<= 100000) . filemap
filemap = snd . snd . runIdentity . state
state = flip runStateT ([], M.empty) . commands
commands = sequence_ . concatMap (map fst) . parse
parse = map (readP_to_S mainParse) . lines
data Dir = Dir String [Dir] | File String
data Direction = Root | Parent | Path String
deriving Show
type CurrentPath = [String]
type WorkingDirState a = StateT (CurrentPath, M.Map String Int) Identity a
do
(_, map) <- get
put (["/"], map)
goDir Parent = do
(cwd, map) <- get
put (drop 1 cwd, map)
goDir (Path s) = do
(cwd, map) <- get
put (s:cwd, map)
do
(cwd, map) <- get
let dirs = scanr1 (flip pathJoin) cwd
let new = foldl' (\m k -> M.alter (f a) k m) map dirs
-- let new' = M.alter (f a) (head dirs) new
put (cwd, new)
where
f x Nothing = Just x
f x (Just old) = Just $ x + old
Just a
test a (Just old) = Just $ old + a
do
(cwd, map) <- get
pure . drop 1 . intercalate "/" . reverse $ cwd
-- maximumBy (compare `on` snd) . M.toAscList . M.filter (< 100000) . snd . snd . runIdentity . flip runStateT ([], M.empty) . sequence_ . concatMap (map fst)
xs ++ "/" ++ ys'
-- Parsers
isAlpha x || x == '.'
isAlpha x || x `elem` "./"
do
string "$ cd "
dir <- munch1 dirName
case dir of
"/" -> pure $ goDir Root
".." -> pure $ goDir Parent
s -> pure $ goDir (Path s)
do
size <- read <$> munch1 isDigit
skipSpaces
name <- munch1 fileName
pure $ fStat size name
parseCd <|> parseEntry