package day19

import java.io.File
import java.lang.IllegalStateException
import java.util.PriorityQueue
import kotlin.math.ceil
import kotlin.math.max

fun main() {
    val regexp = Regex("\\d+")
    val blueprints = File("src/day19/input.txt").readLines()
        .map {
            regexp.findAll(it).drop(1).map { it.value.toInt() }.toList().let { matches ->
                listOf(
                    Quadruple(matches[0], 0, 0, 0),
                    Quadruple(matches[1], 0, 0, 0),
                    Quadruple(matches[2], matches[3], 0, 0),
                    Quadruple(matches[4], 0, matches[5], 0)
                )
            }
        }

    println(blueprints.map { maxGeodes(it, 24) }.mapIndexed { i, geodes -> (i + 1) * geodes }.sum())
    println(blueprints.take(3).map { maxGeodes(it, 32) }.reduce(Int::times))
}

fun maxGeodes(blueprint: List<Quadruple>, totalMinutes: Int): Int {
    var maxGeodes = 0
    val queue = PriorityQueue<State>().apply { add(State(1, Quadruple(1, 0, 0, 0), Quadruple(1, 0, 0, 0))) }
    while (queue.isNotEmpty()) {
        val state = queue.poll()
        maxGeodes = max(maxGeodes, state.materials.geode)
        if (state.minute == totalMinutes) continue
        val theoreticalMaxGeodes =
            state.materials.geode + (state.minute..totalMinutes).sumOf { it + state.robots.geode }
        if (theoreticalMaxGeodes > maxGeodes) {
            queue.addAll(state.next(blueprint, totalMinutes))
        }
    }
    return maxGeodes
}

data class Quadruple(val ore: Int, val clay: Int, val obsidian: Int, val geode: Int) {
    operator fun plus(other: Quadruple) =
        Quadruple(ore + other.ore, clay + other.clay, obsidian + other.obsidian, geode + other.geode)

    operator fun minus(other: Quadruple) =
        Quadruple(ore - other.ore, clay - other.clay, obsidian - other.obsidian, geode - other.geode)

    operator fun times(multiple: Int) =
        Quadruple(ore * multiple, clay * multiple, obsidian * multiple, geode * multiple)

    fun timeToBuild(required: Quadruple): Int = maxOf(
        if (required.ore <= 0) 0 else ceil(required.ore.toDouble() / ore).toInt(),
        if (required.clay <= 0) 0 else ceil(required.clay.toDouble() / clay).toInt(),
        if (required.obsidian <= 0) 0 else ceil(required.obsidian.toDouble() / obsidian).toInt(),
        if (required.geode <= 0) 0 else ceil(required.geode.toDouble() / geode).toInt()
    ) + 1

    companion object {
        fun of(index: Int) =
            when (index) {
                0 -> Quadruple(1, 0, 0, 0)
                1 -> Quadruple(0, 1, 0, 0)
                2 -> Quadruple(0, 0, 1, 0)
                3 -> Quadruple(0, 0, 0, 1)
                else -> throw IllegalStateException()
            }
    }
}

data class State(val minute: Int, val robots: Quadruple, val materials: Quadruple) : Comparable<State> {

    fun next(blueprint: List<Quadruple>, totalMinutes: Int): List<State> {
        val nextBuildStates = mutableListOf<State>()
        if (blueprint.maxOf { it.ore } > robots.ore && materials.ore > 0) {
            nextBuildStates += nextForRobot(blueprint, 0)
        }
        if (blueprint.maxOf { it.clay } > robots.clay && materials.ore > 0) {
            nextBuildStates += nextForRobot(blueprint, 1)
        }
        if (blueprint.maxOf { it.obsidian } > robots.obsidian && materials.ore > 0 && materials.clay > 0) {
            nextBuildStates += nextForRobot(blueprint, 2)
        }
        if (materials.ore > 0 && materials.obsidian > 0) {
            nextBuildStates += nextForRobot(blueprint, 3)
        }
        val nextBuildStatesWithinTime = nextBuildStates.filter { it.minute <= totalMinutes }.toMutableList()
        return nextBuildStatesWithinTime.ifEmpty { listOf(State(totalMinutes, robots, materials + (robots * (totalMinutes - minute)))) }
    }

    private fun nextForRobot(blueprint: List<Quadruple>, index: Int): State {
        return robots.timeToBuild(blueprint[index] - materials)
            .let { time ->
                State(
                    minute + time,
                    robots + Quadruple.of(index),
                    materials - blueprint[index] + (robots * time)
                )
            }

    }

    override fun compareTo(other: State) = other.materials.geode.compareTo(materials.geode)
}

