{-# Language QuasiQuotes, ImportQualifiedPost, NumericUnderscores #-}
module Main where
import Data.List (tails)
import Data.List.NonEmpty (NonEmpty(..), (<|))
import Data.Map qualified as Map
import Data.Tree (Tree(..))
import Data.Tree qualified as Tree
import Advent (format)
type Path = [String]
type Input = [Either String [Either (Int, String) String]]
main :: IO ()
IO ()
main =
do [Either String [Either (Int, String) String]]
input <- [format|2022 7
($ cd %s%n
|$ ls%n
(%u %s%n
|dir %s%n)*)*|]
let totalSizes :: [Int]
totalSizes = [([String], Int)] -> [Int]
lsToTotalSizes ([String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs [] [Either String [Either (Int, String) String]]
input)
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
n | Int
n <- [Int]
totalSizes, Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
100_000])
let minNeeded :: Int
minNeeded = [Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
totalSizes Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
30_000_000 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
70_000_000
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Int
n | Int
n <- [Int]
totalSizes, Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
minNeeded])
lsToTotalSizes :: [(Path, Int)] -> [Int]
lsToTotalSizes :: [([String], Int)] -> [Int]
lsToTotalSizes [([String], Int)]
dirs = Map [String] Int -> [Int]
forall k a. Map k a -> [a]
Map.elems ((Int -> Int -> Int) -> [([String], Int)] -> Map [String] Int
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) [([String]
d',Int
n) | ([String]
d,Int
n) <- [([String], Int)]
dirs, [String]
d' <- [String] -> [[String]]
forall a. [a] -> [[a]]
tails [String]
d])
summarizeLs ::
Path ->
Input ->
[(Path, Int)]
summarizeLs :: [String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs [String]
_ [] = []
summarizeLs [String]
_ (Left String
"/" : [Either String [Either (Int, String) String]]
xs) = [String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs [] [Either String [Either (Int, String) String]]
xs
summarizeLs [String]
cwd (Left String
".." : [Either String [Either (Int, String) String]]
xs) = [String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs (Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 [String]
cwd) [Either String [Either (Int, String) String]]
xs
summarizeLs [String]
cwd (Left String
dir : [Either String [Either (Int, String) String]]
xs) = [String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs (String
dir String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
cwd) [Either String [Either (Int, String) String]]
xs
summarizeLs [String]
cwd (Right [Either (Int, String) String]
ls : [Either String [Either (Int, String) String]]
xs) = ([String]
cwd, [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
n | Left (Int
n,String
_) <- [Either (Int, String) String]
ls]) ([String], Int) -> [([String], Int)] -> [([String], Int)]
forall a. a -> [a] -> [a]
: [String]
-> [Either String [Either (Int, String) String]]
-> [([String], Int)]
summarizeLs [String]
cwd [Either String [Either (Int, String) String]]
xs