This commit is contained in:
2022-12-19 01:34:35 +01:00
parent fe73cc9676
commit 4aa7ef8614
2 changed files with 1201 additions and 0 deletions

1096
day_07/input.txt Normal file

File diff suppressed because it is too large Load Diff

105
day_07/solve.nim Normal file
View File

@@ -0,0 +1,105 @@
import std/[strutils, strformat, sequtils]
const input = readFile("day_07/input.txt")
type
FileKind = enum
fkFile,
fkDirectory
File = ref object
name: string
parent: File
case kind: FileKind
of fkFile:
size: uint64
of fkDirectory:
children: seq[File]
proc `$`(file: FIle): string =
result.add fmt"File(name: {file.name}, kind: {$file.kind}, "
if file.kind == fkDirectory:
let childrenAsStr = file.children.mapIt($it).join(",")
result.add fmt"children: [{childrenAsStr}]"
elif file.kind == fkFile:
result.add fmt"size: {file.size}"
result.add ")"
proc root(file: File): File =
if file.parent.isNil:
return file
return file.parent.root
proc calcSize(file: File): uint64 =
assert file.kind == fkDirectory
return file.children.mapIt(if it.kind == fkFIle: it.size else: it.calcSize).foldl(a + b, 0.uint64)
proc processCommand(wd: File, command: string, output: string): File =
case command.split(" ")[0]:
of "cd":
let path = command.split(" ")[1]
case path:
of "/":
return wd.root
of "..":
return wd.parent
else:
for child in wd.children:
if child.name == path:
return child
let newFile = File(name: path, parent: wd, kind: fkDirectory)
wd.children.add newFile
return newFile
of "ls":
for file in output.splitLines:
if file.isEmptyOrWhitespace: break
let desc = file.split(" ")[0]
let name = file.split(" ")[1]
if desc == "dir":
wd.children.add(File(name: name, parent: wd, kind: fkDirectory))
else:
wd.children.add(File(name: name, parent: wd, kind: fkFile, size: desc.parseBiggestUInt))
return wd
proc traverseDirectoryLog(data: string): File =
var wd = File(name: "/", parent: nil, kind: fkDirectory, children: newSeq[File]())
var command: string
var output: string
for line in data.splitLines:
if line.startsWith "$":
if not command.isEmptyOrWhitespace:
wd = processCommand(wd, command, output)
command = line[2..line.len-1]
output = ""
continue
output.add line & "\n"
return processCommand(wd, command, output).root
iterator traverse(dir: File): File {.closure.} =
assert dir.kind == fkDirectory
for child in dir.children:
if child.kind != fkDirectory: continue
yield child
for subchild in child.traverse:
yield subchild
proc solvePart1() =
let root = traverseDirectoryLog(input)
var sum: uint64 = 0
for dir in traverse(root):
if (dir.calcSize <= 100000):
sum += dir.calcSize
echo "Sum of dirs < 100000: " & $sum
proc solvePart2() =
let root = traverseDirectoryLog(input)
var minimumSize = 30000000 - (70000000 - root.calcSize)
var smallestDir = root.calcSize
for dir in traverse(root):
let size = dir.calcSize
if size < minimumSize: continue
smallestDir = min(smallestDir, size)
echo "Smalles dir for update: " & $smallestDir
if isMainModule:
solvePart1()
solvePart2()