Compiled from "Day19.kt"
public final class day19.Day19Kt {
  public static final void main();
    Code:
       0: new           #8                  // class kotlin/text/Regex
       3: dup
       4: ldc           #10                 // String \\d+
       6: invokespecial #14                 // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
       9: astore_0
      10: new           #16                 // class java/io/File
      13: dup
      14: ldc           #18                 // String src/day19/input.txt
      16: invokespecial #19                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      19: aconst_null
      20: iconst_1
      21: aconst_null
      22: invokestatic  #25                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      25: checkcast     #27                 // class java/lang/Iterable
      28: astore_2
      29: nop
      30: iconst_0
      31: istore_3
      32: aload_2
      33: astore        4
      35: new           #29                 // class java/util/ArrayList
      38: dup
      39: aload_2
      40: bipush        10
      42: invokestatic  #35                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      45: invokespecial #38                 // Method java/util/ArrayList."<init>":(I)V
      48: checkcast     #40                 // class java/util/Collection
      51: astore        5
      53: iconst_0
      54: istore        6
      56: aload         4
      58: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      63: astore        7
      65: aload         7
      67: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      72: ifeq          294
      75: aload         7
      77: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      82: astore        8
      84: aload         5
      86: aload         8
      88: checkcast     #56                 // class java/lang/String
      91: astore        9
      93: astore        14
      95: iconst_0
      96: istore        10
      98: aload_0
      99: aload         9
     101: checkcast     #58                 // class java/lang/CharSequence
     104: iconst_0
     105: iconst_2
     106: aconst_null
     107: invokestatic  #62                 // Method kotlin/text/Regex.findAll$default:(Lkotlin/text/Regex;Ljava/lang/CharSequence;IILjava/lang/Object;)Lkotlin/sequences/Sequence;
     110: iconst_1
     111: invokestatic  #68                 // Method kotlin/sequences/SequencesKt.drop:(Lkotlin/sequences/Sequence;I)Lkotlin/sequences/Sequence;
     114: invokedynamic #88,  0             // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
     119: invokestatic  #92                 // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
     122: invokestatic  #96                 // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
     125: astore        11
     127: iconst_0
     128: istore        12
     130: iconst_4
     131: anewarray     #98                 // class day19/Quadruple
     134: astore        13
     136: aload         13
     138: iconst_0
     139: new           #98                 // class day19/Quadruple
     142: dup
     143: aload         11
     145: iconst_0
     146: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     151: checkcast     #106                // class java/lang/Number
     154: invokevirtual #110                // Method java/lang/Number.intValue:()I
     157: iconst_0
     158: iconst_0
     159: iconst_0
     160: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
     163: aastore
     164: aload         13
     166: iconst_1
     167: new           #98                 // class day19/Quadruple
     170: dup
     171: aload         11
     173: iconst_1
     174: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     179: checkcast     #106                // class java/lang/Number
     182: invokevirtual #110                // Method java/lang/Number.intValue:()I
     185: iconst_0
     186: iconst_0
     187: iconst_0
     188: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
     191: aastore
     192: aload         13
     194: iconst_2
     195: new           #98                 // class day19/Quadruple
     198: dup
     199: aload         11
     201: iconst_2
     202: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     207: checkcast     #106                // class java/lang/Number
     210: invokevirtual #110                // Method java/lang/Number.intValue:()I
     213: aload         11
     215: iconst_3
     216: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     221: checkcast     #106                // class java/lang/Number
     224: invokevirtual #110                // Method java/lang/Number.intValue:()I
     227: iconst_0
     228: iconst_0
     229: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
     232: aastore
     233: aload         13
     235: iconst_3
     236: new           #98                 // class day19/Quadruple
     239: dup
     240: aload         11
     242: iconst_4
     243: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     248: checkcast     #106                // class java/lang/Number
     251: invokevirtual #110                // Method java/lang/Number.intValue:()I
     254: iconst_0
     255: aload         11
     257: iconst_5
     258: invokeinterface #104,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     263: checkcast     #106                // class java/lang/Number
     266: invokevirtual #110                // Method java/lang/Number.intValue:()I
     269: iconst_0
     270: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
     273: aastore
     274: aload         13
     276: invokestatic  #117                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     279: nop
     280: nop
     281: nop
     282: aload         14
     284: swap
     285: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     290: pop
     291: goto          65
     294: aload         5
     296: checkcast     #100                // class java/util/List
     299: nop
     300: astore_1
     301: aload_1
     302: checkcast     #27                 // class java/lang/Iterable
     305: astore_2
     306: iconst_0
     307: istore_3
     308: aload_2
     309: astore        4
     311: new           #29                 // class java/util/ArrayList
     314: dup
     315: aload_2
     316: bipush        10
     318: invokestatic  #35                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     321: invokespecial #38                 // Method java/util/ArrayList."<init>":(I)V
     324: checkcast     #40                 // class java/util/Collection
     327: astore        5
     329: iconst_0
     330: istore        6
     332: aload         4
     334: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     339: astore        7
     341: aload         7
     343: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     348: ifeq          396
     351: aload         7
     353: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     358: astore        8
     360: aload         5
     362: aload         8
     364: checkcast     #100                // class java/util/List
     367: astore        9
     369: astore        14
     371: iconst_0
     372: istore        10
     374: aload         9
     376: bipush        24
     378: invokestatic  #125                // Method maxGeodes:(Ljava/util/List;I)I
     381: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     384: aload         14
     386: swap
     387: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     392: pop
     393: goto          341
     396: aload         5
     398: checkcast     #100                // class java/util/List
     401: nop
     402: checkcast     #27                 // class java/lang/Iterable
     405: astore_2
     406: nop
     407: iconst_0
     408: istore_3
     409: aload_2
     410: astore        4
     412: new           #29                 // class java/util/ArrayList
     415: dup
     416: aload_2
     417: bipush        10
     419: invokestatic  #35                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     422: invokespecial #38                 // Method java/util/ArrayList."<init>":(I)V
     425: checkcast     #40                 // class java/util/Collection
     428: astore        5
     430: iconst_0
     431: istore        6
     433: iconst_0
     434: istore        7
     436: aload         4
     438: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     443: astore        8
     445: aload         8
     447: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     452: ifeq          522
     455: aload         8
     457: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     462: astore        9
     464: aload         5
     466: iload         7
     468: iinc          7, 1
     471: istore        10
     473: iload         10
     475: ifge          481
     478: invokestatic  #134                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
     481: iload         10
     483: aload         9
     485: checkcast     #106                // class java/lang/Number
     488: invokevirtual #110                // Method java/lang/Number.intValue:()I
     491: istore        11
     493: istore        12
     495: astore        14
     497: iconst_0
     498: istore        13
     500: iload         12
     502: iconst_1
     503: iadd
     504: iload         11
     506: imul
     507: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     510: aload         14
     512: swap
     513: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     518: pop
     519: goto          445
     522: aload         5
     524: checkcast     #100                // class java/util/List
     527: nop
     528: checkcast     #27                 // class java/lang/Iterable
     531: invokestatic  #138                // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
     534: istore_2
     535: getstatic     #144                // Field java/lang/System.out:Ljava/io/PrintStream;
     538: iload_2
     539: invokevirtual #149                // Method java/io/PrintStream.println:(I)V
     542: aload_1
     543: checkcast     #27                 // class java/lang/Iterable
     546: iconst_3
     547: invokestatic  #153                // Method kotlin/collections/CollectionsKt.take:(Ljava/lang/Iterable;I)Ljava/util/List;
     550: checkcast     #27                 // class java/lang/Iterable
     553: astore_2
     554: iconst_0
     555: istore_3
     556: aload_2
     557: astore        4
     559: new           #29                 // class java/util/ArrayList
     562: dup
     563: aload_2
     564: bipush        10
     566: invokestatic  #35                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     569: invokespecial #38                 // Method java/util/ArrayList."<init>":(I)V
     572: checkcast     #40                 // class java/util/Collection
     575: astore        5
     577: iconst_0
     578: istore        6
     580: aload         4
     582: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     587: astore        7
     589: aload         7
     591: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     596: ifeq          644
     599: aload         7
     601: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     606: astore        8
     608: aload         5
     610: aload         8
     612: checkcast     #100                // class java/util/List
     615: astore        9
     617: astore        14
     619: iconst_0
     620: istore        10
     622: aload         9
     624: bipush        32
     626: invokestatic  #125                // Method maxGeodes:(Ljava/util/List;I)I
     629: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     632: aload         14
     634: swap
     635: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     640: pop
     641: goto          589
     644: aload         5
     646: checkcast     #100                // class java/util/List
     649: nop
     650: checkcast     #27                 // class java/lang/Iterable
     653: astore_2
     654: nop
     655: iconst_0
     656: istore_3
     657: aload_2
     658: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     663: astore        4
     665: aload         4
     667: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     672: ifne          685
     675: new           #155                // class java/lang/UnsupportedOperationException
     678: dup
     679: ldc           #157                // String Empty collection can\'t be reduced.
     681: invokespecial #158                // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V
     684: athrow
     685: aload         4
     687: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     692: astore        5
     694: aload         4
     696: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     701: ifeq          745
     704: aload         5
     706: aload         4
     708: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     713: checkcast     #106                // class java/lang/Number
     716: invokevirtual #110                // Method java/lang/Number.intValue:()I
     719: istore        6
     721: checkcast     #106                // class java/lang/Number
     724: invokevirtual #110                // Method java/lang/Number.intValue:()I
     727: istore        7
     729: iconst_0
     730: istore        8
     732: iload         7
     734: iload         6
     736: imul
     737: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     740: astore        5
     742: goto          694
     745: aload         5
     747: checkcast     #106                // class java/lang/Number
     750: invokevirtual #110                // Method java/lang/Number.intValue:()I
     753: istore_2
     754: getstatic     #144                // Field java/lang/System.out:Ljava/io/PrintStream;
     757: iload_2
     758: invokevirtual #149                // Method java/io/PrintStream.println:(I)V
     761: return

  public static final int maxGeodes(java.util.List<day19.Quadruple>, int);
    Code:
       0: aload_0
       1: ldc           #199                // String blueprint
       3: invokestatic  #205                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_2
       8: new           #207                // class java/util/PriorityQueue
      11: dup
      12: invokespecial #209                // Method java/util/PriorityQueue."<init>":()V
      15: astore        4
      17: aload         4
      19: astore        5
      21: iconst_0
      22: istore        6
      24: aload         5
      26: new           #211                // class day19/State
      29: dup
      30: iconst_1
      31: new           #98                 // class day19/Quadruple
      34: dup
      35: iconst_1
      36: iconst_0
      37: iconst_0
      38: iconst_0
      39: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
      42: new           #98                 // class day19/Quadruple
      45: dup
      46: iconst_1
      47: iconst_0
      48: iconst_0
      49: iconst_0
      50: invokespecial #113                // Method day19/Quadruple."<init>":(IIII)V
      53: invokespecial #214                // Method day19/State."<init>":(ILday19/Quadruple;Lday19/Quadruple;)V
      56: invokevirtual #215                // Method java/util/PriorityQueue.add:(Ljava/lang/Object;)Z
      59: pop
      60: aload         4
      62: astore_3
      63: aload_3
      64: checkcast     #40                 // class java/util/Collection
      67: invokeinterface #218,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      72: ifne          79
      75: iconst_1
      76: goto          80
      79: iconst_0
      80: ifeq          243
      83: aload_3
      84: invokevirtual #221                // Method java/util/PriorityQueue.poll:()Ljava/lang/Object;
      87: checkcast     #211                // class day19/State
      90: astore        4
      92: iload_2
      93: aload         4
      95: invokevirtual #225                // Method day19/State.getMaterials:()Lday19/Quadruple;
      98: invokevirtual #228                // Method day19/Quadruple.getGeode:()I
     101: invokestatic  #234                // Method java/lang/Math.max:(II)I
     104: istore_2
     105: aload         4
     107: invokevirtual #237                // Method day19/State.getMinute:()I
     110: iload_1
     111: if_icmpeq     63
     114: aload         4
     116: invokevirtual #225                // Method day19/State.getMaterials:()Lday19/Quadruple;
     119: invokevirtual #228                // Method day19/Quadruple.getGeode:()I
     122: new           #239                // class kotlin/ranges/IntRange
     125: dup
     126: aload         4
     128: invokevirtual #237                // Method day19/State.getMinute:()I
     131: iload_1
     132: invokespecial #242                // Method kotlin/ranges/IntRange."<init>":(II)V
     135: checkcast     #27                 // class java/lang/Iterable
     138: astore        6
     140: istore        12
     142: iconst_0
     143: istore        7
     145: aload         6
     147: invokeinterface #44,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     152: astore        8
     154: aload         8
     156: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     161: ifeq          208
     164: aload         8
     166: checkcast     #244                // class kotlin/collections/IntIterator
     169: invokevirtual #247                // Method kotlin/collections/IntIterator.nextInt:()I
     172: istore        9
     174: iload         7
     176: iload         9
     178: istore        10
     180: istore        13
     182: iconst_0
     183: istore        11
     185: iload         10
     187: aload         4
     189: invokevirtual #250                // Method day19/State.getRobots:()Lday19/Quadruple;
     192: invokevirtual #228                // Method day19/Quadruple.getGeode:()I
     195: iadd
     196: istore        14
     198: iload         13
     200: iload         14
     202: iadd
     203: istore        7
     205: goto          154
     208: iload         7
     210: istore        13
     212: iload         12
     214: iload         13
     216: iadd
     217: istore        5
     219: iload         5
     221: iload_2
     222: if_icmple     63
     225: aload_3
     226: aload         4
     228: aload_0
     229: iload_1
     230: invokevirtual #253                // Method day19/State.next:(Ljava/util/List;I)Ljava/util/List;
     233: checkcast     #40                 // class java/util/Collection
     236: invokevirtual #257                // Method java/util/PriorityQueue.addAll:(Ljava/util/Collection;)Z
     239: pop
     240: goto          63
     243: iload_2
     244: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #269                // Method main:()V
       3: return

  private static final int main$lambda$2$lambda$0(kotlin.text.MatchResult);
    Code:
       0: aload_0
       1: ldc_w         #272                // String it
       4: invokestatic  #205                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokeinterface #278,  1          // InterfaceMethod kotlin/text/MatchResult.getValue:()Ljava/lang/String;
      13: invokestatic  #282                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      16: ireturn
}


package day07

import readInput

private const val THRESHOLD_PART1 = 100000
private const val TOTAL_DISC_SIZE = 70000000
private const val SIZE_FOR_UPDATE = 30000000

data class Directory(
    val name: String,
    val files: MutableSet<Int>,
    val dirs: MutableMap<String, Directory>,
    val parent: Directory? = null
) {
    val totalSize: Int
        get() = files.sum() + dirs.values.sumOf { it.totalSize }

    val allDirectories: List<Directory>
        get() = listOf(this) + dirs.values.flatMap { it.allDirectories }

    private fun root(): Directory = parent?.root() ?: this

    fun changeInto(arg: String): Directory {
        return when (arg) {
            "/" -> root()
            ".." -> parent ?: root()
            else -> dirs[arg] ?: Directory(arg, mutableSetOf(), mutableMapOf(), this)
        }
    }

    override fun hashCode(): Int = name.hashCode()

    override fun equals(other: Any?): Boolean = if (other is Directory) name == other.name else false
}

fun main() {
    val input = readInput("main/day07/Day07")
    println(part1(input))
    println(part2(input))
}

fun part1(input: List<String>): Int {

    return input.parseDirectories().allDirectories
        .filter { it.totalSize <= THRESHOLD_PART1 }
        .sumOf { it.totalSize }
}

fun part2(input: List<String>): Int {

    val root = input.parseDirectories()

    return root.allDirectories.filter {
        it.totalSize >= SIZE_FOR_UPDATE - (TOTAL_DISC_SIZE - root.totalSize)
    }.minBy { it.totalSize }.totalSize
}

fun List<String>.parseDirectories(): Directory {

    val root = Directory("/", mutableSetOf(), mutableMapOf())
    var current = root
    forEach { line ->
        when {
            line.isCd() -> current = current.changeInto(line.lastArg())
            line.isDir() -> current.dirs[line.lastArg()] = Directory(line.lastArg(), mutableSetOf(), mutableMapOf(), current)
            line.isFile() -> current.files.add(line.firstArg().toInt())
        }
    }
    return root
}

private fun String.lastArg() = split(" ").last()
private fun String.firstArg() = split(" ").first()

fun String.isCd() = startsWith("$ cd")
fun String.isFile() = first().isDigit()
fun String.isDir() = startsWith("dir")

Compiled from "day07.kt"
public final class day07.Day07Kt {
  private static final int THRESHOLD_PART1;

  private static final int TOTAL_DISC_SIZE;

  private static final int SIZE_FOR_UPDATE;

  public static final void main();
    Code:
       0: ldc           #8                  // String main/day07/Day07
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: invokestatic  #18                 // Method part1:(Ljava/util/List;)I
      10: istore_1
      11: getstatic     #24                 // Field java/lang/System.out:Ljava/io/PrintStream;
      14: iload_1
      15: invokevirtual #30                 // Method java/io/PrintStream.println:(I)V
      18: aload_0
      19: invokestatic  #33                 // Method part2:(Ljava/util/List;)I
      22: istore_1
      23: getstatic     #24                 // Field java/lang/System.out:Ljava/io/PrintStream;
      26: iload_1
      27: invokevirtual #30                 // Method java/io/PrintStream.println:(I)V
      30: return

  public static final int part1(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #38                 // String input
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #48                 // Method parseDirectories:(Ljava/util/List;)Lday07/Directory;
      10: invokevirtual #54                 // Method day07/Directory.getAllDirectories:()Ljava/util/List;
      13: checkcast     #56                 // class java/lang/Iterable
      16: astore_1
      17: nop
      18: iconst_0
      19: istore_2
      20: aload_1
      21: astore_3
      22: new           #58                 // class java/util/ArrayList
      25: dup
      26: invokespecial #61                 // Method java/util/ArrayList."<init>":()V
      29: checkcast     #63                 // class java/util/Collection
      32: astore        4
      34: iconst_0
      35: istore        5
      37: aload_3
      38: invokeinterface #67,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          105
      55: aload         6
      57: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: astore        7
      64: aload         7
      66: checkcast     #50                 // class day07/Directory
      69: astore        8
      71: iconst_0
      72: istore        9
      74: aload         8
      76: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
      79: ldc           #82                 // int 100000
      81: if_icmpgt     88
      84: iconst_1
      85: goto          89
      88: iconst_0
      89: ifeq          45
      92: aload         4
      94: aload         7
      96: invokeinterface #86,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     101: pop
     102: goto          45
     105: aload         4
     107: checkcast     #88                 // class java/util/List
     110: nop
     111: checkcast     #56                 // class java/lang/Iterable
     114: astore_1
     115: iconst_0
     116: istore_2
     117: aload_1
     118: invokeinterface #67,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     123: astore_3
     124: aload_3
     125: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     130: ifeq          170
     133: aload_3
     134: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     139: astore        4
     141: iload_2
     142: aload         4
     144: checkcast     #50                 // class day07/Directory
     147: astore        5
     149: istore        10
     151: iconst_0
     152: istore        6
     154: aload         5
     156: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
     159: istore        11
     161: iload         10
     163: iload         11
     165: iadd
     166: istore_2
     167: goto          124
     170: iload_2
     171: ireturn

  public static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #38                 // String input
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #48                 // Method parseDirectories:(Ljava/util/List;)Lday07/Directory;
      10: astore_1
      11: aload_1
      12: invokevirtual #54                 // Method day07/Directory.getAllDirectories:()Ljava/util/List;
      15: checkcast     #56                 // class java/lang/Iterable
      18: astore_2
      19: iconst_0
      20: istore_3
      21: aload_2
      22: astore        4
      24: new           #58                 // class java/util/ArrayList
      27: dup
      28: invokespecial #61                 // Method java/util/ArrayList."<init>":()V
      31: checkcast     #63                 // class java/util/Collection
      34: astore        5
      36: iconst_0
      37: istore        6
      39: aload         4
      41: invokeinterface #67,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      46: astore        7
      48: aload         7
      50: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      55: ifeq          116
      58: aload         7
      60: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      65: astore        8
      67: aload         8
      69: checkcast     #50                 // class day07/Directory
      72: astore        9
      74: iconst_0
      75: istore        10
      77: aload         9
      79: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
      82: ldc           #103                // int 30000000
      84: ldc           #104                // int 70000000
      86: aload_1
      87: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
      90: isub
      91: isub
      92: if_icmplt     99
      95: iconst_1
      96: goto          100
      99: iconst_0
     100: ifeq          48
     103: aload         5
     105: aload         8
     107: invokeinterface #86,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     112: pop
     113: goto          48
     116: aload         5
     118: checkcast     #88                 // class java/util/List
     121: nop
     122: checkcast     #56                 // class java/lang/Iterable
     125: astore_2
     126: nop
     127: iconst_0
     128: istore_3
     129: aload_2
     130: invokeinterface #67,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     135: astore        4
     137: aload         4
     139: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     144: ifne          155
     147: new           #106                // class java/util/NoSuchElementException
     150: dup
     151: invokespecial #107                // Method java/util/NoSuchElementException."<init>":()V
     154: athrow
     155: aload         4
     157: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     162: astore        5
     164: aload         4
     166: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     171: ifne          179
     174: aload         5
     176: goto          249
     179: aload         5
     181: checkcast     #50                 // class day07/Directory
     184: astore        6
     186: iconst_0
     187: istore        7
     189: aload         6
     191: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
     194: istore        6
     196: aload         4
     198: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     203: astore        7
     205: aload         7
     207: checkcast     #50                 // class day07/Directory
     210: astore        8
     212: iconst_0
     213: istore        9
     215: aload         8
     217: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
     220: istore        8
     222: iload         6
     224: iload         8
     226: if_icmple     237
     229: aload         7
     231: astore        5
     233: iload         8
     235: istore        6
     237: aload         4
     239: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     244: ifne          196
     247: aload         5
     249: checkcast     #50                 // class day07/Directory
     252: invokevirtual #81                 // Method day07/Directory.getTotalSize:()I
     255: ireturn

  public static final day07.Directory parseDirectories(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #121                // String <this>
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #50                 // class day07/Directory
       9: dup
      10: ldc           #123                // String /
      12: new           #125                // class java/util/LinkedHashSet
      15: dup
      16: invokespecial #126                // Method java/util/LinkedHashSet."<init>":()V
      19: checkcast     #128                // class java/util/Set
      22: new           #130                // class java/util/LinkedHashMap
      25: dup
      26: invokespecial #131                // Method java/util/LinkedHashMap."<init>":()V
      29: checkcast     #133                // class java/util/Map
      32: aconst_null
      33: bipush        8
      35: aconst_null
      36: invokespecial #136                // Method day07/Directory."<init>":(Ljava/lang/String;Ljava/util/Set;Ljava/util/Map;Lday07/Directory;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      39: astore_1
      40: aconst_null
      41: astore_2
      42: aload_1
      43: astore_2
      44: aload_0
      45: checkcast     #56                 // class java/lang/Iterable
      48: astore_3
      49: iconst_0
      50: istore        4
      52: aload_3
      53: invokeinterface #67,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      58: astore        5
      60: aload         5
      62: invokeinterface #73,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      67: ifeq          204
      70: aload         5
      72: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      77: astore        6
      79: aload         6
      81: checkcast     #138                // class java/lang/String
      84: astore        7
      86: iconst_0
      87: istore        8
      89: nop
      90: aload         7
      92: invokestatic  #142                // Method isCd:(Ljava/lang/String;)Z
      95: ifeq          111
      98: aload_2
      99: aload         7
     101: invokestatic  #146                // Method lastArg:(Ljava/lang/String;)Ljava/lang/String;
     104: invokevirtual #150                // Method day07/Directory.changeInto:(Ljava/lang/String;)Lday07/Directory;
     107: astore_2
     108: goto          199
     111: aload         7
     113: invokestatic  #153                // Method isDir:(Ljava/lang/String;)Z
     116: ifeq          170
     119: aload_2
     120: invokevirtual #157                // Method day07/Directory.getDirs:()Ljava/util/Map;
     123: aload         7
     125: invokestatic  #146                // Method lastArg:(Ljava/lang/String;)Ljava/lang/String;
     128: new           #50                 // class day07/Directory
     131: dup
     132: aload         7
     134: invokestatic  #146                // Method lastArg:(Ljava/lang/String;)Ljava/lang/String;
     137: new           #125                // class java/util/LinkedHashSet
     140: dup
     141: invokespecial #126                // Method java/util/LinkedHashSet."<init>":()V
     144: checkcast     #128                // class java/util/Set
     147: new           #130                // class java/util/LinkedHashMap
     150: dup
     151: invokespecial #131                // Method java/util/LinkedHashMap."<init>":()V
     154: checkcast     #133                // class java/util/Map
     157: aload_2
     158: invokespecial #160                // Method day07/Directory."<init>":(Ljava/lang/String;Ljava/util/Set;Ljava/util/Map;Lday07/Directory;)V
     161: invokeinterface #164,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     166: pop
     167: goto          199
     170: aload         7
     172: invokestatic  #167                // Method isFile:(Ljava/lang/String;)Z
     175: ifeq          199
     178: aload_2
     179: invokevirtual #171                // Method day07/Directory.getFiles:()Ljava/util/Set;
     182: aload         7
     184: invokestatic  #174                // Method firstArg:(Ljava/lang/String;)Ljava/lang/String;
     187: invokestatic  #180                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     190: invokestatic  #184                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     193: invokeinterface #185,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
     198: pop
     199: nop
     200: nop
     201: goto          60
     204: nop
     205: aload_1
     206: areturn

  private static final java.lang.String lastArg(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #195                // class java/lang/CharSequence
       4: iconst_1
       5: anewarray     #138                // class java/lang/String
       8: astore_1
       9: aload_1
      10: iconst_0
      11: ldc           #197                // String
      13: aastore
      14: aload_1
      15: iconst_0
      16: iconst_0
      17: bipush        6
      19: aconst_null
      20: invokestatic  #203                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      23: invokestatic  #209                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      26: checkcast     #138                // class java/lang/String
      29: areturn

  private static final java.lang.String firstArg(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #195                // class java/lang/CharSequence
       4: iconst_1
       5: anewarray     #138                // class java/lang/String
       8: astore_1
       9: aload_1
      10: iconst_0
      11: ldc           #197                // String
      13: aastore
      14: aload_1
      15: iconst_0
      16: iconst_0
      17: bipush        6
      19: aconst_null
      20: invokestatic  #203                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      23: invokestatic  #213                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      26: checkcast     #138                // class java/lang/String
      29: areturn

  public static final boolean isCd(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #121                // String <this>
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: ldc           #216                // String $ cd
       9: iconst_0
      10: iconst_2
      11: aconst_null
      12: invokestatic  #220                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
      15: ireturn

  public static final boolean isFile(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #121                // String <this>
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #195                // class java/lang/CharSequence
      10: invokestatic  #224                // Method kotlin/text/StringsKt.first:(Ljava/lang/CharSequence;)C
      13: invokestatic  #230                // Method java/lang/Character.isDigit:(C)Z
      16: ireturn

  public static final boolean isDir(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #121                // String <this>
       3: invokestatic  #44                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: ldc           #233                // String dir
       9: iconst_0
      10: iconst_2
      11: aconst_null
      12: invokestatic  #220                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
      15: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #237                // Method main:()V
       3: return
}


package day09

import Point
import kotlin.math.sign
import readInput

typealias Segment = Point

enum class Direction { R, U, D, L }

val regex = """([RUDL]) (\d+)""".toRegex()

val start = Segment(0, 0)

fun main() {
    val input = readInput("main/day09/Day09")

    println(part1(input))
    println(part2(input))
}

fun part1(input: List<String>): Int {
    return input.toSteps().tailPositions(2).size
}

fun part2(input: List<String>): Int {
    return input.toSteps().tailPositions(10).size
}

private fun List<Direction>.tailPositions(length: Int) =
    tailPositions(Rope(Array(length) { Point(0, 0) }.toList()))

private fun List<Direction>.tailPositions(rope: Rope) = iterator().let { directions ->
    generateSequence(rope) {
        if (directions.hasNext()) it.step(directions.next())
        else null
    }.takeWhile { it != null }.map { it.tail() }.distinct().toList()
}

fun List<String>.toSteps(): List<Direction> {
    val directions = mutableListOf<Direction>()
    forEach {
        regex.matchEntire(it)?.destructured?.let { (direction, steps) ->
            repeat(steps.toInt()) {
                directions.add(Direction.valueOf(direction))
            }
        } ?: error("invalid input")
    }
    return directions
}

data class Rope(val segments: List<Segment> = emptyList()) {
    fun step(direction: Direction): Rope {
        var newRope = Rope().add(head().move(direction))
        segments.drop(1).forEach { segment ->
            val head = newRope.tail()
            newRope =
                if (segment.isAdjacentTo(head)) newRope.add(segment)
                else newRope.add(Segment((head.x - segment.x).sign + segment.x, (head.y - segment.y).sign + segment.y))
        }
        return newRope
    }

    private fun head() = segments.first()
    fun tail(): Segment = segments.last()
    private fun add(segment: Segment) = copy(segments = segments + segment)
}

fun Segment.isAdjacentTo(other: Segment): Boolean {
    return other.x in (x - 1..x + 1) && other.y in (y - 1..y + 1)
}

fun Segment.move(direction: Direction) =
    when (direction) {
        Direction.R -> copy(x = x + 1)
        Direction.U -> copy(y = y + 1)
        Direction.D -> copy(y = y - 1)
        Direction.L -> copy(x = x - 1)
    }

Compiled from "day09.kt"
public final class day09.Day09Kt$WhenMappings {
  public static final int[] $EnumSwitchMapping$0;

  static {};
    Code:
       0: invokestatic  #14                 // Method day09/Direction.values:()[Lday09/Direction;
       3: arraylength
       4: newarray       int
       6: astore_0
       7: nop
       8: aload_0
       9: getstatic     #18                 // Field day09/Direction.R:Lday09/Direction;
      12: invokevirtual #22                 // Method day09/Direction.ordinal:()I
      15: iconst_1
      16: iastore
      17: goto          21
      20: astore_1
      21: nop
      22: aload_0
      23: getstatic     #25                 // Field day09/Direction.U:Lday09/Direction;
      26: invokevirtual #22                 // Method day09/Direction.ordinal:()I
      29: iconst_2
      30: iastore
      31: goto          35
      34: astore_1
      35: nop
      36: aload_0
      37: getstatic     #28                 // Field day09/Direction.D:Lday09/Direction;
      40: invokevirtual #22                 // Method day09/Direction.ordinal:()I
      43: iconst_3
      44: iastore
      45: goto          49
      48: astore_1
      49: nop
      50: aload_0
      51: getstatic     #31                 // Field day09/Direction.L:Lday09/Direction;
      54: invokevirtual #22                 // Method day09/Direction.ordinal:()I
      57: iconst_4
      58: iastore
      59: goto          63
      62: astore_1
      63: aload_0
      64: putstatic     #35                 // Field $EnumSwitchMapping$0:[I
      67: return
    Exception table:
       from    to  target type
           7    17    20   Class java/lang/NoSuchFieldError
          21    31    34   Class java/lang/NoSuchFieldError
          35    45    48   Class java/lang/NoSuchFieldError
          49    59    62   Class java/lang/NoSuchFieldError
}

Compiled from "day09.kt"
public final class day09.Day09Kt {
  private static final kotlin.text.Regex regex;

  private static final Point start;

  public static final kotlin.text.Regex getRegex();
    Code:
       0: getstatic     #11                 // Field regex:Lkotlin/text/Regex;
       3: areturn

  public static final Point getStart();
    Code:
       0: getstatic     #17                 // Field start:LPoint;
       3: areturn

  public static final void main();
    Code:
       0: ldc           #21                 // String main/day09/Day09
       2: invokestatic  #27                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: invokestatic  #31                 // Method part1:(Ljava/util/List;)I
      10: istore_1
      11: getstatic     #37                 // Field java/lang/System.out:Ljava/io/PrintStream;
      14: iload_1
      15: invokevirtual #43                 // Method java/io/PrintStream.println:(I)V
      18: aload_0
      19: invokestatic  #46                 // Method part2:(Ljava/util/List;)I
      22: istore_1
      23: getstatic     #37                 // Field java/lang/System.out:Ljava/io/PrintStream;
      26: iload_1
      27: invokevirtual #43                 // Method java/io/PrintStream.println:(I)V
      30: return

  public static final int part1(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #50                 // String input
       3: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #60                 // Method toSteps:(Ljava/util/List;)Ljava/util/List;
      10: iconst_2
      11: invokestatic  #64                 // Method tailPositions:(Ljava/util/List;I)Ljava/util/List;
      14: invokeinterface #70,  1           // InterfaceMethod java/util/List.size:()I
      19: ireturn

  public static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #50                 // String input
       3: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #60                 // Method toSteps:(Ljava/util/List;)Ljava/util/List;
      10: bipush        10
      12: invokestatic  #64                 // Method tailPositions:(Ljava/util/List;I)Ljava/util/List;
      15: invokeinterface #70,  1           // InterfaceMethod java/util/List.size:()I
      20: ireturn

  private static final java.util.List<Point> tailPositions(java.util.List<? extends day09.Direction>, int);
    Code:
       0: aload_0
       1: iconst_0
       2: istore_2
       3: iload_1
       4: anewarray     #73                 // class Point
       7: astore_3
       8: astore        5
      10: iload_2
      11: iload_1
      12: if_icmpge     37
      15: iload_2
      16: istore        4
      18: aload_3
      19: iload         4
      21: new           #73                 // class Point
      24: dup
      25: iconst_0
      26: iconst_0
      27: invokespecial #77                 // Method Point."<init>":(II)V
      30: aastore
      31: iinc          2, 1
      34: goto          10
      37: aload         5
      39: aload_3
      40: invokestatic  #83                 // Method kotlin/collections/ArraysKt.toList:([Ljava/lang/Object;)Ljava/util/List;
      43: astore        6
      45: new           #85                 // class day09/Rope
      48: dup
      49: aload         6
      51: invokespecial #88                 // Method day09/Rope."<init>":(Ljava/util/List;)V
      54: invokestatic  #91                 // Method tailPositions:(Ljava/util/List;Lday09/Rope;)Ljava/util/List;
      57: areturn

  private static final java.util.List<Point> tailPositions(java.util.List<? extends day09.Direction>, day09.Rope);
    Code:
       0: aload_0
       1: invokeinterface #101,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
       6: astore_2
       7: iconst_0
       8: istore_3
       9: aload_1
      10: aload_2
      11: invokedynamic #121,  0            // InvokeDynamic #0:invoke:(Ljava/util/Iterator;)Lkotlin/jvm/functions/Function1;
      16: invokestatic  #127                // Method kotlin/sequences/SequencesKt.generateSequence:(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      19: invokedynamic #137,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function1;
      24: invokestatic  #141                // Method kotlin/sequences/SequencesKt.takeWhile:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      27: invokedynamic #148,  0            // InvokeDynamic #2:invoke:()Lkotlin/jvm/functions/Function1;
      32: invokestatic  #151                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      35: invokestatic  #155                // Method kotlin/sequences/SequencesKt.distinct:(Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
      38: invokestatic  #158                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
      41: nop
      42: areturn

  public static final java.util.List<day09.Direction> toSteps(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #166                // String <this>
       3: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #168                // class java/util/ArrayList
       9: dup
      10: invokespecial #170                // Method java/util/ArrayList."<init>":()V
      13: checkcast     #66                 // class java/util/List
      16: astore_1
      17: aload_0
      18: checkcast     #172                // class java/lang/Iterable
      21: astore_2
      22: iconst_0
      23: istore_3
      24: aload_2
      25: invokeinterface #173,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      30: astore        4
      32: aload         4
      34: invokeinterface #179,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      39: ifeq          199
      42: aload         4
      44: invokeinterface #183,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      49: astore        5
      51: aload         5
      53: checkcast     #185                // class java/lang/String
      56: astore        6
      58: iconst_0
      59: istore        7
      61: getstatic     #11                 // Field regex:Lkotlin/text/Regex;
      64: aload         6
      66: checkcast     #187                // class java/lang/CharSequence
      69: invokevirtual #193                // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
      72: dup
      73: ifnull        180
      76: invokeinterface #199,  1          // InterfaceMethod kotlin/text/MatchResult.getDestructured:()Lkotlin/text/MatchResult$Destructured;
      81: dup
      82: ifnull        180
      85: astore        8
      87: iconst_0
      88: istore        9
      90: aload         8
      92: invokevirtual #205                // Method kotlin/text/MatchResult$Destructured.getMatch:()Lkotlin/text/MatchResult;
      95: invokeinterface #209,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     100: iconst_1
     101: invokeinterface #213,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     106: checkcast     #185                // class java/lang/String
     109: astore        10
     111: aload         8
     113: invokevirtual #205                // Method kotlin/text/MatchResult$Destructured.getMatch:()Lkotlin/text/MatchResult;
     116: invokeinterface #209,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     121: iconst_2
     122: invokeinterface #213,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     127: checkcast     #185                // class java/lang/String
     130: astore        11
     132: aload         11
     134: invokestatic  #219                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     137: istore        12
     139: iconst_0
     140: istore        13
     142: iload         13
     144: iload         12
     146: if_icmpge     175
     149: iload         13
     151: istore        14
     153: iconst_0
     154: istore        15
     156: aload_1
     157: aload         10
     159: invokestatic  #225                // Method day09/Direction.valueOf:(Ljava/lang/String;)Lday09/Direction;
     162: invokeinterface #229,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     167: pop
     168: nop
     169: iinc          13, 1
     172: goto          142
     175: nop
     176: nop
     177: goto          194
     180: pop
     181: new           #231                // class java/lang/IllegalStateException
     184: dup
     185: ldc           #233                // String invalid input
     187: invokevirtual #237                // Method java/lang/Object.toString:()Ljava/lang/String;
     190: invokespecial #240                // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     193: athrow
     194: nop
     195: nop
     196: goto          32
     199: nop
     200: aload_1
     201: areturn

  public static final boolean isAdjacentTo(Point, Point);
    Code:
       0: aload_0
       1: ldc           #166                // String <this>
       3: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc_w         #257                // String other
      10: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      13: aload_0
      14: invokevirtual #260                // Method Point.getX:()I
      17: iconst_1
      18: isub
      19: istore_2
      20: aload_0
      21: invokevirtual #260                // Method Point.getX:()I
      24: iconst_1
      25: iadd
      26: istore_3
      27: aload_1
      28: invokevirtual #260                // Method Point.getX:()I
      31: istore        4
      33: iload_2
      34: iload         4
      36: if_icmpgt     53
      39: iload         4
      41: iload_3
      42: if_icmpgt     49
      45: iconst_1
      46: goto          54
      49: iconst_0
      50: goto          54
      53: iconst_0
      54: ifeq          105
      57: aload_0
      58: invokevirtual #263                // Method Point.getY:()I
      61: iconst_1
      62: isub
      63: istore_2
      64: aload_0
      65: invokevirtual #263                // Method Point.getY:()I
      68: iconst_1
      69: iadd
      70: istore_3
      71: aload_1
      72: invokevirtual #263                // Method Point.getY:()I
      75: istore        4
      77: iload_2
      78: iload         4
      80: if_icmpgt     97
      83: iload         4
      85: iload_3
      86: if_icmpgt     93
      89: iconst_1
      90: goto          98
      93: iconst_0
      94: goto          98
      97: iconst_0
      98: ifeq          105
     101: iconst_1
     102: goto          106
     105: iconst_0
     106: ireturn

  public static final Point move(Point, day09.Direction);
    Code:
       0: aload_0
       1: ldc           #166                // String <this>
       3: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc_w         #267                // String direction
      10: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      13: aload_1
      14: getstatic     #273                // Field day09/Day09Kt$WhenMappings.$EnumSwitchMapping$0:[I
      17: swap
      18: invokevirtual #276                // Method day09/Direction.ordinal:()I
      21: iaload
      22: tableswitch   { // 1 to 4
                     1: 52
                     2: 68
                     3: 84
                     4: 100
               default: 116
          }
      52: aload_0
      53: aload_0
      54: invokevirtual #260                // Method Point.getX:()I
      57: iconst_1
      58: iadd
      59: iconst_0
      60: iconst_2
      61: aconst_null
      62: invokestatic  #280                // Method Point.copy$default:(LPoint;IIILjava/lang/Object;)LPoint;
      65: goto          124
      68: aload_0
      69: iconst_0
      70: aload_0
      71: invokevirtual #263                // Method Point.getY:()I
      74: iconst_1
      75: iadd
      76: iconst_1
      77: aconst_null
      78: invokestatic  #280                // Method Point.copy$default:(LPoint;IIILjava/lang/Object;)LPoint;
      81: goto          124
      84: aload_0
      85: iconst_0
      86: aload_0
      87: invokevirtual #263                // Method Point.getY:()I
      90: iconst_1
      91: isub
      92: iconst_1
      93: aconst_null
      94: invokestatic  #280                // Method Point.copy$default:(LPoint;IIILjava/lang/Object;)LPoint;
      97: goto          124
     100: aload_0
     101: aload_0
     102: invokevirtual #260                // Method Point.getX:()I
     105: iconst_1
     106: isub
     107: iconst_0
     108: iconst_2
     109: aconst_null
     110: invokestatic  #280                // Method Point.copy$default:(LPoint;IIILjava/lang/Object;)LPoint;
     113: goto          124
     116: new           #282                // class kotlin/NoWhenBranchMatchedException
     119: dup
     120: invokespecial #283                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     123: athrow
     124: areturn

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #288                // Method main:()V
       3: return

  private static final day09.Rope tailPositions$lambda$3$lambda$0(java.util.Iterator, day09.Rope);
    Code:
       0: aload_1
       1: ldc_w         #291                // String it
       4: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokeinterface #179,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      13: ifeq          32
      16: aload_1
      17: aload_0
      18: invokeinterface #183,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      23: checkcast     #221                // class day09/Direction
      26: invokevirtual #295                // Method day09/Rope.step:(Lday09/Direction;)Lday09/Rope;
      29: goto          33
      32: aconst_null
      33: areturn

  private static final boolean tailPositions$lambda$3$lambda$1(day09.Rope);
    Code:
       0: aload_0
       1: ldc_w         #291                // String it
       4: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: iconst_1
       8: ireturn

  private static final Point tailPositions$lambda$3$lambda$2(day09.Rope);
    Code:
       0: aload_0
       1: ldc_w         #291                // String it
       4: invokestatic  #56                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #299                // Method day09/Rope.tail:()LPoint;
      11: areturn

  static {};
    Code:
       0: new           #189                // class kotlin/text/Regex
       3: dup
       4: ldc_w         #302                // String ([RUDL]) (\\d+)
       7: invokespecial #303                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      10: putstatic     #11                 // Field regex:Lkotlin/text/Regex;
      13: new           #73                 // class Point
      16: dup
      17: iconst_0
      18: iconst_0
      19: invokespecial #77                 // Method Point."<init>":(II)V
      22: putstatic     #17                 // Field start:LPoint;
      25: return
}


package day08

import Point
import readInput

typealias Forest = List<Tree>

fun main() {
    val input = readInput("main/day08/Day08")

    val forest = input.flatMapIndexed { y, line ->
        line.mapIndexed { x, height ->
            Tree(x, y, height.digitToInt())
        }
    }

    println(part1(forest))
    println(part2(forest))
}

fun part1(forest: Forest): Int {
    return forest.count {
        it.isVisibleFromLeft(forest) || it.isVisibleFromRight(forest) || it.isVisibleFromTop(forest) || it.isVisibleFromBottom(forest)
    }
}

fun part2(forest: Forest): Int {
    return forest.maxOf {
        it.scenicScore(forest.associateBy { tree -> Point(tree.x, tree.y) })
    }
}

data class Tree(val x: Int, val y: Int, val height: Int) {
    operator fun compareTo(other: Tree) = this.height.compareTo(other.height)

    override fun equals(other: Any?): Boolean {
        return if (other is Tree) x == other.x && y == other.y else false
    }

    override fun hashCode(): Int {
        return x.hashCode() * 31 + y.hashCode()
    }

    fun isVisibleFromLeft(otherTrees: Forest): Boolean = otherTrees.none { it.y == y && it >= this && it.x < this.x }

    fun isVisibleFromRight(otherTrees: Forest): Boolean = otherTrees.none { it.y == y && it >= this && it.x > this.x }

    fun isVisibleFromTop(otherTrees: Forest): Boolean = otherTrees.none { it.x == x && it >= this && it.y < this.y }

    fun isVisibleFromBottom(otherTrees: Forest): Boolean = otherTrees.none { it.x == x && it >= this && it.y > this.y }

    fun scenicScore(treeMap: Map<Point, Tree>): Int {
        return countVisibleTreesLeft(treeMap) * countVisibleTreesDown(treeMap) * countVisibleTreesRight(treeMap) * countVisibleTreesUp(treeMap)
    }

    private fun countVisibleTreesLeft(treeMap: Map<Point, Tree>): Int {
        var result = 0
        var xpos = x - 1
        while (xpos >= 0 && this > treeMap[Point(xpos, y)]!!) {
            result++
            xpos--
        }
        return result + if (xpos < 0) 0 else 1
    }

    private fun countVisibleTreesRight(treeMap: Map<Point, Tree>): Int {
        val maxX = treeMap.maxOf { it.key.x }
        var result = 0
        var xpos = x + 1
        while (xpos <= maxX && this > treeMap[Point(xpos, y)]!!) {
            result++
            xpos++
        }
        return result + if (xpos > maxX) 0 else 1
    }

    private fun countVisibleTreesUp(treeMap: Map<Point, Tree>): Int {
        var result = 0
        var ypos = y - 1
        while (ypos >= 0 && this > treeMap[Point(x, ypos)]!!) {
            result++
            ypos--
        }
        return result + if (ypos < 0) 0 else 1
    }

    private fun countVisibleTreesDown(treeMap: Map<Point, Tree>): Int {
        val maxY = treeMap.maxOf { it.key.y }
        var result = 0
        var ypos = y + 1
        while (ypos <= maxY && this > treeMap[Point(x, ypos)]!!) {
            result++
            ypos++
        }
        return result + if (ypos > maxY) 0 else 1
    }
}

Compiled from "day08.kt"
public final class day08.Day08Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String main/day08/Day08
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: checkcast     #16                 // class java/lang/Iterable
      10: astore_3
      11: new           #18                 // class java/util/ArrayList
      14: dup
      15: invokespecial #21                 // Method java/util/ArrayList."<init>":()V
      18: checkcast     #23                 // class java/util/Collection
      21: astore        4
      23: iconst_0
      24: istore        5
      26: aload_3
      27: invokeinterface #27,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      32: astore        6
      34: aload         6
      36: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      41: ifeq          216
      44: aload         6
      46: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      51: astore        7
      53: iload         5
      55: iinc          5, 1
      58: istore        8
      60: iload         8
      62: ifge          68
      65: invokestatic  #42                 // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      68: iload         8
      70: aload         7
      72: checkcast     #44                 // class java/lang/String
      75: astore        9
      77: istore        10
      79: iconst_0
      80: istore        11
      82: aload         9
      84: checkcast     #46                 // class java/lang/CharSequence
      87: astore        12
      89: iconst_0
      90: istore        13
      92: aload         12
      94: astore        14
      96: new           #18                 // class java/util/ArrayList
      99: dup
     100: aload         12
     102: invokeinterface #50,  1           // InterfaceMethod java/lang/CharSequence.length:()I
     107: invokespecial #53                 // Method java/util/ArrayList."<init>":(I)V
     110: checkcast     #23                 // class java/util/Collection
     113: astore        15
     115: iconst_0
     116: istore        16
     118: iconst_0
     119: istore        17
     121: iconst_0
     122: istore        18
     124: iload         18
     126: aload         14
     128: invokeinterface #50,  1           // InterfaceMethod java/lang/CharSequence.length:()I
     133: if_icmpge     196
     136: aload         14
     138: iload         18
     140: invokeinterface #57,  2           // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     145: istore        19
     147: aload         15
     149: iload         17
     151: iinc          17, 1
     154: iload         19
     156: istore        20
     158: istore        21
     160: astore        22
     162: iconst_0
     163: istore        23
     165: new           #59                 // class day08/Tree
     168: dup
     169: iload         21
     171: iload         10
     173: iload         20
     175: invokestatic  #65                 // Method kotlin/text/CharsKt.digitToInt:(C)I
     178: invokespecial #68                 // Method day08/Tree."<init>":(III)V
     181: aload         22
     183: swap
     184: invokeinterface #72,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     189: pop
     190: iinc          18, 1
     193: goto          124
     196: aload         15
     198: checkcast     #74                 // class java/util/List
     201: nop
     202: checkcast     #16                 // class java/lang/Iterable
     205: nop
     206: aload         4
     208: swap
     209: invokestatic  #78                 // Method kotlin/collections/CollectionsKt.addAll:(Ljava/util/Collection;Ljava/lang/Iterable;)Z
     212: pop
     213: goto          34
     216: aload         4
     218: checkcast     #74                 // class java/util/List
     221: astore_1
     222: aload_1
     223: invokestatic  #82                 // Method part1:(Ljava/util/List;)I
     226: istore_2
     227: getstatic     #88                 // Field java/lang/System.out:Ljava/io/PrintStream;
     230: iload_2
     231: invokevirtual #93                 // Method java/io/PrintStream.println:(I)V
     234: aload_1
     235: invokestatic  #96                 // Method part2:(Ljava/util/List;)I
     238: istore_2
     239: getstatic     #88                 // Field java/lang/System.out:Ljava/io/PrintStream;
     242: iload_2
     243: invokevirtual #93                 // Method java/io/PrintStream.println:(I)V
     246: return

  public static final int part1(java.util.List<day08.Tree>);
    Code:
       0: aload_0
       1: ldc           #120                // String forest
       3: invokestatic  #126                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #16                 // class java/lang/Iterable
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: instanceof    #23                 // class java/util/Collection
      17: ifeq          36
      20: aload_1
      21: checkcast     #23                 // class java/util/Collection
      24: invokeinterface #129,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      29: ifeq          36
      32: iconst_0
      33: goto          133
      36: iconst_0
      37: istore_3
      38: aload_1
      39: invokeinterface #27,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      44: astore        4
      46: aload         4
      48: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      53: ifeq          132
      56: aload         4
      58: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      63: astore        5
      65: aload         5
      67: checkcast     #59                 // class day08/Tree
      70: astore        6
      72: iconst_0
      73: istore        7
      75: aload         6
      77: aload_0
      78: invokevirtual #133                // Method day08/Tree.isVisibleFromLeft:(Ljava/util/List;)Z
      81: ifne          111
      84: aload         6
      86: aload_0
      87: invokevirtual #136                // Method day08/Tree.isVisibleFromRight:(Ljava/util/List;)Z
      90: ifne          111
      93: aload         6
      95: aload_0
      96: invokevirtual #139                // Method day08/Tree.isVisibleFromTop:(Ljava/util/List;)Z
      99: ifne          111
     102: aload         6
     104: aload_0
     105: invokevirtual #142                // Method day08/Tree.isVisibleFromBottom:(Ljava/util/List;)Z
     108: ifeq          115
     111: iconst_1
     112: goto          116
     115: iconst_0
     116: ifeq          46
     119: iinc          3, 1
     122: iload_3
     123: ifge          46
     126: invokestatic  #145                // Method kotlin/collections/CollectionsKt.throwCountOverflow:()V
     129: goto          46
     132: iload_3
     133: ireturn

  public static final int part2(java.util.List<day08.Tree>);
    Code:
       0: aload_0
       1: ldc           #120                // String forest
       3: invokestatic  #126                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #16                 // class java/lang/Iterable
      10: invokeinterface #27,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      15: astore_1
      16: aload_1
      17: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      22: ifne          33
      25: new           #156                // class java/util/NoSuchElementException
      28: dup
      29: invokespecial #157                // Method java/util/NoSuchElementException."<init>":()V
      32: athrow
      33: aload_1
      34: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      39: checkcast     #59                 // class day08/Tree
      42: astore_2
      43: iconst_0
      44: istore_3
      45: aload_2
      46: aload_0
      47: checkcast     #16                 // class java/lang/Iterable
      50: astore        4
      52: astore        5
      54: iconst_0
      55: istore        6
      57: aload         4
      59: bipush        10
      61: invokestatic  #161                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      64: invokestatic  #167                // Method kotlin/collections/MapsKt.mapCapacity:(I)I
      67: bipush        16
      69: invokestatic  #173                // Method kotlin/ranges/RangesKt.coerceAtLeast:(II)I
      72: istore        7
      74: aload         4
      76: astore        8
      78: new           #175                // class java/util/LinkedHashMap
      81: dup
      82: iload         7
      84: invokespecial #176                // Method java/util/LinkedHashMap."<init>":(I)V
      87: checkcast     #178                // class java/util/Map
      90: astore        9
      92: iconst_0
      93: istore        10
      95: aload         8
      97: invokeinterface #27,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     102: astore        11
     104: aload         11
     106: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     111: ifeq          168
     114: aload         11
     116: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     121: astore        12
     123: aload         9
     125: aload         12
     127: checkcast     #59                 // class day08/Tree
     130: astore        13
     132: astore        14
     134: iconst_0
     135: istore        15
     137: new           #180                // class Point
     140: dup
     141: aload         13
     143: invokevirtual #183                // Method day08/Tree.getX:()I
     146: aload         13
     148: invokevirtual #186                // Method day08/Tree.getY:()I
     151: invokespecial #189                // Method Point."<init>":(II)V
     154: aload         14
     156: swap
     157: aload         12
     159: invokeinterface #193,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     164: pop
     165: goto          104
     168: aload         9
     170: nop
     171: aload         5
     173: swap
     174: invokevirtual #197                // Method day08/Tree.scenicScore:(Ljava/util/Map;)I
     177: istore_2
     178: aload_1
     179: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     184: ifeq          343
     187: aload_1
     188: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     193: checkcast     #59                 // class day08/Tree
     196: astore_3
     197: iconst_0
     198: istore        4
     200: aload_3
     201: aload_0
     202: checkcast     #16                 // class java/lang/Iterable
     205: astore        5
     207: astore        6
     209: iconst_0
     210: istore        7
     212: aload         5
     214: bipush        10
     216: invokestatic  #161                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     219: invokestatic  #167                // Method kotlin/collections/MapsKt.mapCapacity:(I)I
     222: bipush        16
     224: invokestatic  #173                // Method kotlin/ranges/RangesKt.coerceAtLeast:(II)I
     227: istore        8
     229: aload         5
     231: astore        9
     233: new           #175                // class java/util/LinkedHashMap
     236: dup
     237: iload         8
     239: invokespecial #176                // Method java/util/LinkedHashMap."<init>":(I)V
     242: checkcast     #178                // class java/util/Map
     245: astore        10
     247: iconst_0
     248: istore        11
     250: aload         9
     252: invokeinterface #27,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     257: astore        12
     259: aload         12
     261: invokeinterface #33,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     266: ifeq          323
     269: aload         12
     271: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     276: astore        13
     278: aload         10
     280: aload         13
     282: checkcast     #59                 // class day08/Tree
     285: astore        14
     287: astore        15
     289: iconst_0
     290: istore        16
     292: new           #180                // class Point
     295: dup
     296: aload         14
     298: invokevirtual #183                // Method day08/Tree.getX:()I
     301: aload         14
     303: invokevirtual #186                // Method day08/Tree.getY:()I
     306: invokespecial #189                // Method Point."<init>":(II)V
     309: aload         15
     311: swap
     312: aload         13
     314: invokeinterface #193,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     319: pop
     320: goto          259
     323: aload         10
     325: nop
     326: aload         6
     328: swap
     329: invokevirtual #197                // Method day08/Tree.scenicScore:(Ljava/util/Map;)I
     332: istore_3
     333: iload_2
     334: iload_3
     335: if_icmpge     178
     338: iload_3
     339: istore_2
     340: goto          178
     343: iload_2
     344: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #210                // Method main:()V
       3: return
}