summaryrefslogtreecommitdiff
path: root/9-2.hs
blob: 361b9d1c93c69debce2cf6d9983b0cd2d1ba6128 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import Data.Foldable (toList)
import Data.Sequence hiding (replicate, zip)

type FS = Seq File

data File = File { fid :: Int, size :: Int } | Blank { size :: Int }
  deriving (Eq, Show)

doOne :: FS -> Maybe FS
doOne = go Empty
  where
    go :: FS -> FS -> Maybe FS
    go _ Empty = Nothing
    go _ (_ :|> (Blank _)) = Nothing
    go res (y@(Blank l) :<| ys@(xs :|> x@(File _ k)))
      | k <= l = Just $ res <> (x :<| Blank (l-k) :<| (xs :|> Blank k))
      | otherwise = go (res :|> y) ys
    go res (x :<| xs) = go (res :|> x) xs

rearrange :: FS -> FS
rearrange Empty = Empty
rearrange ys@(xs :|> x) = case doOne ys of
  Nothing -> rearrange xs :|> x
  Just zs -> rearrange zs

parse :: String -> Seq File
parse = go 0 Empty
  where
    go :: Int -> Seq File -> String -> Seq File
    go _ res [] = res
    go n res (x:xs) = go' (n+1) (res :|> File n (f x)) xs

    go' :: Int -> Seq File -> String -> Seq File
    go' _ res [] = res
    go' n res (x:xs) = go n (res :|> Blank (f x)) xs

    f :: Char -> Int
    f = read . pure 

expand :: File -> [Int]
expand (Blank n) = replicate n 0
expand (File i n) = replicate n i

checksum :: FS -> Int
checksum = sum . fmap (uncurry (*)) . zip [0..] . concatMap expand . toList

main :: IO ()
main = getLine >>= print . checksum . rearrange . parse