diff options
Diffstat (limited to 'solutions')
-rw-r--r-- | solutions/day7.fs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/solutions/day7.fs b/solutions/day7.fs new file mode 100644 index 0000000..622c54c --- /dev/null +++ b/solutions/day7.fs @@ -0,0 +1,56 @@ +namespace Solutions + +module Day7 = + open System.IO + open System.Text.RegularExpressions + + type Listing = + | LS + | CD of target: string + | Dir of name: string + | File of name: string * size: int + + let (|RegexMatch|_|) pattern line = + let matched = Regex.Match(line, pattern) + if matched.Success then + let groups = + matched.Groups |> Seq.map (fun x -> x.Value) |> Seq.tail |> List.ofSeq + Some groups + else None + + let parseListing = function + | RegexMatch "\$ cd (\/|\S+)" args -> CD args[0] + | RegexMatch "\$ ls" [] -> LS + | RegexMatch "dir (\S+)" name -> Dir name[0] + | RegexMatch "(\d+) (\S+)" data -> File (data[1], int data[0]) + | _ -> failwith "shouldn't happen" + + let input = File.ReadLines("inputs/day7.txt") |> Seq.map parseListing |> List.ofSeq + + + let dirSizes listings = + let processListing (pwd, tree) listing = + match listing with + | CD ".." -> (List.tail pwd, tree) + | CD target -> (target::pwd, tree) + | File (name, size) -> + let rec addFileSize rem dirs = + match rem with + | [] -> dirs + | _ :: t -> + let addIfExists current = defaultArg current 0 + size + let newDirs = Map.change rem (addIfExists >> Some) dirs + addFileSize t newDirs + pwd, addFileSize pwd tree + | _ -> pwd, tree + listings |> List.fold processListing ([], Map.empty) |> snd + + let part1 () = dirSizes input |> Map.values |> Seq.filter (fun size -> size <= 100000) |> Seq.sum + + let part2 () = + let sizes = dirSizes input + let totalSpace = 70000000 + let targetSpace = 30000000 + let usedSpace = sizes[[ "/" ]] + let needToFree = usedSpace - (totalSpace - targetSpace) + sizes.Values |> Seq.sort |> Seq.find (fun x -> x >= needToFree) \ No newline at end of file |