diff --git a/aoc2022.cabal b/aoc2022.cabal index 59ef8cc..fb16dc9 100644 --- a/aoc2022.cabal +++ b/aoc2022.cabal @@ -44,6 +44,8 @@ library Day5.Part2 Day5.Shared Day6 + Day7 + Day7.Parser Lib other-modules: Paths_aoc2022 @@ -57,6 +59,7 @@ library , heredoc , hspec , lens + , parsec , split , text default-language: Haskell2010 @@ -76,6 +79,7 @@ executable aoc2022-exe , heredoc , hspec , lens + , parsec , split , text default-language: Haskell2010 @@ -90,6 +94,7 @@ test-suite aoc2022-test Day4Spec Day5Spec Day6Spec + Day7Spec Paths_aoc2022 hs-source-dirs: test @@ -102,6 +107,7 @@ test-suite aoc2022-test , heredoc , hspec , lens + , parsec , split , text default-language: Haskell2010 diff --git a/package.yaml b/package.yaml index bcfe013..f0f8845 100644 --- a/package.yaml +++ b/package.yaml @@ -29,6 +29,7 @@ dependencies: - split - lens - Ranged-sets +- parsec ghc-options: - -Wall diff --git a/ressources/day07-input b/ressources/day07-input new file mode 100644 index 0000000..659f8b0 --- /dev/null +++ b/ressources/day07-input @@ -0,0 +1,986 @@ +$ cd / +$ ls +dir bnl +dir dmpsnhdh +272080 dncdssn.hdr +dir fcnqg +6067 hjpmqrq +dir jvwtm +dir ldztz +dir lmmw +dir wthvqw +dir zpdnprb +$ cd bnl +$ ls +dir dhw +dir dmpsnhdh +dir lmw +dir vgbqbrst +$ cd dhw +$ ls +237421 vccwmhl +$ cd .. +$ cd dmpsnhdh +$ ls +dir chf +dir mjpbhjm +dir zwhpwp +$ cd chf +$ ls +4679 lmw.wmp +217367 wwnfv.qqr +dir zfgznbz +$ cd zfgznbz +$ ls +179409 cnj.gdn +171574 vglqg +$ cd .. +$ cd .. +$ cd mjpbhjm +$ ls +dir crf +dir hqnj +dir lmw +18783 lmw.rwr +302608 twpq +166891 vqczlg +$ cd crf +$ ls +32183 dltmqht +240428 frqqdsr.hbf +224910 sgtnrvrt +$ cd .. +$ cd hqnj +$ ls +261723 cgstb +77979 dmpsnhdh.cmd +$ cd .. +$ cd lmw +$ ls +50307 fcqrwd +$ cd .. +$ cd .. +$ cd zwhpwp +$ ls +141133 gdngm.mps +$ cd .. +$ cd .. +$ cd lmw +$ ls +dir dvv +267473 jmqgrh.dlz +295139 rrqjwpm +$ cd dvv +$ ls +114536 gmlmbrrw.wdm +102061 lmw +$ cd .. +$ cd .. +$ cd vgbqbrst +$ ls +105102 dmpsnhdh.bgl +269054 gmwgjf.fzz +dir jbdtpnw +245266 jzsjvgl +216220 lmw.gtb +dir rflp +dir twpq +$ cd jbdtpnw +$ ls +27543 cjvvmzp +$ cd .. +$ cd rflp +$ ls +137601 frqqdsr.hbf +83444 rrqjwpm +$ cd .. +$ cd twpq +$ ls +dir rlbsdj +36846 tnrqzjdd +$ cd rlbsdj +$ ls +56078 bvndq +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd dmpsnhdh +$ ls +dir fnpwwhtj +dir lmw +9090 mgjpsvl.jlh +186374 pbb.zln +$ cd fnpwwhtj +$ ls +dir cgp +$ cd cgp +$ ls +81938 hjpmqrq +281971 jvszf +151057 wmr.bnf +$ cd .. +$ cd .. +$ cd lmw +$ ls +dir bfbv +56929 pbb.zln +dir rrqjwpm +dir sngm +$ cd bfbv +$ ls +92667 qrrttb.jgp +$ cd .. +$ cd rrqjwpm +$ ls +25739 cqljn.zqw +91325 dncdssn.hdr +$ cd .. +$ cd sngm +$ ls +282163 jgrj +dir lmw +237524 lmw.dff +153497 lmw.ntg +dir lqd +dir szn +143535 tvpvc.qpr +98326 vbfgh +$ cd lmw +$ ls +32484 dncdssn.hdr +dir glwr +$ cd glwr +$ ls +144719 frqqdsr.hbf +$ cd .. +$ cd .. +$ cd lqd +$ ls +231401 dncdssn.hdr +dir jnjqmvg +dir lmw +199704 rrqjwpm +$ cd jnjqmvg +$ ls +104947 trpsrfjz.brg +$ cd .. +$ cd lmw +$ ls +230298 rrqjwpm.nnv +158947 wfv.qrb +$ cd .. +$ cd .. +$ cd szn +$ ls +197974 frqqdsr.hbf +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd fcnqg +$ ls +251609 dncdssn.hdr +289497 jdjmftqs +228459 qbmthcq +$ cd .. +$ cd jvwtm +$ ls +dir dmpsnhdh +47959 pbb.zln +dir tlr +dir twpq +dir wbgcsw +dir zjmldjdh +$ cd dmpsnhdh +$ ls +247567 bnl +102471 bnl.wdm +80054 fhqvp.hfm +dir llhp +dir mnsbh +dir mpplsfjp +20844 mtvl.lmp +$ cd llhp +$ ls +180255 dmpsnhdh +$ cd .. +$ cd mnsbh +$ ls +267627 dmpsnhdh +$ cd .. +$ cd mpplsfjp +$ ls +dir bnl +233742 tcnpvqc.tdr +$ cd bnl +$ ls +243223 fcqrwd +$ cd .. +$ cd .. +$ cd .. +$ cd tlr +$ ls +dir vcsngm +dir wndmt +$ cd vcsngm +$ ls +36434 czs.dnv +$ cd .. +$ cd wndmt +$ ls +dir fvmtfcqd +dir nvdb +dir nwqqgl +dir sbspgnpm +$ cd fvmtfcqd +$ ls +237025 nzttjt.rzh +$ cd .. +$ cd nvdb +$ ls +235328 dnrqwqtp.vfc +51984 rhblt.mfz +51332 rjhvhw +$ cd .. +$ cd nwqqgl +$ ls +203534 cjghw +dir cljbrh +$ cd cljbrh +$ ls +133820 lmw.dnd +$ cd .. +$ cd .. +$ cd sbspgnpm +$ ls +270010 hjpmqrq +$ cd .. +$ cd .. +$ cd .. +$ cd twpq +$ ls +dir dmpsnhdh +dir hbchdjjp +247649 hjpmqrq +29891 rrqjwpm +72407 twpq.crb +$ cd dmpsnhdh +$ ls +251490 dncdssn.hdr +222231 hjpmqrq +102058 pbb.zln +$ cd .. +$ cd hbchdjjp +$ ls +70058 dprrmd.qcd +230958 tsdbl.bnq +$ cd .. +$ cd .. +$ cd wbgcsw +$ ls +292028 bhtfcf +dir bnl +dir bqq +dir ctnlpgt +247888 hblhfvwj +dir hbqm +277949 pbb.zln +106225 rrqjwpm +125927 ssqpmlfb.gwm +dir zqmjwsgz +dir zwwphs +$ cd bnl +$ ls +dir fbbr +240500 frqqdsr.hbf +dir mzfrdl +25137 srqlww.mcj +dir tqgrdz +dir ztrnq +$ cd fbbr +$ ls +84414 mjbw.dhs +$ cd .. +$ cd mzfrdl +$ ls +135647 bccwgn +dir cjdptqgh +dir hwdnrqns +dir prq +$ cd cjdptqgh +$ ls +147946 mdgl.drz +11972 pbb.zln +$ cd .. +$ cd hwdnrqns +$ ls +dir dmpsnhdh +$ cd dmpsnhdh +$ ls +254432 phthmn +$ cd .. +$ cd .. +$ cd prq +$ ls +75827 dmpsnhdh.rtl +$ cd .. +$ cd .. +$ cd tqgrdz +$ ls +251475 bjwnll.rlw +$ cd .. +$ cd ztrnq +$ ls +208497 bnl.dtr +179376 gqnbswcj.hht +$ cd .. +$ cd .. +$ cd bqq +$ ls +202201 bnl.lbm +$ cd .. +$ cd ctnlpgt +$ ls +269484 vsfvzrpr +$ cd .. +$ cd hbqm +$ ls +74455 bvnfz +42748 pbb.zln +$ cd .. +$ cd zqmjwsgz +$ ls +146194 pbb.zln +$ cd .. +$ cd zwwphs +$ ls +209587 mtbzd.nwb +$ cd .. +$ cd .. +$ cd zjmldjdh +$ ls +dir cdq +dir mdclfbs +dir tfc +132043 wrm +$ cd cdq +$ ls +289173 twpq.mrn +$ cd .. +$ cd mdclfbs +$ ls +64639 bnl.jwf +dir hpdgt +72868 hznfj.nmj +159467 lmw.bfz +$ cd hpdgt +$ ls +52760 fcqrwd +54661 tzgt.hvh +$ cd .. +$ cd .. +$ cd tfc +$ ls +185481 bwntlh +18925 fcqrwd +$ cd .. +$ cd .. +$ cd .. +$ cd ldztz +$ ls +128430 bwz.fcz +dir dmpsnhdh +dir lbqgz +dir znrnj +$ cd dmpsnhdh +$ ls +238193 dncdssn.hdr +285939 hwfngq.dpw +$ cd .. +$ cd lbqgz +$ ls +171931 vgrp +$ cd .. +$ cd znrnj +$ ls +153738 vmwwbjqd +$ cd .. +$ cd .. +$ cd lmmw +$ ls +dir bqqnsfdj +163303 fcqrwd +43453 frqqdsr.hbf +33319 hjpmqrq +dir rlpcqtzg +$ cd bqqnsfdj +$ ls +dir bnl +2251 hjpmqrq +14707 rrqjwpm +dir tlnbvhdl +$ cd bnl +$ ls +33357 bnl.fqp +151237 bnl.vbs +40294 dmpsnhdh.hwz +76455 dncdssn.hdr +290341 hjpmqrq +dir lmw +dir nqw +$ cd lmw +$ ls +dir sfj +$ cd sfj +$ ls +156532 fcqrwd +$ cd .. +$ cd .. +$ cd nqw +$ ls +59928 dncdssn.hdr +$ cd .. +$ cd .. +$ cd tlnbvhdl +$ ls +183301 hjpmqrq +$ cd .. +$ cd .. +$ cd rlpcqtzg +$ ls +258638 dqt.mlc +$ cd .. +$ cd .. +$ cd wthvqw +$ ls +224501 pbb.zln +$ cd .. +$ cd zpdnprb +$ ls +dir bnl +dir ffg +dir jljlwpsv +212081 lrzc.lhj +dir rrqjwpm +dir twpq +dir vlgsrtm +$ cd bnl +$ ls +124009 hjgjf +74860 hjpmqrq +84996 lrdl.swf +dir pnzmp +$ cd pnzmp +$ ls +dir btbtlrs +128636 nfzf +$ cd btbtlrs +$ ls +107651 hhzbwd.wzj +$ cd .. +$ cd .. +$ cd .. +$ cd ffg +$ ls +57918 jwzbs.tnt +$ cd .. +$ cd jljlwpsv +$ ls +188175 dmpsnhdh.nnb +46693 fcqrwd +111557 pbb.zln +$ cd .. +$ cd rrqjwpm +$ ls +dir bftw +dir ccsfws +87225 mccw +290654 pbb.zln +147394 twzqc.pbz +52983 wsvgf +dir wwfgbzqh +$ cd bftw +$ ls +dir brl +167154 crs +dir lmw +dir rrqjwpm +dir twpq +174963 twpq.wjl +dir vnfhb +dir wcldzp +$ cd brl +$ ls +297937 wspcnp +$ cd .. +$ cd lmw +$ ls +166695 mcjql.jrv +$ cd .. +$ cd rrqjwpm +$ ls +198762 mwn +$ cd .. +$ cd twpq +$ ls +141835 jlwf.hcd +$ cd .. +$ cd vnfhb +$ ls +128626 tvmwhq.wfn +$ cd .. +$ cd wcldzp +$ ls +dir ncq +dir twpq +$ cd ncq +$ ls +dir wrtw +$ cd wrtw +$ ls +133331 fcqrwd +$ cd .. +$ cd .. +$ cd twpq +$ ls +151811 fcqrwd +$ cd .. +$ cd .. +$ cd .. +$ cd ccsfws +$ ls +100548 twpq.ppm +$ cd .. +$ cd wwfgbzqh +$ ls +dir lmw +dir mfms +dir pjbjgbcl +204154 qtflzwm +226500 vdmjj.htj +dir wzqbwr +$ cd lmw +$ ls +dir bgl +95150 dncdssn.hdr +119653 frqqdsr.hbf +97941 hjpmqrq +dir jqthwzj +$ cd bgl +$ ls +dir lmw +dir rrqjwpm +$ cd lmw +$ ls +233655 wmdldvbz +$ cd .. +$ cd rrqjwpm +$ ls +242918 frqqdsr.hbf +227581 hjpmqrq +dir hsvnmlp +dir nsch +25524 pbb.zln +dir qlgg +dir twpq +67453 twpq.fms +$ cd hsvnmlp +$ ls +264517 pbb.zln +$ cd .. +$ cd nsch +$ ls +7898 cmsdzh +233270 dmpsnhdh.bsq +101256 frl +133902 jzvh.vdv +dir lmw +dir sgjsg +130245 wcftvft +$ cd lmw +$ ls +69572 bnjnc.csp +$ cd .. +$ cd sgjsg +$ ls +38856 tnzpz.tbq +$ cd .. +$ cd .. +$ cd qlgg +$ ls +276013 frbstg.pzb +$ cd .. +$ cd twpq +$ ls +136454 fhwz.bqb +94099 rglp +114026 tsrt.cbd +26252 zhclpzm.rqf +$ cd .. +$ cd .. +$ cd .. +$ cd jqthwzj +$ ls +128200 lmw.btl +$ cd .. +$ cd .. +$ cd mfms +$ ls +274935 dmpsnhdh +76547 lchwq.dsd +215701 pbb.zln +dir rmwtvjt +$ cd rmwtvjt +$ ls +74490 hjpmqrq +$ cd .. +$ cd .. +$ cd pjbjgbcl +$ ls +231757 cjcpwwc.wbf +dir cswvftzs +dir jtvtg +dir lmw +dir tnctbjr +dir tqsrfhdr +$ cd cswvftzs +$ ls +dir dchqnbns +dir smf +$ cd dchqnbns +$ ls +94111 szl.hqs +$ cd .. +$ cd smf +$ ls +dir dlnsgvl +dir zglt +$ cd dlnsgvl +$ ls +dir dsz +$ cd dsz +$ ls +156473 hjpmqrq +$ cd .. +$ cd .. +$ cd zglt +$ ls +295383 frgg.sdp +$ cd .. +$ cd .. +$ cd .. +$ cd jtvtg +$ ls +202254 bftv.rqb +58419 lmw +$ cd .. +$ cd lmw +$ ls +8097 fcqrwd +$ cd .. +$ cd tnctbjr +$ ls +250830 frqqdsr.hbf +dir gzrcqr +$ cd gzrcqr +$ ls +dir fnzgsnv +$ cd fnzgsnv +$ ls +117215 hjpmqrq +$ cd .. +$ cd .. +$ cd .. +$ cd tqsrfhdr +$ ls +96381 lmw +$ cd .. +$ cd .. +$ cd wzqbwr +$ ls +149066 dmpsnhdh.vnd +dir dpbcgfdr +dir swp +14495 twpq.gsb +dir zhj +$ cd dpbcgfdr +$ ls +12909 dmpsnhdh +dir jvn +173491 mnhpr.lpr +222018 rfqfjmd.jqq +205077 wbbdrpr.hzj +dir wzpbbbhm +$ cd jvn +$ ls +117656 vqddrqlq.nfd +233109 vqqvh.swz +$ cd .. +$ cd wzpbbbhm +$ ls +143534 pbb.zln +$ cd .. +$ cd .. +$ cd swp +$ ls +131295 pbb.zln +$ cd .. +$ cd zhj +$ ls +166268 pbb.zln +33734 rrqjwpm.blg +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd twpq +$ ls +dir bppvlwqs +dir bvh +dir rmcdr +dir tdn +2230 whb.lfb +dir wwtwnvh +$ cd bppvlwqs +$ ls +195026 hvlhgsw +279259 rrqjwpm +$ cd .. +$ cd bvh +$ ls +dir lmw +$ cd lmw +$ ls +66958 pdqnd +$ cd .. +$ cd .. +$ cd rmcdr +$ ls +dir dmpsnhdh +182930 grj +dir pmrdhrth +119725 qpcqclqh +77890 sjgfjz +142855 twpq +dir zbmcrvbh +$ cd dmpsnhdh +$ ls +dir rrqjwpm +188474 zgjzpbl.vgv +$ cd rrqjwpm +$ ls +dir bnl +dir lmw +7598 vsntvs.pdv +$ cd bnl +$ ls +245600 lmw.mgf +$ cd .. +$ cd lmw +$ ls +73396 hjpmqrq +$ cd .. +$ cd .. +$ cd .. +$ cd pmrdhrth +$ ls +173155 rrqjwpm.pjw +178530 smgpzs.qtj +$ cd .. +$ cd zbmcrvbh +$ ls +124201 fcqrwd +135578 hjpmqrq +54356 hnztplsp.qlh +dir lmw +58350 pbb.zln +dir qfrvdm +dir rcg +15267 rwbzjpt.djn +$ cd lmw +$ ls +dir bbbll +28362 bfgfwlf.wvg +229637 dmpndms.fln +146121 dncdssn.hdr +131039 frqqdsr.hbf +152805 hjpmqrq +dir mlz +$ cd bbbll +$ ls +169940 dncdssn.hdr +216888 pbb.zln +248369 tjpmlr.vmf +$ cd .. +$ cd mlz +$ ls +115167 bhfv.fts +$ cd .. +$ cd .. +$ cd qfrvdm +$ ls +284564 pbb.zln +$ cd .. +$ cd rcg +$ ls +dir sqzjz +$ cd sqzjz +$ ls +116435 jrstpcpl.zsq +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd tdn +$ ls +143971 cmg +133317 fcqrwd +dir pstpclp +133161 tddv +$ cd pstpclp +$ ls +267351 hjpmqrq +86930 rrqjwpm.dvl +$ cd .. +$ cd .. +$ cd wwtwnvh +$ ls +256584 frqqdsr.hbf +114564 twpq.wrd +$ cd .. +$ cd .. +$ cd vlgsrtm +$ ls +148089 bnl.jzj +119796 cjfphsfw.hnd +197668 cpw +dir dmpsnhdh +dir fjsglr +dir lmw +dir lqgrft +9231 pltdltrs +dir rmdp +109777 rncfff.fll +dir vgjzqjpq +dir ztnqnfnq +$ cd dmpsnhdh +$ ls +dir lltnrdtv +dir scthsg +$ cd lltnrdtv +$ ls +179511 pcvmpz +90913 tbr +$ cd .. +$ cd scthsg +$ ls +dir rrqjwpm +$ cd rrqjwpm +$ ls +188629 fcqrwd +$ cd .. +$ cd .. +$ cd .. +$ cd fjsglr +$ ls +139754 fcqrwd +dir pnsjwfzc +$ cd pnsjwfzc +$ ls +113848 lmw +$ cd .. +$ cd .. +$ cd lmw +$ ls +54999 dmpsnhdh +dir ffhcf +251476 frqqdsr.hbf +dir jpgqspqw +198972 nhfclq.pbh +180380 nqmjnvc.fvr +dir pfsjwmbc +213768 rcvccgcd +$ cd ffhcf +$ ls +40478 svmwstq.sjj +$ cd .. +$ cd jpgqspqw +$ ls +22181 hjpmqrq +$ cd .. +$ cd pfsjwmbc +$ ls +dir bcvchw +$ cd bcvchw +$ ls +225892 bnl.nwc +$ cd .. +$ cd .. +$ cd .. +$ cd lqgrft +$ ls +dir rrqjwpm +dir twpq +$ cd rrqjwpm +$ ls +54786 fcqrwd +3053 tthhqjm.ntd +$ cd .. +$ cd twpq +$ ls +109355 bnl +dir lmw +dir mhgqt +301291 rrqjwpm.lrm +271233 twpq.srp +$ cd lmw +$ ls +dir lmw +dir lngbszqm +$ cd lmw +$ ls +139640 pbb.zln +$ cd .. +$ cd lngbszqm +$ ls +98279 mqvq.gsj +283599 rvjd.dvt +$ cd .. +$ cd .. +$ cd mhgqt +$ ls +208165 fcqrwd +$ cd .. +$ cd .. +$ cd .. +$ cd rmdp +$ ls +dir bqn +170956 fcqrwd +90954 snnttp.gld +$ cd bqn +$ ls +75628 hdrgbrpc +$ cd .. +$ cd .. +$ cd vgjzqjpq +$ ls +dir bnl +dir wpfw +$ cd bnl +$ ls +25911 pbb.zln +$ cd .. +$ cd wpfw +$ ls +247784 bzll.ltc +$ cd .. +$ cd .. +$ cd ztnqnfnq +$ ls +dir dtpzsrfc +214055 srgzhp.nlr +$ cd dtpzsrfc +$ ls +142652 bhgwj diff --git a/src/Day7.hs b/src/Day7.hs new file mode 100644 index 0000000..e25e21b --- /dev/null +++ b/src/Day7.hs @@ -0,0 +1,97 @@ +module Day7 ( + buildTree, + buildTree', + mkdir, + Directory (..), + calculateSize, + filterDirectories, + sumUp, + day7 +) where + +import Day7.Parser +import Data.Map (Map) +import qualified Data.Map as Map + +data Directory = Directory + { sub :: Map String Directory + , files :: Map String Int + , isRoot :: Bool +} deriving (Eq) + + +instance Show Directory where + show d = show (files d) ++ " - " ++ show (sub d) ++ "\n" + +mkdir :: Directory +mkdir = Directory { sub = Map.empty, files = Map.empty, isRoot = False } + +rootDirectory :: Directory +rootDirectory = Directory { sub = Map.empty, files = Map.empty, isRoot = True } + +buildTree :: [TerminalCommand] -> Directory +buildTree commands = fst (buildTree' rootDirectory commands) + +buildTree' :: Directory -> [TerminalCommand] -> (Directory, [TerminalCommand]) +buildTree' dir [] = (dir, []) +buildTree' dir (command:cs) = case command of + Listing entries -> + let asFiles = Map.fromList $ toFiles entries + newDir = dir { files = asFiles } + in buildTree' newDir cs + In dirName -> + let subFolders = sub dir + selectedDir = Map.findWithDefault mkdir dirName subFolders + (replacement, rest) = buildTree' selectedDir cs + updatedSub = Map.insert dirName replacement subFolders + in buildTree' dir { sub = updatedSub} rest + Out -> (dir, cs) + Root -> if isRoot dir + then buildTree' dir cs + else (dir, command:cs) + +toFiles :: [ListingEntry] -> [(String, Int)] +toFiles ((FileListing name size):rest) = (name, size): toFiles rest +toFiles (_:rest) = toFiles rest +toFiles [] = [] + +sizeThreshold :: Int +sizeThreshold = 100000 + +calculateSize :: Directory -> Int +calculateSize dir = sum (Map.elems (files dir)) + sum sizes + where + subFolders = Map.elems (sub dir) + sizes = map calculateSize subFolders + +flatten :: Directory -> [(String, Directory)] +flatten dir = flatten' ("/", dir) + where + flatten' (name, d) = (name, d) : concatMap flatten' (Map.toList (sub d)) + +sizeOfDirectories :: Directory -> [(String, Int)] +sizeOfDirectories dir = map withSize allDirectories + where + allDirectories = flatten dir + withSize (name, directory) = (name, calculateSize directory) + +filterDirectories :: (Int -> Bool) -> Directory -> [(String, Int)] +filterDirectories predicate dir = filter (\(_, size) -> predicate size) $ sizeOfDirectories dir + +sumUp :: [(String, Int)] -> Int +sumUp = sum . map snd + + +forceRight :: Either a b -> b +forceRight (Left _) = error "forced Right but got Left" +forceRight (Right b) = b + +day7 :: IO () +day7 = do + input <- readFile "ressources/day07-input" + putStrLn "Day7" + let parsed = forceRight $ parseTerminalLines input + let tree = buildTree parsed + let filtered = filterDirectories (<= 100000) tree + let summed = sumUp filtered + putStrLn ("Sum of those directories is " ++ show summed) diff --git a/src/Day7/Parser.hs b/src/Day7/Parser.hs new file mode 100644 index 0000000..519d68f --- /dev/null +++ b/src/Day7/Parser.hs @@ -0,0 +1,68 @@ +module Day7.Parser ( + parseTerminalLines, + TerminalCommand (..), + ListingEntry (..), + DirName, + FileName, + Size +) where + +import Text.ParserCombinators.Parsec + +type DirName = String +type FileName = String +type Size = Int + +data ListingEntry = DirListing DirName | FileListing FileName Size + deriving (Show, Eq) + +data TerminalCommand = In DirName | Out | Root | Listing [ListingEntry] + deriving (Show, Eq) + +parseTerminalLines :: String -> Either ParseError [TerminalCommand] +parseTerminalLines = parse terminal "(error)" + +terminal :: GenParser Char st [TerminalCommand] +terminal = many command + +command :: GenParser Char st TerminalCommand +command = do + _ <- string "$ " + cd <|> ls + +ls :: GenParser Char st TerminalCommand +ls = do + _ <- string "ls\n" + entries <- many listingEntry + return $ Listing entries + +listingEntry :: GenParser Char st ListingEntry +listingEntry = dirListing <|> fileListing + +dirListing :: GenParser Char st ListingEntry +dirListing = do + _ <- string "dir " + dirName <- many $ noneOf "\n" + _ <- char '\n' + return $ DirListing dirName + +fileListing :: GenParser Char st ListingEntry +fileListing = do + fileSize <- many1 digit + _ <- char ' ' + fileName <- many $ noneOf "\n" + _ <- char '\n' + return $ FileListing fileName (read fileSize) + +cd :: GenParser Char st TerminalCommand +cd = do + _ <- string "cd " + name <- many $ noneOf "\n" + _ <- char '\n' + return (nameToDir name) + +nameToDir :: DirName -> TerminalCommand +nameToDir "/" = Root +nameToDir ".." = Out +nameToDir ds = In ds + diff --git a/src/Lib.hs b/src/Lib.hs index 5cd6ee7..c4c1262 100644 --- a/src/Lib.hs +++ b/src/Lib.hs @@ -8,6 +8,7 @@ import Day3 import Day4 import Day5 import Day6 +import Day7 someFunc :: IO () someFunc = do @@ -22,5 +23,7 @@ someFunc = do day5 putStrLn "-----------" day6 + putStrLn "-----------" + day7 diff --git a/test/Day7Spec.hs b/test/Day7Spec.hs new file mode 100644 index 0000000..7efbdce --- /dev/null +++ b/test/Day7Spec.hs @@ -0,0 +1,133 @@ +{-# LANGUAGE QuasiQuotes #-} +module Day7Spec (spec) where + +import Test.Hspec +import Text.Heredoc + +import Day7 +import Day7.Parser +import qualified Data.Map as Map + +inputPart1 :: String +inputPart1 = [str|$ cd / + |$ ls + |dir a + |14848514 b.txt + |8504156 c.dat + |dir d + |$ cd a + |$ ls + |dir e + |29116 f + |2557 g + |62596 h.lst + |$ cd e + |$ ls + |584 i + |$ cd .. + |$ cd .. + |$ cd d + |$ ls + |4060174 j + |8033020 d.log + |5626152 d.ext + |7214296 k + |] + +cdTerm :: [TerminalCommand] +cdTerm = forceRight $ parseTerminalLines + [str|$ cd foo + |$ ls + |23 f + |34 f2 + |dir d + |$ cd .. + |] + +cdOutTerm :: [TerminalCommand] +cdOutTerm = forceRight $ parseTerminalLines + [str|$ cd foo + |$ ls + |42 f + |$ cd .. + |$ cd bar + |$ ls + |100 baba + |$ cd x + |$ cd / + |$ ls + |23 f + |dir foo + |dir bar + |] +cdOutParsed :: [TerminalCommand] +cdOutParsed = [ + In "foo", + Listing [FileListing "f" 42], + Out, + In "bar", + Listing [FileListing "baba" 100], + In "x", + Root, + Listing [FileListing "f" 23, DirListing "foo", DirListing "bar"] + ] + +forceRight :: Either a b -> b +forceRight (Left _) = error "forced Right but got Left" +forceRight (Right b) = b + +spec :: Spec +spec = + describe "Day7" $ do + describe "Part1" $ do + describe "parser" $ do + it "parses an ls command" $ do + parseTerminalLines "$ ls\n" `shouldBe` Right [Listing []] + it "parses a cd up command" $ do + parseTerminalLines "$ cd ..\n" `shouldBe` Right [Out] + it "parses a cd root command" $ do + parseTerminalLines "$ cd /\n" `shouldBe` Right [Root] + it "parses a cd in command" $ do + parseTerminalLines "$ cd dirname\n" `shouldBe` Right [In "dirname"] + it "parses a file listing line" $ do + parseTerminalLines "$ ls\n1234 f\n$ cd foo\n" `shouldBe` Right [Listing [FileListing "f" 1234], In "foo"] + it "parses a larger shell log" $ do + cdOutTerm `shouldBe` cdOutParsed + describe "tree" $ do + it "reads a listing" $ do + buildTree [Listing [FileListing "f" 123]] `shouldBe` + mkdir { files = Map.singleton "f" 123, isRoot = True } + it "changes dir" $ do + buildTree cdTerm `shouldBe` + mkdir { + sub = Map.fromList [ + ("foo", mkdir { files = Map.fromList [("f", 23), ("f2", 34)] }) + ], + files = Map.empty, + isRoot = True + } + it "changes dir outwards" $ do + buildTree cdOutTerm `shouldBe` + mkdir { + sub = Map.fromList [ + ("foo", mkdir { files = Map.fromList [("f", 42)] } ), + ("bar", mkdir { + sub = Map.fromList [("x", mkdir)], + files = Map.fromList [("baba", 100)] + } ) + ], + files = Map.fromList [("f", 23)], + isRoot = True + } + it "calculates size of directories" $ do + calculateSize mkdir { files = Map.fromList [("f", 23), ("f2", 34)] } + `shouldBe` 23 + 34 + calculateSize mkdir { + sub = Map.fromList [ ("d", mkdir { files = Map.fromList [("f", 23), ("f2", 34)] })] } + `shouldBe` 23 + 34 + it "sums stuff up" $ do + let parsed = forceRight $ parseTerminalLines inputPart1 + let tree = buildTree parsed + let filtered = filterDirectories (<= 100000) tree + let summed = sumUp filtered + summed `shouldBe` 95437