Created
December 14, 2022 03:17
-
-
Save tildekarthik/f6886462a38b9dd77e873b563b274dc1 to your computer and use it in GitHub Desktop.
Advent of Code F# Learning 2022 Day 7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System.IO | |
let testTxt = """$ 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""" | |
type LineType = | |
| CommandLine of string | |
| OutputFileLine of string | |
| OutputDirLine of string | |
type DirectoryItem = { name:string;parent:string;} | |
type FileItem = { name:string;parent:string;size:int;} | |
type ContentItem = | |
| Dir of DirectoryItem | |
| File of FileItem | |
let parseLineType (line:string) = | |
if (line.StartsWith("$")) then | |
CommandLine line | |
elif (line.StartsWith("dir")) then | |
OutputDirLine line | |
else | |
OutputFileLine line | |
let parseDirLine (line:string) (currDirName:string) = | |
let name = currDirName+"/"+line.Substring(4) | |
{name=name;parent=currDirName} | |
let parseFileLine (line:string) (currDirName:string) = | |
let parts = line.Split(' ') | |
let size = int(parts.[0]) | |
let name = parts.[1] | |
{name=name;parent=currDirName;size=size} | |
let changeDirectory (cdCommandLine:string) (currDir:DirectoryItem) (allThings: ContentItem[]) = | |
let dirName = cdCommandLine.Split("cd ").[1] | |
match dirName with | |
|"/" -> {name="/";parent=""},allThings | |
|".." -> | |
let parentDir = allThings |> Array.filter (fun x -> match x with |Dir d -> d.name = currDir.parent |_-> false) |> Array.item 0 | |
match parentDir with | |
|Dir d -> d,allThings | |
|_-> failwith "parentDir is not a directory" | |
|_ -> | |
let newDir = allThings |> Array.filter (fun x -> match x with |Dir d -> d.name = (currDir.name+"/"+dirName) |_-> false) |> Array.item 0 | |
match newDir with | |
|Dir d -> d,allThings | |
|_-> failwith "newDir is not a directory" | |
let parseCommandLine (line:string) (currDir:DirectoryItem) (allThings: ContentItem[]) = | |
let cmd = line.Split(' ').[1] | |
if (cmd = "cd") then | |
changeDirectory line currDir allThings | |
else | |
(currDir, allThings) | |
let parseLine (line:string) (currDir:DirectoryItem) (allThings: ContentItem[]) = | |
match parseLineType line with | |
|CommandLine cmd -> parseCommandLine cmd currDir allThings | |
|OutputDirLine dirLine -> | |
let newDir = parseDirLine dirLine currDir.name | |
let newAllThings = allThings |> Array.append [|Dir newDir|] | |
(currDir, newAllThings) | |
|OutputFileLine fileLine -> | |
let newFile = parseFileLine fileLine currDir.name | |
let newAllThings = allThings |> Array.append [|File newFile|] | |
(currDir, newAllThings) | |
let compileTree (lines:string[]) = | |
let mutable currDir = {name="/";parent=""} | |
let mutable allThings:ContentItem[] = [|Dir currDir|] | |
for line in lines do | |
let (newCurrDir, newAllThings) = parseLine line currDir allThings | |
currDir <- newCurrDir | |
allThings <- newAllThings | |
allThings | |
let rec getDirectorySize (currDir:DirectoryItem) (allThings:ContentItem[]) = | |
let files = allThings |> Array.filter (fun x -> match x with |File f -> f.parent = currDir.name |_-> false) | |
let dirs = allThings |> Array.filter (fun x -> match x with |Dir d -> d.parent = currDir.name |_-> false) | |
let fileSizes = files |> Array.map (fun x -> match x with |File f -> f.size |_-> 0)|> Array.sum | |
let dirSizes = dirs |> Array.map (fun x -> match x with |Dir d -> getDirectorySize d allThings |_-> 0) |> Array.sum | |
fileSizes + dirSizes | |
let mainPart1 (lines:string[]) = | |
let allThings = compileTree lines | |
let directories = allThings |> Array.filter (fun x -> match x with |Dir d -> true |_-> false)|> Array.map (fun x -> match x with |Dir d -> d |_-> failwith "not a directory") | |
let dirSizes = directories |> Array.map (fun x -> getDirectorySize x allThings) | |
dirSizes |> Array.filter (fun x -> x < 100000) |> Array.sum | |
let mainPart2 (lines:string[]) = | |
let MAX_SPACE = 70000000 | |
let SPACE_REQUIRED = 30000000 | |
let allThings = compileTree lines | |
let directories = allThings |> Array.filter (fun x -> match x with |Dir d -> true |_-> false)|> Array.map (fun x -> match x with |Dir d -> d |_-> failwith "not a directory") | |
let dirSizes = directories |> Array.map (fun x -> getDirectorySize x allThings) | |
let space_used = dirSizes |> Array.max | |
let space_to_free = SPACE_REQUIRED - (MAX_SPACE - space_used) | |
dirSizes |> Array.filter (fun x -> x > space_to_free) |> Array.min | |
printfn "%d" (mainPart1 (File.ReadAllLines("inp7.txt"))) | |
printfn "%d" (mainPart2 (File.ReadAllLines("inp7.txt"))) | |
// printfn "%d" (mainPart1 (testTxt.Split('\n'))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment