Day 7
This commit is contained in:
1096
day_07/input.txt
Normal file
1096
day_07/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
105
day_07/solve.nim
Normal file
105
day_07/solve.nim
Normal 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()
|
||||
Reference in New Issue
Block a user