Skip to content

Instantly share code, notes, and snippets.

@waynejo
Last active February 24, 2023 12:00
Show Gist options
  • Save waynejo/b171e576cb1f50b23f358017ee721458 to your computer and use it in GitHub Desktop.
Save waynejo/b171e576cb1f50b23f358017ee721458 to your computer and use it in GitHub Desktop.
import java.io.FileInputStream
import scala.annotation.tailrec
import scala.io.StdIn
trait FileSystemElement {
def name: String
def size: BigInt
}
case class File(name: String, size: BigInt) extends FileSystemElement
case class Directory(name: String, size: BigInt, children: Map[String, FileSystemElement]) extends FileSystemElement {
def copy(children: Map[String, FileSystemElement]): Directory =
val totalSize = children.values.map(_.size).sum
Directory(name, totalSize, children)
}
case class FileSystem(path: Vector[String], root: Directory)
def appended(path: Vector[String], elements: Map[String, FileSystemElement], element: FileSystemElement): Map[String, FileSystemElement] =
path.headOption match
case Some(pathElement) =>
elements.getOrElse(pathElement, Directory(pathElement, 0, Map())) match
case directory@Directory(name, size, children) =>
val nextChildren = appended(path.tail, children, element)
elements + (name -> directory.copy(nextChildren))
case None =>
elements + (element.name -> element)
def process(system: FileSystem, commands: Vector[String]): FileSystem =
commands.headOption match
case Some(line) =>
val parts = line.split(" ")
parts match
case Array("$", "cd", "/") =>
process(system.copy(path = Vector()), commands.tail)
case Array("$", "cd", "..") =>
process(system.copy(path = system.path.init), commands.tail)
case Array("$", "cd", path) =>
process(system.copy(path = system.path :+ path), commands.tail)
case Array("$", "ls") =>
process(system, commands.tail)
case Array("dir", path) =>
val nextRootChildren = appended(system.path, system.root.children, Directory(path, 0, Map()))
process(system.copy(root = system.root.copy(nextRootChildren)), commands.tail)
case Array(size, path) =>
val nextRootChildren = appended(system.path, system.root.children, File(path, BigInt(size)))
process(system.copy(root = system.root.copy(nextRootChildren)), commands.tail)
case _=>
throw Exception("unknown command")
case None =>
system
def iterateFolder[T](directory: Directory, f: (T, FileSystemElement) => T, initial: T): T =
directory.children.values.foldLeft(initial)((acc, element) =>
element match
case file: File => f(acc, file)
case directory: Directory => iterateFolder(directory, f, f(acc, directory))
)
def solve7_1(inputs: Vector[String]): Int =
val system = process(FileSystem(Vector(), Directory("/", 0, Map())), inputs)
iterateFolder(system.root, (acc, element) => {
if 100000 >= element.size && element.isInstanceOf[Directory] then
acc + element.size.toInt
else
acc
}, 0)
def solve7_2(inputs: Vector[String]): Int =
val system = process(FileSystem(Vector(), Directory("/", 0, Map())), inputs)
val totalSize: BigInt = system.root.size
val diskSize: BigInt = 70000000
val requiredSize: BigInt = 30000000 - (diskSize - totalSize)
iterateFolder(system.root, (acc, element) => {
if requiredSize <= element.size && acc > element.size && element.isInstanceOf[Directory] then
element.size.toInt
else
acc
}, diskSize.toInt)
@main def solve7(): Unit =
val in = new FileInputStream("example7-2.in")
System.setIn(in)
val inputs = Iterator.continually(StdIn.readLine())
.takeWhile(line => null != line)
.toVector
println(solve7_1(inputs))
println(solve7_2(inputs))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment