package dev.claudio.adventofcode2022

fun main() {
    Day7().main()
}

private class Day7 {
    fun main() {
        val input = Support.readFileAsListString("2022/day7-input.txt")
        val tree : Directory = buildTree(input)
        val sumedVal: Long = calcResult(tree)
        println(sumedVal)
    }

    private fun calcResult(tree: Directory): Long {
        var result: Long = 0
        val maxSize = 100000L
        tree.dirs.forEach{
            val calcSize = it.calcSize()
            if (calcSize <= maxSize) result += calcSize
            result += it.dirs.sumOf { innerDir -> calcResult(innerDir) }
        }

        val calcSize = tree.calcSize()
        if (calcSize <= maxSize) result += calcSize
        return result
    }

    private fun buildTree(input: List<String>): Directory {
        var curDir = Directory("/", null)
        val root: Directory = curDir
        input
            .drop(1)
            .map { it.split(" ") }
            .forEach{
                if (it[0] == "$" && it[1] == "cd") {
                    // change dir
                    curDir = if (it[2] == "..") {
                        curDir.parentDir!!
                    } else {
                        curDir.dirs.find { node -> node.name == it[2] } as Directory
                    }
                } else if (it[0] == "$" && it[1] == "ls") {
                    // list dir
                } else {
                    val newNode: Node
                    if (it[0].startsWith("dir")) {
                        newNode = Directory(it[1], curDir)
                        curDir.dirs.add(newNode)
                    } else {
                        newNode = File(it[1], it[0].toLong())
                        curDir.files.add(newNode)
                    }
                }
            }
        println(root)
        return root
    }

    abstract class Node (val name: String) {
        abstract fun calcSize() : Long
    }
    data class File(val fileName: String, val fileSize: Long) : Node(fileName) {
        override fun calcSize(): Long {
            return fileSize
        }
    }
    data class Directory(
        val dirName: String,
        val parentDir: Directory?,
        val dirs: MutableList<Directory> = mutableListOf(),
        val files: MutableList<File> = mutableListOf(),
    ) : Node(dirName) {
        override fun calcSize(): Long {
            return dirs.sumOf { it.calcSize() } + files.sumOf { it.calcSize() }
        }
        override fun toString(): String {
            return "Directory(dirName='$dirName', parentDir=${parentDir?.name}, directories=$dirs, files=$files)"
        }
    }
}
package dev.claudio.adventofcode2022

fun main() {
    Day7().main()
}

private class Day7 {
    fun main() {
        val input = Support.readFileAsListString("2022/day7-input.txt")
        val tree : Directory = buildTree(input)
        val sumedVal: Long = calcResult(tree)
        println(sumedVal)
    }

    private fun calcResult(tree: Directory): Long {
        var result: Long = 0
        val maxSize = 100000L
        tree.dirs.forEach{
            val calcSize = it.calcSize()
            if (calcSize <= maxSize) result += calcSize
            result += it.dirs.sumOf { innerDir -> calcResult(innerDir) }
        }

        val calcSize = tree.calcSize()
        if (calcSize <= maxSize) result += calcSize
        return result
    }

    private fun buildTree(input: List<String>): Directory {
        var curDir = Directory("/", null)
        val root: Directory = curDir
        input
            .drop(1)
            .map { it.split(" ") }
            .forEach{
                if (it[0] == "$" && it[1] == "cd") {
                    // change dir
                    curDir = if (it[2] == "..") {
                        curDir.parentDir!!
                    } else {
                        curDir.dirs.find { node -> node.name == it[2] } as Directory
                    }
                } else if (it[0] == "$" && it[1] == "ls") {
                    // list dir
                } else {
                    val newNode: Node
                    if (it[0].startsWith("dir")) {
                        newNode = Directory(it[1], curDir)
                        curDir.dirs.add(newNode)
                    } else {
                        newNode = File(it[1], it[0].toLong())
                        curDir.files.add(newNode)
                    }
                }
            }
        println(root)
        return root
    }

    abstract class Node (val name: String) {
        abstract fun calcSize() : Long
    }
    data class File(val fileName: String, val fileSize: Long) : Node(fileName) {
        override fun calcSize(): Long {
            return fileSize
        }
    }
    data class Directory(
        val dirName: String,
        val parentDir: Directory?,
        val dirs: MutableList<Directory> = mutableListOf(),
        val files: MutableList<File> = mutableListOf(),
    ) : Node(dirName) {
        override fun calcSize(): Long {
            return dirs.sumOf { it.calcSize() } + files.sumOf { it.calcSize() }
        }
        override fun toString(): String {
            return "Directory(dirName='$dirName', parentDir=${parentDir?.name}, directories=$dirs, files=$files)"
        }
    }
}