blob: 5f507c433928d4ac9e1743d24f68b2d89962e1db (
plain) (
tree)
|
|
module Solutions.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)
|