import kotlin.math.max
import kotlin.math.min

fun main() {
    val testInput = readInput("Day23_test")
    check(part1(testInput) == 110)
    check(part2(testInput) == 20)

    val input = readInput("Day23")
    println(part1(input))
    println(part2(input))
}

private val DIRECTIONS = listOf(
    //N, NE, NW
    listOf(
        intArrayOf(-1, 0),
        intArrayOf(-1, 1),
        intArrayOf(-1, -1)
    ),
    //S, SE, SW
    listOf(
        intArrayOf(1, 0),
        intArrayOf(1, 1),
        intArrayOf(1, -1)
    ),
    //W, NW, SW
    listOf(
        intArrayOf(0, -1),
        intArrayOf(-1, -1),
        intArrayOf(1, -1)
    ),
    //E, NE, SE
    listOf(
        intArrayOf(0, 1),
        intArrayOf(-1, 1),
        intArrayOf(1, 1)
    ),
)

private val ALL_ADJACENT = listOf(
    intArrayOf(-1, -1),
    intArrayOf(-1, 0),
    intArrayOf(-1, 1),
    intArrayOf(0, 1),
    intArrayOf(1, 1),
    intArrayOf(1, 0),
    intArrayOf(1, -1),
    intArrayOf(0, -1),
)

private fun part1(input: List<String>): Int {
    var elves = input.toElves()

    val moveMap = mutableMapOf<IJ, IJ>()
    val counts = mutableMapOf<IJ, Int>()
    repeat(10) { iterationNumber ->
        moveMap.clear()
        counts.clear()

        elves.calculateMoves(iterationNumber, moveMap, counts)
        elves = elves.applyMoves(moveMap, counts)
    }

    var iFrom = elves.first().i
    var jFrom = elves.first().j
    var iTo = iFrom
    var jTo = jFrom
    elves.forEach {
        iFrom = min(iFrom, it.i)
        jFrom = min(jFrom, it.j)
        iTo = max(iTo, it.i)
        jTo = max(jTo, it.j)
    }

    var count = 0
    for (i in iFrom..iTo) {
        for (j in jFrom..jTo) {
            if (IJ(i, j) !in elves) {
                ++count
            }
        }
    }

    return count
}

private fun part2(input: List<String>): Int {
    var elves = input.toElves()

    var iterationNumber = 0

    val moveMap = mutableMapOf<IJ, IJ>()
    val counts = mutableMapOf<IJ, Int>()
    while (true) {
        moveMap.clear()
        counts.clear()

        elves.calculateMoves(iterationNumber, moveMap, counts)

        if (moveMap.isEmpty()) {
            break
        }

        elves = elves.applyMoves(moveMap, counts)

        ++iterationNumber
    }

    return iterationNumber + 1
}

private fun List<String>.toElves(): Set<IJ> {
    return this.flatMapIndexed { i, row ->
        row.mapIndexedNotNull { j, ch ->
            if (ch == '#') {
                IJ(i, j)
            } else {
                null
            }
        }
    }.toSet()
}

private fun Set<IJ>.calculateMoves(
    iterationNumber: Int,
    moveMap: MutableMap<IJ, IJ>,
    counts: MutableMap<IJ, Int>
) {
    this.forEach { elf ->
        val shouldMove = ALL_ADJACENT.any { delta ->
            IJ(elf.i + delta[0], elf.j + delta[1]) in this
        }

        if (shouldMove) {
            val moveDirection = DIRECTIONS.indices.firstNotNullOfOrNull { i ->
                DIRECTIONS[(i + iterationNumber) % DIRECTIONS.size].takeIf { dir ->
                    dir.all { delta -> IJ(elf.i + delta[0], elf.j + delta[1]) !in this }
                }
            }

            if (moveDirection != null) {
                val newLocation = IJ(elf.i + moveDirection[0][0], elf.j + moveDirection[0][1])
                moveMap[elf] = newLocation
                counts[newLocation] = counts.getOrDefault(newLocation, 0) + 1
            }
        }
    }
}

private fun Set<IJ>.applyMoves(
    moveMap: MutableMap<IJ, IJ>,
    counts: MutableMap<IJ, Int>
): Set<IJ> {
    return this.map { elf ->
        moveMap[elf]?.takeIf { counts[it] == 1 } ?: elf
    }.toSet()
}

Compiled from "Day23.kt"
public final class Day23Kt {
  private static final java.util.List<java.util.List<int[]>> DIRECTIONS;

  private static final java.util.List<int[]> ALL_ADJACENT;

  public static final void main();
    Code:
       0: ldc           #8                  // String Day23_test
       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: bipush        110
      12: if_icmpne     19
      15: iconst_1
      16: goto          20
      19: iconst_0
      20: ifne          33
      23: new           #20                 // class java/lang/IllegalStateException
      26: dup
      27: ldc           #22                 // String Check failed.
      29: invokespecial #26                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      32: athrow
      33: aload_0
      34: invokestatic  #29                 // Method part2:(Ljava/util/List;)I
      37: bipush        20
      39: if_icmpne     46
      42: iconst_1
      43: goto          47
      46: iconst_0
      47: ifne          60
      50: new           #20                 // class java/lang/IllegalStateException
      53: dup
      54: ldc           #22                 // String Check failed.
      56: invokespecial #26                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      59: athrow
      60: ldc           #31                 // String Day23
      62: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      65: astore_1
      66: aload_1
      67: invokestatic  #18                 // Method part1:(Ljava/util/List;)I
      70: istore_2
      71: getstatic     #37                 // Field java/lang/System.out:Ljava/io/PrintStream;
      74: iload_2
      75: invokevirtual #43                 // Method java/io/PrintStream.println:(I)V
      78: aload_1
      79: invokestatic  #29                 // Method part2:(Ljava/util/List;)I
      82: istore_2
      83: getstatic     #37                 // Field java/lang/System.out:Ljava/io/PrintStream;
      86: iload_2
      87: invokevirtual #43                 // Method java/io/PrintStream.println:(I)V
      90: return

  private static final int part1(java.util.List<java.lang.String>);
    Code:
       0: aconst_null
       1: astore_1
       2: aload_0
       3: invokestatic  #53                 // Method toElves:(Ljava/util/List;)Ljava/util/Set;
       6: astore_1
       7: new           #55                 // class java/util/LinkedHashMap
      10: dup
      11: invokespecial #57                 // Method java/util/LinkedHashMap."<init>":()V
      14: checkcast     #59                 // class java/util/Map
      17: astore_2
      18: new           #55                 // class java/util/LinkedHashMap
      21: dup
      22: invokespecial #57                 // Method java/util/LinkedHashMap."<init>":()V
      25: checkcast     #59                 // class java/util/Map
      28: astore_3
      29: bipush        10
      31: istore        4
      33: iconst_0
      34: istore        5
      36: iload         5
      38: iload         4
      40: if_icmpge     84
      43: iload         5
      45: istore        6
      47: iconst_0
      48: istore        7
      50: aload_2
      51: invokeinterface #62,  1           // InterfaceMethod java/util/Map.clear:()V
      56: aload_3
      57: invokeinterface #62,  1           // InterfaceMethod java/util/Map.clear:()V
      62: aload_1
      63: iload         6
      65: aload_2
      66: aload_3
      67: invokestatic  #66                 // Method calculateMoves:(Ljava/util/Set;ILjava/util/Map;Ljava/util/Map;)V
      70: aload_1
      71: aload_2
      72: aload_3
      73: invokestatic  #70                 // Method applyMoves:(Ljava/util/Set;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Set;
      76: astore_1
      77: nop
      78: iinc          5, 1
      81: goto          36
      84: iconst_0
      85: istore        4
      87: aload_1
      88: checkcast     #72                 // class java/lang/Iterable
      91: invokestatic  #78                 // Method kotlin/collections/CollectionsKt.first:(Ljava/lang/Iterable;)Ljava/lang/Object;
      94: checkcast     #80                 // class IJ
      97: invokevirtual #84                 // Method IJ.getI:()I
     100: istore        4
     102: iconst_0
     103: istore        5
     105: aload_1
     106: checkcast     #72                 // class java/lang/Iterable
     109: invokestatic  #78                 // Method kotlin/collections/CollectionsKt.first:(Ljava/lang/Iterable;)Ljava/lang/Object;
     112: checkcast     #80                 // class IJ
     115: invokevirtual #87                 // Method IJ.getJ:()I
     118: istore        5
     120: iconst_0
     121: istore        6
     123: iload         4
     125: istore        6
     127: iconst_0
     128: istore        7
     130: iload         5
     132: istore        7
     134: aload_1
     135: checkcast     #72                 // class java/lang/Iterable
     138: astore        8
     140: iconst_0
     141: istore        9
     143: aload         8
     145: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     150: astore        10
     152: aload         10
     154: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     159: ifeq          234
     162: aload         10
     164: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     169: astore        11
     171: aload         11
     173: checkcast     #80                 // class IJ
     176: astore        12
     178: iconst_0
     179: istore        13
     181: iload         4
     183: aload         12
     185: invokevirtual #84                 // Method IJ.getI:()I
     188: invokestatic  #107                // Method java/lang/Math.min:(II)I
     191: istore        4
     193: iload         5
     195: aload         12
     197: invokevirtual #87                 // Method IJ.getJ:()I
     200: invokestatic  #107                // Method java/lang/Math.min:(II)I
     203: istore        5
     205: iload         6
     207: aload         12
     209: invokevirtual #84                 // Method IJ.getI:()I
     212: invokestatic  #110                // Method java/lang/Math.max:(II)I
     215: istore        6
     217: iload         7
     219: aload         12
     221: invokevirtual #87                 // Method IJ.getJ:()I
     224: invokestatic  #110                // Method java/lang/Math.max:(II)I
     227: istore        7
     229: nop
     230: nop
     231: goto          152
     234: nop
     235: iconst_0
     236: istore        8
     238: iload         4
     240: istore        9
     242: iload         6
     244: istore        10
     246: iload         9
     248: iload         10
     250: if_icmpgt     317
     253: iload         5
     255: istore        11
     257: iload         7
     259: istore        12
     261: iload         11
     263: iload         12
     265: if_icmpgt     304
     268: aload_1
     269: new           #80                 // class IJ
     272: dup
     273: iload         9
     275: iload         11
     277: invokespecial #113                // Method IJ."<init>":(II)V
     280: invokeinterface #119,  2          // InterfaceMethod java/util/Set.contains:(Ljava/lang/Object;)Z
     285: ifne          291
     288: iinc          8, 1
     291: iload         11
     293: iload         12
     295: if_icmpeq     304
     298: iinc          11, 1
     301: goto          268
     304: iload         9
     306: iload         10
     308: if_icmpeq     317
     311: iinc          9, 1
     314: goto          253
     317: iload         8
     319: ireturn

  private static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: invokestatic  #53                 // Method toElves:(Ljava/util/List;)Ljava/util/Set;
       4: astore_1
       5: iconst_0
       6: istore_2
       7: new           #55                 // class java/util/LinkedHashMap
      10: dup
      11: invokespecial #57                 // Method java/util/LinkedHashMap."<init>":()V
      14: checkcast     #59                 // class java/util/Map
      17: astore_3
      18: new           #55                 // class java/util/LinkedHashMap
      21: dup
      22: invokespecial #57                 // Method java/util/LinkedHashMap."<init>":()V
      25: checkcast     #59                 // class java/util/Map
      28: astore        4
      30: nop
      31: aload_3
      32: invokeinterface #62,  1           // InterfaceMethod java/util/Map.clear:()V
      37: aload         4
      39: invokeinterface #62,  1           // InterfaceMethod java/util/Map.clear:()V
      44: aload_1
      45: iload_2
      46: aload_3
      47: aload         4
      49: invokestatic  #66                 // Method calculateMoves:(Ljava/util/Set;ILjava/util/Map;Ljava/util/Map;)V
      52: aload_3
      53: invokeinterface #144,  1          // InterfaceMethod java/util/Map.isEmpty:()Z
      58: ifeq          64
      61: goto          78
      64: aload_1
      65: aload_3
      66: aload         4
      68: invokestatic  #70                 // Method applyMoves:(Ljava/util/Set;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Set;
      71: astore_1
      72: iinc          2, 1
      75: goto          30
      78: iload_2
      79: iconst_1
      80: iadd
      81: ireturn

  private static final java.util.Set<IJ> toElves(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: checkcast     #72                 // class java/lang/Iterable
       4: astore_1
       5: new           #148                // class java/util/ArrayList
       8: dup
       9: invokespecial #149                // Method java/util/ArrayList."<init>":()V
      12: checkcast     #151                // class java/util/Collection
      15: astore_2
      16: iconst_0
      17: istore_3
      18: aload_1
      19: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      24: astore        4
      26: aload         4
      28: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      33: ifeq          236
      36: aload         4
      38: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      43: astore        5
      45: iload_3
      46: iinc          3, 1
      49: istore        6
      51: iload         6
      53: ifge          59
      56: invokestatic  #154                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      59: iload         6
      61: aload         5
      63: checkcast     #156                // class java/lang/String
      66: astore        7
      68: istore        8
      70: iconst_0
      71: istore        9
      73: aload         7
      75: checkcast     #158                // class java/lang/CharSequence
      78: astore        10
      80: iconst_0
      81: istore        11
      83: aload         10
      85: astore        12
      87: new           #148                // class java/util/ArrayList
      90: dup
      91: invokespecial #149                // Method java/util/ArrayList."<init>":()V
      94: checkcast     #151                // class java/util/Collection
      97: astore        13
      99: iconst_0
     100: istore        14
     102: aload         12
     104: astore        15
     106: iconst_0
     107: istore        16
     109: iconst_0
     110: istore        17
     112: iconst_0
     113: istore        18
     115: iload         18
     117: aload         15
     119: invokeinterface #161,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     124: if_icmpge     216
     127: aload         15
     129: iload         18
     131: invokeinterface #165,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     136: istore        19
     138: iload         17
     140: iinc          17, 1
     143: iload         19
     145: istore        20
     147: istore        21
     149: iconst_0
     150: istore        22
     152: iload         21
     154: iload         20
     156: istore        23
     158: istore        24
     160: iconst_0
     161: istore        25
     163: iload         23
     165: bipush        35
     167: if_icmpne     184
     170: new           #80                 // class IJ
     173: dup
     174: iload         8
     176: iload         24
     178: invokespecial #113                // Method IJ."<init>":(II)V
     181: goto          185
     184: aconst_null
     185: nop
     186: dup
     187: ifnull        208
     190: astore        26
     192: iconst_0
     193: istore        27
     195: aload         13
     197: aload         26
     199: invokeinterface #168,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     204: pop
     205: goto          209
     208: pop
     209: nop
     210: iinc          18, 1
     213: goto          115
     216: nop
     217: aload         13
     219: checkcast     #48                 // class java/util/List
     222: nop
     223: checkcast     #72                 // class java/lang/Iterable
     226: nop
     227: aload_2
     228: swap
     229: invokestatic  #172                // Method kotlin/collections/CollectionsKt.addAll:(Ljava/util/Collection;Ljava/lang/Iterable;)Z
     232: pop
     233: goto          26
     236: aload_2
     237: checkcast     #48                 // class java/util/List
     240: checkcast     #72                 // class java/lang/Iterable
     243: invokestatic  #176                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     246: areturn

  private static final void calculateMoves(java.util.Set<IJ>, int, java.util.Map<IJ, IJ>, java.util.Map<IJ, java.lang.Integer>);
    Code:
       0: aload_0
       1: checkcast     #72                 // class java/lang/Iterable
       4: astore        4
       6: iconst_0
       7: istore        5
       9: aload         4
      11: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      16: astore        6
      18: aload         6
      20: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      25: ifeq          495
      28: aload         6
      30: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      35: astore        7
      37: aload         7
      39: checkcast     #80                 // class IJ
      42: astore        8
      44: iconst_0
      45: istore        9
      47: getstatic     #203                // Field ALL_ADJACENT:Ljava/util/List;
      50: checkcast     #72                 // class java/lang/Iterable
      53: astore        10
      55: iconst_0
      56: istore        11
      58: aload         10
      60: instanceof    #151                // class java/util/Collection
      63: ifeq          83
      66: aload         10
      68: checkcast     #151                // class java/util/Collection
      71: invokeinterface #204,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      76: ifeq          83
      79: iconst_0
      80: goto          162
      83: aload         10
      85: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      90: astore        12
      92: aload         12
      94: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      99: ifeq          161
     102: aload         12
     104: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     109: astore        13
     111: aload         13
     113: checkcast     #206                // class "[I"
     116: astore        14
     118: iconst_0
     119: istore        15
     121: aload_0
     122: new           #80                 // class IJ
     125: dup
     126: aload         8
     128: invokevirtual #84                 // Method IJ.getI:()I
     131: aload         14
     133: iconst_0
     134: iaload
     135: iadd
     136: aload         8
     138: invokevirtual #87                 // Method IJ.getJ:()I
     141: aload         14
     143: iconst_1
     144: iaload
     145: iadd
     146: invokespecial #113                // Method IJ."<init>":(II)V
     149: invokeinterface #119,  2          // InterfaceMethod java/util/Set.contains:(Ljava/lang/Object;)Z
     154: ifeq          92
     157: iconst_1
     158: goto          162
     161: iconst_0
     162: istore        16
     164: iload         16
     166: ifeq          490
     169: getstatic     #209                // Field DIRECTIONS:Ljava/util/List;
     172: checkcast     #151                // class java/util/Collection
     175: invokestatic  #213                // Method kotlin/collections/CollectionsKt.getIndices:(Ljava/util/Collection;)Lkotlin/ranges/IntRange;
     178: checkcast     #72                 // class java/lang/Iterable
     181: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     186: astore        12
     188: aload         12
     190: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     195: ifeq          392
     198: aload         12
     200: checkcast     #215                // class kotlin/collections/IntIterator
     203: invokevirtual #218                // Method kotlin/collections/IntIterator.nextInt:()I
     206: istore        13
     208: iconst_0
     209: istore        14
     211: getstatic     #209                // Field DIRECTIONS:Ljava/util/List;
     214: iload         13
     216: iload_1
     217: iadd
     218: getstatic     #209                // Field DIRECTIONS:Ljava/util/List;
     221: invokeinterface #221,  1          // InterfaceMethod java/util/List.size:()I
     226: irem
     227: invokeinterface #225,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     232: astore        15
     234: aload         15
     236: checkcast     #48                 // class java/util/List
     239: astore        17
     241: iconst_0
     242: istore        18
     244: aload         17
     246: checkcast     #72                 // class java/lang/Iterable
     249: astore        19
     251: iconst_0
     252: istore        20
     254: aload         19
     256: instanceof    #151                // class java/util/Collection
     259: ifeq          279
     262: aload         19
     264: checkcast     #151                // class java/util/Collection
     267: invokeinterface #204,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
     272: ifeq          279
     275: iconst_1
     276: goto          366
     279: aload         19
     281: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     286: astore        21
     288: aload         21
     290: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     295: ifeq          365
     298: aload         21
     300: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     305: astore        22
     307: aload         22
     309: checkcast     #206                // class "[I"
     312: astore        23
     314: iconst_0
     315: istore        24
     317: aload_0
     318: new           #80                 // class IJ
     321: dup
     322: aload         8
     324: invokevirtual #84                 // Method IJ.getI:()I
     327: aload         23
     329: iconst_0
     330: iaload
     331: iadd
     332: aload         8
     334: invokevirtual #87                 // Method IJ.getJ:()I
     337: aload         23
     339: iconst_1
     340: iaload
     341: iadd
     342: invokespecial #113                // Method IJ."<init>":(II)V
     345: invokeinterface #119,  2          // InterfaceMethod java/util/Set.contains:(Ljava/lang/Object;)Z
     350: ifne          357
     353: iconst_1
     354: goto          358
     357: iconst_0
     358: ifne          288
     361: iconst_0
     362: goto          366
     365: iconst_1
     366: nop
     367: ifeq          375
     370: aload         15
     372: goto          376
     375: aconst_null
     376: checkcast     #48                 // class java/util/List
     379: nop
     380: astore        13
     382: aload         13
     384: ifnull        188
     387: aload         13
     389: goto          393
     392: aconst_null
     393: astore        10
     395: aload         10
     397: ifnull        490
     400: new           #80                 // class IJ
     403: dup
     404: aload         8
     406: invokevirtual #84                 // Method IJ.getI:()I
     409: aload         10
     411: iconst_0
     412: invokeinterface #225,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     417: checkcast     #206                // class "[I"
     420: iconst_0
     421: iaload
     422: iadd
     423: aload         8
     425: invokevirtual #87                 // Method IJ.getJ:()I
     428: aload         10
     430: iconst_0
     431: invokeinterface #225,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     436: checkcast     #206                // class "[I"
     439: iconst_1
     440: iaload
     441: iadd
     442: invokespecial #113                // Method IJ."<init>":(II)V
     445: astore        11
     447: aload_2
     448: aload         8
     450: aload         11
     452: invokeinterface #229,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     457: pop
     458: aload_3
     459: aload         11
     461: aload_3
     462: aload         11
     464: iconst_0
     465: invokestatic  #235                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     468: invokeinterface #238,  3          // InterfaceMethod java/util/Map.getOrDefault:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     473: checkcast     #240                // class java/lang/Number
     476: invokevirtual #243                // Method java/lang/Number.intValue:()I
     479: iconst_1
     480: iadd
     481: invokestatic  #235                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     484: invokeinterface #229,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     489: pop
     490: nop
     491: nop
     492: goto          18
     495: nop
     496: return

  private static final java.util.Set<IJ> applyMoves(java.util.Set<IJ>, java.util.Map<IJ, IJ>, java.util.Map<IJ, java.lang.Integer>);
    Code:
       0: aload_0
       1: checkcast     #72                 // class java/lang/Iterable
       4: astore_3
       5: iconst_0
       6: istore        4
       8: aload_3
       9: astore        5
      11: new           #148                // class java/util/ArrayList
      14: dup
      15: aload_3
      16: bipush        10
      18: invokestatic  #265                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      21: invokespecial #267                // Method java/util/ArrayList."<init>":(I)V
      24: checkcast     #151                // class java/util/Collection
      27: astore        6
      29: iconst_0
      30: istore        7
      32: aload         5
      34: invokeinterface #91,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      39: astore        8
      41: aload         8
      43: invokeinterface #97,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      48: ifeq          161
      51: aload         8
      53: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      58: astore        9
      60: aload         6
      62: aload         9
      64: checkcast     #80                 // class IJ
      67: astore        10
      69: astore        16
      71: iconst_0
      72: istore        11
      74: aload_1
      75: aload         10
      77: invokeinterface #270,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      82: checkcast     #80                 // class IJ
      85: dup
      86: ifnull        146
      89: astore        12
      91: aload         12
      93: astore        13
      95: iconst_0
      96: istore        14
      98: aload_2
      99: aload         13
     101: invokeinterface #270,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     106: checkcast     #231                // class java/lang/Integer
     109: iconst_1
     110: istore        15
     112: dup
     113: ifnonnull     120
     116: pop
     117: goto          132
     120: invokevirtual #271                // Method java/lang/Integer.intValue:()I
     123: iload         15
     125: if_icmpne     132
     128: iconst_1
     129: goto          133
     132: iconst_0
     133: ifeq          141
     136: aload         12
     138: goto          142
     141: aconst_null
     142: dup
     143: ifnonnull     149
     146: pop
     147: aload         10
     149: aload         16
     151: swap
     152: invokeinterface #168,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     157: pop
     158: goto          41
     161: aload         6
     163: checkcast     #48                 // class java/util/List
     166: nop
     167: checkcast     #72                 // class java/lang/Iterable
     170: invokestatic  #176                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     173: areturn

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

  static {};
    Code:
       0: iconst_4
       1: anewarray     #48                 // class java/util/List
       4: astore_0
       5: aload_0
       6: iconst_0
       7: iconst_3
       8: anewarray     #206                // class "[I"
      11: astore_1
      12: aload_1
      13: iconst_0
      14: iconst_2
      15: newarray       int
      17: astore_2
      18: aload_2
      19: iconst_0
      20: iconst_m1
      21: iastore
      22: aload_2
      23: iconst_1
      24: iconst_0
      25: iastore
      26: aload_2
      27: aastore
      28: aload_1
      29: iconst_1
      30: iconst_2
      31: newarray       int
      33: astore_2
      34: aload_2
      35: iconst_0
      36: iconst_m1
      37: iastore
      38: aload_2
      39: iconst_1
      40: iconst_1
      41: iastore
      42: aload_2
      43: aastore
      44: aload_1
      45: iconst_2
      46: iconst_2
      47: newarray       int
      49: astore_2
      50: aload_2
      51: iconst_0
      52: iconst_m1
      53: iastore
      54: aload_2
      55: iconst_1
      56: iconst_m1
      57: iastore
      58: aload_2
      59: aastore
      60: aload_1
      61: checkcast     #287                // class "[Ljava/lang/Object;"
      64: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
      67: aastore
      68: aload_0
      69: iconst_1
      70: iconst_3
      71: anewarray     #206                // class "[I"
      74: astore_1
      75: aload_1
      76: iconst_0
      77: iconst_2
      78: newarray       int
      80: astore_2
      81: aload_2
      82: iconst_0
      83: iconst_1
      84: iastore
      85: aload_2
      86: iconst_1
      87: iconst_0
      88: iastore
      89: aload_2
      90: aastore
      91: aload_1
      92: iconst_1
      93: iconst_2
      94: newarray       int
      96: astore_2
      97: aload_2
      98: iconst_0
      99: iconst_1
     100: iastore
     101: aload_2
     102: iconst_1
     103: iconst_1
     104: iastore
     105: aload_2
     106: aastore
     107: aload_1
     108: iconst_2
     109: iconst_2
     110: newarray       int
     112: astore_2
     113: aload_2
     114: iconst_0
     115: iconst_1
     116: iastore
     117: aload_2
     118: iconst_1
     119: iconst_m1
     120: iastore
     121: aload_2
     122: aastore
     123: aload_1
     124: checkcast     #287                // class "[Ljava/lang/Object;"
     127: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     130: aastore
     131: aload_0
     132: iconst_2
     133: iconst_3
     134: anewarray     #206                // class "[I"
     137: astore_1
     138: aload_1
     139: iconst_0
     140: iconst_2
     141: newarray       int
     143: astore_2
     144: aload_2
     145: iconst_0
     146: iconst_0
     147: iastore
     148: aload_2
     149: iconst_1
     150: iconst_m1
     151: iastore
     152: aload_2
     153: aastore
     154: aload_1
     155: iconst_1
     156: iconst_2
     157: newarray       int
     159: astore_2
     160: aload_2
     161: iconst_0
     162: iconst_m1
     163: iastore
     164: aload_2
     165: iconst_1
     166: iconst_m1
     167: iastore
     168: aload_2
     169: aastore
     170: aload_1
     171: iconst_2
     172: iconst_2
     173: newarray       int
     175: astore_2
     176: aload_2
     177: iconst_0
     178: iconst_1
     179: iastore
     180: aload_2
     181: iconst_1
     182: iconst_m1
     183: iastore
     184: aload_2
     185: aastore
     186: aload_1
     187: checkcast     #287                // class "[Ljava/lang/Object;"
     190: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     193: aastore
     194: aload_0
     195: iconst_3
     196: iconst_3
     197: anewarray     #206                // class "[I"
     200: astore_1
     201: aload_1
     202: iconst_0
     203: iconst_2
     204: newarray       int
     206: astore_2
     207: aload_2
     208: iconst_0
     209: iconst_0
     210: iastore
     211: aload_2
     212: iconst_1
     213: iconst_1
     214: iastore
     215: aload_2
     216: aastore
     217: aload_1
     218: iconst_1
     219: iconst_2
     220: newarray       int
     222: astore_2
     223: aload_2
     224: iconst_0
     225: iconst_m1
     226: iastore
     227: aload_2
     228: iconst_1
     229: iconst_1
     230: iastore
     231: aload_2
     232: aastore
     233: aload_1
     234: iconst_2
     235: iconst_2
     236: newarray       int
     238: astore_2
     239: aload_2
     240: iconst_0
     241: iconst_1
     242: iastore
     243: aload_2
     244: iconst_1
     245: iconst_1
     246: iastore
     247: aload_2
     248: aastore
     249: aload_1
     250: checkcast     #287                // class "[Ljava/lang/Object;"
     253: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     256: aastore
     257: aload_0
     258: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     261: putstatic     #209                // Field DIRECTIONS:Ljava/util/List;
     264: bipush        8
     266: anewarray     #206                // class "[I"
     269: astore_0
     270: aload_0
     271: iconst_0
     272: iconst_2
     273: newarray       int
     275: astore_1
     276: aload_1
     277: iconst_0
     278: iconst_m1
     279: iastore
     280: aload_1
     281: iconst_1
     282: iconst_m1
     283: iastore
     284: aload_1
     285: aastore
     286: aload_0
     287: iconst_1
     288: iconst_2
     289: newarray       int
     291: astore_1
     292: aload_1
     293: iconst_0
     294: iconst_m1
     295: iastore
     296: aload_1
     297: iconst_1
     298: iconst_0
     299: iastore
     300: aload_1
     301: aastore
     302: aload_0
     303: iconst_2
     304: iconst_2
     305: newarray       int
     307: astore_1
     308: aload_1
     309: iconst_0
     310: iconst_m1
     311: iastore
     312: aload_1
     313: iconst_1
     314: iconst_1
     315: iastore
     316: aload_1
     317: aastore
     318: aload_0
     319: iconst_3
     320: iconst_2
     321: newarray       int
     323: astore_1
     324: aload_1
     325: iconst_0
     326: iconst_0
     327: iastore
     328: aload_1
     329: iconst_1
     330: iconst_1
     331: iastore
     332: aload_1
     333: aastore
     334: aload_0
     335: iconst_4
     336: iconst_2
     337: newarray       int
     339: astore_1
     340: aload_1
     341: iconst_0
     342: iconst_1
     343: iastore
     344: aload_1
     345: iconst_1
     346: iconst_1
     347: iastore
     348: aload_1
     349: aastore
     350: aload_0
     351: iconst_5
     352: iconst_2
     353: newarray       int
     355: astore_1
     356: aload_1
     357: iconst_0
     358: iconst_1
     359: iastore
     360: aload_1
     361: iconst_1
     362: iconst_0
     363: iastore
     364: aload_1
     365: aastore
     366: aload_0
     367: bipush        6
     369: iconst_2
     370: newarray       int
     372: astore_1
     373: aload_1
     374: iconst_0
     375: iconst_1
     376: iastore
     377: aload_1
     378: iconst_1
     379: iconst_m1
     380: iastore
     381: aload_1
     382: aastore
     383: aload_0
     384: bipush        7
     386: iconst_2
     387: newarray       int
     389: astore_1
     390: aload_1
     391: iconst_0
     392: iconst_0
     393: iastore
     394: aload_1
     395: iconst_1
     396: iconst_m1
     397: iastore
     398: aload_1
     399: aastore
     400: aload_0
     401: checkcast     #287                // class "[Ljava/lang/Object;"
     404: invokestatic  #291                // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     407: putstatic     #203                // Field ALL_ADJACENT:Ljava/util/List;
     410: return
}


import java.util.*

fun main() {
    val testInput = readInput("Day05_test")
    check(part1(testInput) == "CMZ")
    check(part2(testInput) == "MCD")

    val input = readInput("Day05")
    println(part1(input))
    println(part2(input))
}

private fun part1(input: List<String>): String =
    solve(input) { stacks, cmd ->
        repeat(cmd.count) {
            stacks[cmd.to].push(stacks[cmd.from].pop())
        }
    }

private fun part2(input: List<String>): String {
    val stack = LinkedList<Char>()

    return solve(input) { stacks, cmd ->
        repeat(cmd.count) {
            stack.push(stacks[cmd.from].pop())
        }

        while (stack.isNotEmpty()) {
            stacks[cmd.to].push(stack.pop())
        }
    }
}

private fun solve(input: List<String>, reorderStrategy: (List<LinkedList<Char>>, Command) -> Unit): String {
    val dividerIndex = input.indexOfFirst { it.isEmpty() }
    val stacks = input
        .subList(0, dividerIndex)
        .toInitialStacks()

    input
        .subList(dividerIndex + 1, input.lastIndex + 1)
        .map(String::toCommand)
        .forEach { cmd ->
            reorderStrategy(stacks, cmd)
        }

    return stacks.joinToString(separator = "") {
        it.pop().toString()
    }
}

private fun List<String>.toInitialStacks(): List<LinkedList<Char>> {
    val count = this.last()
        .trim()
        .drop(
            this.last()
                .lastIndexOf(' ')
        )
        .toInt()
    val list = List(count) { LinkedList<Char>() }

    this.subList(0, this.lastIndex)
        .asReversed()
        .forEach { row ->
            var i = 1
            while (i <= row.lastIndex) {
                if (row[i].isLetter()) {
                    list[i / 4].push(row[i])
                }

                i += 4
            }
        }

    return list
}

private val COMMAND_FORMAT = Regex("move (\\d+) from (\\d+) to (\\d+)")

private fun String.toCommand(): Command {
    val match = COMMAND_FORMAT.find(this)
    val (move, from, to) = requireNotNull(match).destructured
    return Command(from = from.toInt() - 1, to = to.toInt() - 1, count = move.toInt())
}

private class Command(val from: Int, val to: Int, val count: Int)

Compiled from "Day05.kt"
public final class Day05Kt {
  private static final kotlin.text.Regex COMMAND_FORMAT;

  public static final void main();
    Code:
       0: ldc           #8                  // String Day05_test
       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;)Ljava/lang/String;
      10: ldc           #20                 // String CMZ
      12: invokestatic  #26                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      15: ifne          28
      18: new           #28                 // class java/lang/IllegalStateException
      21: dup
      22: ldc           #30                 // String Check failed.
      24: invokespecial #34                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      27: athrow
      28: aload_0
      29: invokestatic  #37                 // Method part2:(Ljava/util/List;)Ljava/lang/String;
      32: ldc           #39                 // String MCD
      34: invokestatic  #26                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      37: ifne          50
      40: new           #28                 // class java/lang/IllegalStateException
      43: dup
      44: ldc           #30                 // String Check failed.
      46: invokespecial #34                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      49: athrow
      50: ldc           #41                 // String Day05
      52: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      55: astore_1
      56: aload_1
      57: invokestatic  #18                 // Method part1:(Ljava/util/List;)Ljava/lang/String;
      60: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
      63: swap
      64: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      67: aload_1
      68: invokestatic  #37                 // Method part2:(Ljava/util/List;)Ljava/lang/String;
      71: getstatic     #47                 // Field java/lang/System.out:Ljava/io/PrintStream;
      74: swap
      75: invokevirtual #53                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      78: return

  private static final java.lang.String part1(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: invokedynamic #78,  0             // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function2;
       6: invokestatic  #82                 // Method solve:(Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/lang/String;
       9: areturn

  private static final java.lang.String part2(java.util.List<java.lang.String>);
    Code:
       0: new           #84                 // class java/util/LinkedList
       3: dup
       4: invokespecial #86                 // Method java/util/LinkedList."<init>":()V
       7: astore_1
       8: aload_0
       9: aload_1
      10: invokedynamic #94,  0             // InvokeDynamic #1:invoke:(Ljava/util/LinkedList;)Lkotlin/jvm/functions/Function2;
      15: invokestatic  #82                 // Method solve:(Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/lang/String;
      18: areturn

  private static final java.lang.String solve(java.util.List<java.lang.String>, kotlin.jvm.functions.Function2<? super java.util.List<? extends java.util.LinkedList<java.lang.Character>>, ? super Command, kotlin.Unit>);
    Code:
       0: aload_0
       1: astore_3
       2: iconst_0
       3: istore        4
       5: iconst_0
       6: istore        5
       8: aload_3
       9: invokeinterface #101,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      14: astore        6
      16: aload         6
      18: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      23: ifeq          78
      26: aload         6
      28: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      33: astore        7
      35: aload         7
      37: checkcast     #113                // class java/lang/String
      40: astore        8
      42: iconst_0
      43: istore        9
      45: aload         8
      47: checkcast     #115                // class java/lang/CharSequence
      50: invokeinterface #119,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      55: ifne          62
      58: iconst_1
      59: goto          63
      62: iconst_0
      63: nop
      64: ifeq          72
      67: iload         5
      69: goto          79
      72: iinc          5, 1
      75: goto          16
      78: iconst_m1
      79: istore_2
      80: aload_0
      81: iconst_0
      82: iload_2
      83: invokeinterface #123,  3          // InterfaceMethod java/util/List.subList:(II)Ljava/util/List;
      88: invokestatic  #127                // Method toInitialStacks:(Ljava/util/List;)Ljava/util/List;
      91: astore_3
      92: aload_0
      93: iload_2
      94: iconst_1
      95: iadd
      96: aload_0
      97: invokestatic  #133                // Method kotlin/collections/CollectionsKt.getLastIndex:(Ljava/util/List;)I
     100: iconst_1
     101: iadd
     102: invokeinterface #123,  3          // InterfaceMethod java/util/List.subList:(II)Ljava/util/List;
     107: checkcast     #135                // class java/lang/Iterable
     110: astore        4
     112: nop
     113: iconst_0
     114: istore        5
     116: aload         4
     118: astore        6
     120: new           #137                // class java/util/ArrayList
     123: dup
     124: aload         4
     126: bipush        10
     128: invokestatic  #141                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     131: invokespecial #144                // Method java/util/ArrayList."<init>":(I)V
     134: checkcast     #146                // class java/util/Collection
     137: astore        7
     139: iconst_0
     140: istore        8
     142: aload         6
     144: invokeinterface #147,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     149: astore        9
     151: aload         9
     153: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     158: ifeq          201
     161: aload         9
     163: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     168: astore        10
     170: aload         7
     172: aload         10
     174: checkcast     #113                // class java/lang/String
     177: astore        11
     179: astore        13
     181: iconst_0
     182: istore        12
     184: aload         11
     186: invokestatic  #151                // Method toCommand:(Ljava/lang/String;)LCommand;
     189: aload         13
     191: swap
     192: invokeinterface #155,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     197: pop
     198: goto          151
     201: aload         7
     203: checkcast     #58                 // class java/util/List
     206: nop
     207: checkcast     #135                // class java/lang/Iterable
     210: astore        4
     212: nop
     213: iconst_0
     214: istore        5
     216: aload         4
     218: invokeinterface #147,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     223: astore        6
     225: aload         6
     227: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     232: ifeq          269
     235: aload         6
     237: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     242: astore        7
     244: aload         7
     246: checkcast     #157                // class Command
     249: astore        8
     251: iconst_0
     252: istore        9
     254: aload_1
     255: aload_3
     256: aload         8
     258: invokeinterface #161,  3          // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     263: pop
     264: nop
     265: nop
     266: goto          225
     269: nop
     270: aload_3
     271: checkcast     #135                // class java/lang/Iterable
     274: ldc           #163                // String
     276: checkcast     #115                // class java/lang/CharSequence
     279: aconst_null
     280: aconst_null
     281: iconst_0
     282: aconst_null
     283: invokedynamic #174,  0            // InvokeDynamic #2:invoke:()Lkotlin/jvm/functions/Function1;
     288: bipush        30
     290: aconst_null
     291: invokestatic  #178                // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     294: areturn

  private static final java.util.List<java.util.LinkedList<java.lang.Character>> toInitialStacks(java.util.List<java.lang.String>);
    Code:
       0: nop
       1: nop
       2: aload_0
       3: invokestatic  #212                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
       6: checkcast     #113                // class java/lang/String
       9: checkcast     #115                // class java/lang/CharSequence
      12: invokestatic  #218                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      15: invokevirtual #222                // Method java/lang/Object.toString:()Ljava/lang/String;
      18: aload_0
      19: invokestatic  #212                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      22: checkcast     #115                // class java/lang/CharSequence
      25: bipush        32
      27: iconst_0
      28: iconst_0
      29: bipush        6
      31: aconst_null
      32: invokestatic  #226                // Method kotlin/text/StringsKt.lastIndexOf$default:(Ljava/lang/CharSequence;CIZILjava/lang/Object;)I
      35: invokestatic  #230                // Method kotlin/text/StringsKt.drop:(Ljava/lang/String;I)Ljava/lang/String;
      38: invokestatic  #236                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      41: istore_1
      42: new           #137                // class java/util/ArrayList
      45: dup
      46: iload_1
      47: invokespecial #144                // Method java/util/ArrayList."<init>":(I)V
      50: astore_3
      51: iconst_0
      52: istore        4
      54: iload         4
      56: iload_1
      57: if_icmpge     94
      60: iload         4
      62: istore        5
      64: aload_3
      65: iload         5
      67: istore        6
      69: astore        10
      71: iconst_0
      72: istore        7
      74: new           #84                 // class java/util/LinkedList
      77: dup
      78: invokespecial #86                 // Method java/util/LinkedList."<init>":()V
      81: aload         10
      83: swap
      84: invokevirtual #237                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      87: pop
      88: iinc          4, 1
      91: goto          54
      94: aload_3
      95: checkcast     #58                 // class java/util/List
      98: astore_2
      99: aload_0
     100: iconst_0
     101: aload_0
     102: invokestatic  #133                // Method kotlin/collections/CollectionsKt.getLastIndex:(Ljava/util/List;)I
     105: invokeinterface #123,  3          // InterfaceMethod java/util/List.subList:(II)Ljava/util/List;
     110: invokestatic  #240                // Method kotlin/collections/CollectionsKt.asReversed:(Ljava/util/List;)Ljava/util/List;
     113: checkcast     #135                // class java/lang/Iterable
     116: astore_3
     117: nop
     118: iconst_0
     119: istore        4
     121: aload_3
     122: invokeinterface #147,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     127: astore        5
     129: aload         5
     131: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     136: ifeq          224
     139: aload         5
     141: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     146: astore        6
     148: aload         6
     150: checkcast     #113                // class java/lang/String
     153: astore        7
     155: iconst_0
     156: istore        8
     158: iconst_1
     159: istore        9
     161: iload         9
     163: aload         7
     165: checkcast     #115                // class java/lang/CharSequence
     168: invokestatic  #243                // Method kotlin/text/StringsKt.getLastIndex:(Ljava/lang/CharSequence;)I
     171: if_icmpgt     219
     174: aload         7
     176: iload         9
     178: invokevirtual #247                // Method java/lang/String.charAt:(I)C
     181: invokestatic  #253                // Method java/lang/Character.isLetter:(C)Z
     184: ifeq          213
     187: aload_2
     188: iload         9
     190: iconst_4
     191: idiv
     192: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     197: checkcast     #84                 // class java/util/LinkedList
     200: aload         7
     202: iload         9
     204: invokevirtual #247                // Method java/lang/String.charAt:(I)C
     207: invokestatic  #261                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     210: invokevirtual #264                // Method java/util/LinkedList.push:(Ljava/lang/Object;)V
     213: iinc          9, 4
     216: goto          161
     219: nop
     220: nop
     221: goto          129
     224: nop
     225: aload_2
     226: areturn

  private static final Command toCommand(java.lang.String);
    Code:
       0: getstatic     #275                // Field COMMAND_FORMAT:Lkotlin/text/Regex;
       3: aload_0
       4: checkcast     #115                // class java/lang/CharSequence
       7: iconst_0
       8: iconst_2
       9: aconst_null
      10: invokestatic  #281                // Method kotlin/text/Regex.find$default:(Lkotlin/text/Regex;Ljava/lang/CharSequence;IILjava/lang/Object;)Lkotlin/text/MatchResult;
      13: astore_1
      14: aload_1
      15: dup
      16: ifnonnull     36
      19: pop
      20: ldc_w         #283                // String Required value was null.
      23: astore_3
      24: new           #285                // class java/lang/IllegalArgumentException
      27: dup
      28: aload_3
      29: invokevirtual #222                // Method java/lang/Object.toString:()Ljava/lang/String;
      32: invokespecial #286                // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      35: athrow
      36: invokeinterface #292,  1          // InterfaceMethod kotlin/text/MatchResult.getDestructured:()Lkotlin/text/MatchResult$Destructured;
      41: astore_2
      42: aload_2
      43: invokevirtual #298                // Method kotlin/text/MatchResult$Destructured.getMatch:()Lkotlin/text/MatchResult;
      46: invokeinterface #302,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
      51: iconst_1
      52: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      57: checkcast     #113                // class java/lang/String
      60: astore_3
      61: aload_2
      62: invokevirtual #298                // Method kotlin/text/MatchResult$Destructured.getMatch:()Lkotlin/text/MatchResult;
      65: invokeinterface #302,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
      70: iconst_2
      71: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      76: checkcast     #113                // class java/lang/String
      79: astore        4
      81: aload_2
      82: invokevirtual #298                // Method kotlin/text/MatchResult$Destructured.getMatch:()Lkotlin/text/MatchResult;
      85: invokeinterface #302,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
      90: iconst_3
      91: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      96: checkcast     #113                // class java/lang/String
      99: astore        5
     101: new           #157                // class Command
     104: dup
     105: aload         4
     107: invokestatic  #236                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     110: iconst_1
     111: isub
     112: aload         5
     114: invokestatic  #236                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     117: iconst_1
     118: isub
     119: aload_3
     120: invokestatic  #236                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     123: invokespecial #305                // Method Command."<init>":(III)V
     126: areturn

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

  private static final kotlin.Unit part1$lambda$1(java.util.List, Command);
    Code:
       0: aload_0
       1: ldc_w         #317                // String stacks
       4: invokestatic  #321                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_1
       8: ldc_w         #322                // String cmd
      11: invokestatic  #321                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      14: aload_1
      15: invokevirtual #325                // Method Command.getCount:()I
      18: istore_2
      19: iconst_0
      20: istore_3
      21: iload_3
      22: iload_2
      23: if_icmpge     71
      26: iload_3
      27: istore        4
      29: iconst_0
      30: istore        5
      32: aload_0
      33: aload_1
      34: invokevirtual #328                // Method Command.getTo:()I
      37: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      42: checkcast     #84                 // class java/util/LinkedList
      45: aload_0
      46: aload_1
      47: invokevirtual #331                // Method Command.getFrom:()I
      50: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      55: checkcast     #84                 // class java/util/LinkedList
      58: invokevirtual #334                // Method java/util/LinkedList.pop:()Ljava/lang/Object;
      61: invokevirtual #264                // Method java/util/LinkedList.push:(Ljava/lang/Object;)V
      64: nop
      65: iinc          3, 1
      68: goto          21
      71: getstatic     #340                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      74: areturn

  private static final kotlin.Unit part2$lambda$3(java.util.LinkedList, java.util.List, Command);
    Code:
       0: aload_1
       1: ldc_w         #317                // String stacks
       4: invokestatic  #321                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_2
       8: ldc_w         #322                // String cmd
      11: invokestatic  #321                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      14: aload_2
      15: invokevirtual #325                // Method Command.getCount:()I
      18: istore_3
      19: iconst_0
      20: istore        4
      22: iload         4
      24: iload_3
      25: if_icmpge     62
      28: iload         4
      30: istore        5
      32: iconst_0
      33: istore        6
      35: aload_0
      36: aload_1
      37: aload_2
      38: invokevirtual #331                // Method Command.getFrom:()I
      41: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      46: checkcast     #84                 // class java/util/LinkedList
      49: invokevirtual #334                // Method java/util/LinkedList.pop:()Ljava/lang/Object;
      52: invokevirtual #264                // Method java/util/LinkedList.push:(Ljava/lang/Object;)V
      55: nop
      56: iinc          4, 1
      59: goto          22
      62: aload_0
      63: checkcast     #146                // class java/util/Collection
      66: invokeinterface #344,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      71: ifne          78
      74: iconst_1
      75: goto          79
      78: iconst_0
      79: ifeq          105
      82: aload_1
      83: aload_2
      84: invokevirtual #328                // Method Command.getTo:()I
      87: invokeinterface #257,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      92: checkcast     #84                 // class java/util/LinkedList
      95: aload_0
      96: invokevirtual #334                // Method java/util/LinkedList.pop:()Ljava/lang/Object;
      99: invokevirtual #264                // Method java/util/LinkedList.push:(Ljava/lang/Object;)V
     102: goto          62
     105: getstatic     #340                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     108: areturn

  private static final java.lang.CharSequence solve$lambda$6(java.util.LinkedList);
    Code:
       0: aload_0
       1: ldc_w         #347                // String it
       4: invokestatic  #321                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #334                // Method java/util/LinkedList.pop:()Ljava/lang/Object;
      11: checkcast     #249                // class java/lang/Character
      14: invokevirtual #348                // Method java/lang/Character.toString:()Ljava/lang/String;
      17: checkcast     #115                // class java/lang/CharSequence
      20: areturn

  static {};
    Code:
       0: new           #277                // class kotlin/text/Regex
       3: dup
       4: ldc_w         #351                // String move (\\d+) from (\\d+) to (\\d+)
       7: invokespecial #352                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      10: putstatic     #275                // Field COMMAND_FORMAT:Lkotlin/text/Regex;
      13: return
}


fun main() {
    val testInput = readInput("Day21_test")
    val testOperations = testInput.toOperations()
    check(part1(testOperations) == 152L)
    check(part2(testOperations) == 301L)

    val input = readInput("Day21")
    val operations = input.toOperations()
    println(part1(operations))
    println(part2(operations))
}

private fun part1(operations: Map<String, MathOperation>): Long = getValue("root", operations)

private const val TARGET_OPERATION = "humn"
private fun part2(operations: Map<String, MathOperation>): Long {
    val rootOp = operations.getValue("root")
    val operand1Depends = dependsOn(rootOp.operand1, TARGET_OPERATION, operations)

    val targetValue = getValue(
        name = if (operand1Depends) rootOp.operand2 else rootOp.operand1,
        operations = operations
    )

    return correctToValue(
        name = if (operand1Depends) rootOp.operand1 else rootOp.operand2,
        targetValue = targetValue,
        targetOperationName = TARGET_OPERATION,
        operations = operations
    )
}

private fun correctToValue(
    name: String,
    targetValue: Long,
    targetOperationName: String,
    operations: Map<String, MathOperation>
): Long {
    if (name == targetOperationName) {
        return targetValue
    }

    val op = operations.getValue(name)
    val operand1Depends = dependsOn(op.operand1, TARGET_OPERATION, operations)
    val anotherOperandValue = getValue(
        name = if (operand1Depends) op.operand2 else op.operand1,
        operations = operations
    )
    val nextName = if (operand1Depends) op.operand1 else op.operand2

    val nextTargetValue = when (op) {
        is MathOperation.Divide ->
            if (operand1Depends) {
                targetValue * anotherOperandValue
            } else {
                anotherOperandValue / targetValue
            }
        is MathOperation.Minus ->
            if (operand1Depends) {
                targetValue + anotherOperandValue
            } else {
                anotherOperandValue - targetValue
            }
        is MathOperation.Multiply -> targetValue / anotherOperandValue
        is MathOperation.Plus -> targetValue - anotherOperandValue
        is MathOperation.Value -> error("Should not be here")
    }

    return correctToValue(nextName, nextTargetValue, targetOperationName, operations)
}

private fun dependsOn(
    operationName: String,
    targetDependency: String,
    operations: Map<String, MathOperation>
): Boolean {
    if (operationName == targetDependency) {
        return true
    }

    return when (val op = operations.getValue(operationName)) {
        is MathOperation.Value -> false
        else ->
            dependsOn(op.operand1, targetDependency, operations) || dependsOn(op.operand2, targetDependency, operations)
    }
}

private fun getValue(name: String, operations: Map<String, MathOperation>): Long {
    return when (val op = operations.getValue(name)) {
        is MathOperation.Divide -> getValue(op.operand1, operations) / getValue(op.operand2, operations)
        is MathOperation.Minus -> getValue(op.operand1, operations) - getValue(op.operand2, operations)
        is MathOperation.Multiply -> getValue(op.operand1, operations) * getValue(op.operand2, operations)
        is MathOperation.Plus -> getValue(op.operand1, operations) + getValue(op.operand2, operations)
        is MathOperation.Value -> op.value
    }
}

private fun List<String>.toOperations(): Map<String, MathOperation> = this.associate { row ->
    val name = row.substringBefore(":")
    val operationStr = row.substringAfter(": ")
    val operation = when {
        operationStr.contains('+') ->
            MathOperation.Plus(
                operand1 = operationStr.substringBefore(" + "),
                operand2 = operationStr.substringAfter(" + ")
            )
        operationStr.contains('-') ->
            MathOperation.Minus(
                operand1 = operationStr.substringBefore(" - "),
                operand2 = operationStr.substringAfter(" - ")
            )
        operationStr.contains('/') ->
            MathOperation.Divide(
                operand1 = operationStr.substringBefore(" / "),
                operand2 = operationStr.substringAfter(" / ")
            )
        operationStr.contains('*') ->
            MathOperation.Multiply(
                operand1 = operationStr.substringBefore(" * "),
                operand2 = operationStr.substringAfter(" * ")
            )
        else -> MathOperation.Value(operationStr.toLong())
    }

    name to operation
}

private sealed interface MathOperation {
    class Value(val value: Long) : MathOperation
    class Plus(val operand1: String, val operand2: String) : MathOperation
    class Minus(val operand1: String, val operand2: String) : MathOperation
    class Multiply(val operand1: String, val operand2: String) : MathOperation
    class Divide(val operand1: String, val operand2: String) : MathOperation
}

private val MathOperation.operand1: String
    get() = when (this) {
        is MathOperation.Divide -> this.operand1
        is MathOperation.Minus -> this.operand1
        is MathOperation.Multiply -> this.operand1
        is MathOperation.Plus -> this.operand1
        is MathOperation.Value -> error("MathOperation.Value doesn't have operands")
    }

private val MathOperation.operand2: String
    get() = when (this) {
        is MathOperation.Divide -> this.operand2
        is MathOperation.Minus -> this.operand2
        is MathOperation.Multiply -> this.operand2
        is MathOperation.Plus -> this.operand2
        is MathOperation.Value -> error("MathOperation.Value doesn't have operands")
    }

Compiled from "Day21.kt"
public final class Day21Kt {
  private static final java.lang.String TARGET_OPERATION;

  public static final void main();
    Code:
       0: ldc           #8                  // String Day21_test
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: invokestatic  #18                 // Method toOperations:(Ljava/util/List;)Ljava/util/Map;
      10: astore_1
      11: aload_1
      12: invokestatic  #22                 // Method part1:(Ljava/util/Map;)J
      15: ldc2_w        #23                 // long 152l
      18: lcmp
      19: ifne          26
      22: iconst_1
      23: goto          27
      26: iconst_0
      27: ifne          40
      30: new           #26                 // class java/lang/IllegalStateException
      33: dup
      34: ldc           #28                 // String Check failed.
      36: invokespecial #32                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      39: athrow
      40: aload_1
      41: invokestatic  #35                 // Method part2:(Ljava/util/Map;)J
      44: ldc2_w        #36                 // long 301l
      47: lcmp
      48: ifne          55
      51: iconst_1
      52: goto          56
      55: iconst_0
      56: ifne          69
      59: new           #26                 // class java/lang/IllegalStateException
      62: dup
      63: ldc           #28                 // String Check failed.
      65: invokespecial #32                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      68: athrow
      69: ldc           #39                 // String Day21
      71: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      74: astore_2
      75: aload_2
      76: invokestatic  #18                 // Method toOperations:(Ljava/util/List;)Ljava/util/Map;
      79: astore_3
      80: aload_3
      81: invokestatic  #22                 // Method part1:(Ljava/util/Map;)J
      84: lstore        4
      86: getstatic     #45                 // Field java/lang/System.out:Ljava/io/PrintStream;
      89: lload         4
      91: invokevirtual #51                 // Method java/io/PrintStream.println:(J)V
      94: aload_3
      95: invokestatic  #35                 // Method part2:(Ljava/util/Map;)J
      98: lstore        4
     100: getstatic     #45                 // Field java/lang/System.out:Ljava/io/PrintStream;
     103: lload         4
     105: invokevirtual #51                 // Method java/io/PrintStream.println:(J)V
     108: return

  private static final long part1(java.util.Map<java.lang.String, ? extends MathOperation>);
    Code:
       0: ldc           #64                 // String root
       2: aload_0
       3: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
       6: lreturn

  private static final long part2(java.util.Map<java.lang.String, ? extends MathOperation>);
    Code:
       0: aload_0
       1: ldc           #64                 // String root
       3: invokestatic  #73                 // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
       6: checkcast     #75                 // class MathOperation
       9: astore_1
      10: aload_1
      11: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      14: ldc           #81                 // String humn
      16: aload_0
      17: invokestatic  #85                 // Method dependsOn:(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Z
      20: istore_2
      21: iload_2
      22: ifeq          32
      25: aload_1
      26: invokestatic  #88                 // Method getOperand2:(LMathOperation;)Ljava/lang/String;
      29: goto          36
      32: aload_1
      33: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      36: aload_0
      37: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      40: lstore_3
      41: iload_2
      42: ifeq          52
      45: aload_1
      46: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      49: goto          56
      52: aload_1
      53: invokestatic  #88                 // Method getOperand2:(LMathOperation;)Ljava/lang/String;
      56: lload_3
      57: ldc           #81                 // String humn
      59: aload_0
      60: invokestatic  #92                 // Method correctToValue:(Ljava/lang/String;JLjava/lang/String;Ljava/util/Map;)J
      63: lreturn

  private static final long correctToValue(java.lang.String, long, java.lang.String, java.util.Map<java.lang.String, ? extends MathOperation>);
    Code:
       0: aload_0
       1: aload_3
       2: invokestatic  #107                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
       5: ifeq          10
       8: lload_1
       9: lreturn
      10: aload         4
      12: aload_0
      13: invokestatic  #73                 // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
      16: checkcast     #75                 // class MathOperation
      19: astore        5
      21: aload         5
      23: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      26: ldc           #81                 // String humn
      28: aload         4
      30: invokestatic  #85                 // Method dependsOn:(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Z
      33: istore        6
      35: iload         6
      37: ifeq          48
      40: aload         5
      42: invokestatic  #88                 // Method getOperand2:(LMathOperation;)Ljava/lang/String;
      45: goto          53
      48: aload         5
      50: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      53: aload         4
      55: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      58: lstore        7
      60: iload         6
      62: ifeq          73
      65: aload         5
      67: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      70: goto          78
      73: aload         5
      75: invokestatic  #88                 // Method getOperand2:(LMathOperation;)Ljava/lang/String;
      78: astore        9
      80: aload         5
      82: astore        12
      84: aload         12
      86: instanceof    #109                // class MathOperation$Divide
      89: ifeq          111
      92: iload         6
      94: ifeq          104
      97: lload_1
      98: lload         7
     100: lmul
     101: goto          197
     104: lload         7
     106: lload_1
     107: ldiv
     108: goto          197
     111: aload         12
     113: instanceof    #111                // class MathOperation$Minus
     116: ifeq          138
     119: iload         6
     121: ifeq          131
     124: lload_1
     125: lload         7
     127: ladd
     128: goto          197
     131: lload         7
     133: lload_1
     134: lsub
     135: goto          197
     138: aload         12
     140: instanceof    #113                // class MathOperation$Multiply
     143: ifeq          153
     146: lload_1
     147: lload         7
     149: ldiv
     150: goto          197
     153: aload         12
     155: instanceof    #115                // class MathOperation$Plus
     158: ifeq          168
     161: lload_1
     162: lload         7
     164: lsub
     165: goto          197
     168: aload         12
     170: instanceof    #117                // class MathOperation$Value
     173: ifeq          189
     176: new           #26                 // class java/lang/IllegalStateException
     179: dup
     180: ldc           #119                // String Should not be here
     182: invokevirtual #123                // Method java/lang/Object.toString:()Ljava/lang/String;
     185: invokespecial #32                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     188: athrow
     189: new           #125                // class kotlin/NoWhenBranchMatchedException
     192: dup
     193: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     196: athrow
     197: lstore        10
     199: aload         9
     201: lload         10
     203: aload_3
     204: aload         4
     206: invokestatic  #92                 // Method correctToValue:(Ljava/lang/String;JLjava/lang/String;Ljava/util/Map;)J
     209: lreturn

  private static final boolean dependsOn(java.lang.String, java.lang.String, java.util.Map<java.lang.String, ? extends MathOperation>);
    Code:
       0: aload_0
       1: aload_1
       2: invokestatic  #107                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
       5: ifeq          10
       8: iconst_1
       9: ireturn
      10: aload_2
      11: aload_0
      12: invokestatic  #73                 // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
      15: checkcast     #75                 // class MathOperation
      18: astore_3
      19: aload_3
      20: instanceof    #117                // class MathOperation$Value
      23: ifeq          30
      26: iconst_0
      27: goto          59
      30: aload_3
      31: invokestatic  #79                 // Method getOperand1:(LMathOperation;)Ljava/lang/String;
      34: aload_1
      35: aload_2
      36: invokestatic  #85                 // Method dependsOn:(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Z
      39: ifne          54
      42: aload_3
      43: invokestatic  #88                 // Method getOperand2:(LMathOperation;)Ljava/lang/String;
      46: aload_1
      47: aload_2
      48: invokestatic  #85                 // Method dependsOn:(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Z
      51: ifeq          58
      54: iconst_1
      55: goto          59
      58: iconst_0
      59: ireturn

  private static final long getValue(java.lang.String, java.util.Map<java.lang.String, ? extends MathOperation>);
    Code:
       0: aload_1
       1: aload_0
       2: invokestatic  #73                 // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
       5: checkcast     #75                 // class MathOperation
       8: astore_2
       9: aload_2
      10: instanceof    #109                // class MathOperation$Divide
      13: ifeq          42
      16: aload_2
      17: checkcast     #109                // class MathOperation$Divide
      20: invokevirtual #140                // Method MathOperation$Divide.getOperand1:()Ljava/lang/String;
      23: aload_1
      24: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      27: aload_2
      28: checkcast     #109                // class MathOperation$Divide
      31: invokevirtual #142                // Method MathOperation$Divide.getOperand2:()Ljava/lang/String;
      34: aload_1
      35: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      38: ldiv
      39: goto          166
      42: aload_2
      43: instanceof    #111                // class MathOperation$Minus
      46: ifeq          75
      49: aload_2
      50: checkcast     #111                // class MathOperation$Minus
      53: invokevirtual #143                // Method MathOperation$Minus.getOperand1:()Ljava/lang/String;
      56: aload_1
      57: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      60: aload_2
      61: checkcast     #111                // class MathOperation$Minus
      64: invokevirtual #144                // Method MathOperation$Minus.getOperand2:()Ljava/lang/String;
      67: aload_1
      68: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      71: lsub
      72: goto          166
      75: aload_2
      76: instanceof    #113                // class MathOperation$Multiply
      79: ifeq          108
      82: aload_2
      83: checkcast     #113                // class MathOperation$Multiply
      86: invokevirtual #145                // Method MathOperation$Multiply.getOperand1:()Ljava/lang/String;
      89: aload_1
      90: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
      93: aload_2
      94: checkcast     #113                // class MathOperation$Multiply
      97: invokevirtual #146                // Method MathOperation$Multiply.getOperand2:()Ljava/lang/String;
     100: aload_1
     101: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
     104: lmul
     105: goto          166
     108: aload_2
     109: instanceof    #115                // class MathOperation$Plus
     112: ifeq          141
     115: aload_2
     116: checkcast     #115                // class MathOperation$Plus
     119: invokevirtual #147                // Method MathOperation$Plus.getOperand1:()Ljava/lang/String;
     122: aload_1
     123: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
     126: aload_2
     127: checkcast     #115                // class MathOperation$Plus
     130: invokevirtual #148                // Method MathOperation$Plus.getOperand2:()Ljava/lang/String;
     133: aload_1
     134: invokestatic  #68                 // Method getValue:(Ljava/lang/String;Ljava/util/Map;)J
     137: ladd
     138: goto          166
     141: aload_2
     142: instanceof    #117                // class MathOperation$Value
     145: ifeq          158
     148: aload_2
     149: checkcast     #117                // class MathOperation$Value
     152: invokevirtual #151                // Method MathOperation$Value.getValue:()J
     155: goto          166
     158: new           #125                // class kotlin/NoWhenBranchMatchedException
     161: dup
     162: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     165: athrow
     166: lreturn

  private static final java.util.Map<java.lang.String, MathOperation> toOperations(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: checkcast     #154                // class java/lang/Iterable
       4: astore_1
       5: iconst_0
       6: istore_2
       7: aload_1
       8: bipush        10
      10: invokestatic  #160                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      13: invokestatic  #164                // Method kotlin/collections/MapsKt.mapCapacity:(I)I
      16: bipush        16
      18: invokestatic  #170                // Method kotlin/ranges/RangesKt.coerceAtLeast:(II)I
      21: istore_3
      22: aload_1
      23: astore        4
      25: new           #172                // class java/util/LinkedHashMap
      28: dup
      29: iload_3
      30: invokespecial #175                // Method java/util/LinkedHashMap."<init>":(I)V
      33: checkcast     #61                 // class java/util/Map
      36: astore        5
      38: iconst_0
      39: istore        6
      41: aload         4
      43: invokeinterface #179,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      48: astore        7
      50: aload         7
      52: invokeinterface #185,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      57: ifeq          351
      60: aload         7
      62: invokeinterface #189,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      67: astore        8
      69: aload         5
      71: astore        9
      73: aload         8
      75: checkcast     #100                // class java/lang/String
      78: astore        10
      80: iconst_0
      81: istore        11
      83: aload         10
      85: ldc           #191                // String :
      87: aconst_null
      88: iconst_2
      89: aconst_null
      90: invokestatic  #197                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      93: astore        12
      95: aload         10
      97: ldc           #199                // String :
      99: aconst_null
     100: iconst_2
     101: aconst_null
     102: invokestatic  #202                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     105: astore        13
     107: nop
     108: aload         13
     110: checkcast     #204                // class java/lang/CharSequence
     113: bipush        43
     115: iconst_0
     116: iconst_2
     117: aconst_null
     118: invokestatic  #208                // Method kotlin/text/StringsKt.contains$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
     121: ifeq          157
     124: new           #115                // class MathOperation$Plus
     127: dup
     128: aload         13
     130: ldc           #210                // String  +
     132: aconst_null
     133: iconst_2
     134: aconst_null
     135: invokestatic  #197                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     138: aload         13
     140: ldc           #210                // String  +
     142: aconst_null
     143: iconst_2
     144: aconst_null
     145: invokestatic  #202                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     148: invokespecial #213                // Method MathOperation$Plus."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     151: checkcast     #75                 // class MathOperation
     154: goto          319
     157: aload         13
     159: checkcast     #204                // class java/lang/CharSequence
     162: bipush        45
     164: iconst_0
     165: iconst_2
     166: aconst_null
     167: invokestatic  #208                // Method kotlin/text/StringsKt.contains$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
     170: ifeq          206
     173: new           #111                // class MathOperation$Minus
     176: dup
     177: aload         13
     179: ldc           #215                // String  -
     181: aconst_null
     182: iconst_2
     183: aconst_null
     184: invokestatic  #197                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     187: aload         13
     189: ldc           #215                // String  -
     191: aconst_null
     192: iconst_2
     193: aconst_null
     194: invokestatic  #202                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     197: invokespecial #216                // Method MathOperation$Minus."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     200: checkcast     #75                 // class MathOperation
     203: goto          319
     206: aload         13
     208: checkcast     #204                // class java/lang/CharSequence
     211: bipush        47
     213: iconst_0
     214: iconst_2
     215: aconst_null
     216: invokestatic  #208                // Method kotlin/text/StringsKt.contains$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
     219: ifeq          255
     222: new           #109                // class MathOperation$Divide
     225: dup
     226: aload         13
     228: ldc           #218                // String  /
     230: aconst_null
     231: iconst_2
     232: aconst_null
     233: invokestatic  #197                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     236: aload         13
     238: ldc           #218                // String  /
     240: aconst_null
     241: iconst_2
     242: aconst_null
     243: invokestatic  #202                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     246: invokespecial #219                // Method MathOperation$Divide."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     249: checkcast     #75                 // class MathOperation
     252: goto          319
     255: aload         13
     257: checkcast     #204                // class java/lang/CharSequence
     260: bipush        42
     262: iconst_0
     263: iconst_2
     264: aconst_null
     265: invokestatic  #208                // Method kotlin/text/StringsKt.contains$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
     268: ifeq          304
     271: new           #113                // class MathOperation$Multiply
     274: dup
     275: aload         13
     277: ldc           #221                // String  *
     279: aconst_null
     280: iconst_2
     281: aconst_null
     282: invokestatic  #197                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     285: aload         13
     287: ldc           #221                // String  *
     289: aconst_null
     290: iconst_2
     291: aconst_null
     292: invokestatic  #202                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     295: invokespecial #222                // Method MathOperation$Multiply."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     298: checkcast     #75                 // class MathOperation
     301: goto          319
     304: new           #117                // class MathOperation$Value
     307: dup
     308: aload         13
     310: invokestatic  #228                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
     313: invokespecial #230                // Method MathOperation$Value."<init>":(J)V
     316: checkcast     #75                 // class MathOperation
     319: astore        14
     321: aload         12
     323: aload         14
     325: invokestatic  #236                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     328: astore        10
     330: aload         9
     332: aload         10
     334: invokevirtual #241                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     337: aload         10
     339: invokevirtual #244                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     342: invokeinterface #248,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     347: pop
     348: goto          50
     351: aload         5
     353: nop
     354: areturn

  private static final java.lang.String getOperand1(MathOperation);
    Code:
       0: aload_0
       1: astore_1
       2: aload_1
       3: instanceof    #109                // class MathOperation$Divide
       6: ifeq          19
       9: aload_0
      10: checkcast     #109                // class MathOperation$Divide
      13: invokevirtual #140                // Method MathOperation$Divide.getOperand1:()Ljava/lang/String;
      16: goto          99
      19: aload_1
      20: instanceof    #111                // class MathOperation$Minus
      23: ifeq          36
      26: aload_0
      27: checkcast     #111                // class MathOperation$Minus
      30: invokevirtual #143                // Method MathOperation$Minus.getOperand1:()Ljava/lang/String;
      33: goto          99
      36: aload_1
      37: instanceof    #113                // class MathOperation$Multiply
      40: ifeq          53
      43: aload_0
      44: checkcast     #113                // class MathOperation$Multiply
      47: invokevirtual #145                // Method MathOperation$Multiply.getOperand1:()Ljava/lang/String;
      50: goto          99
      53: aload_1
      54: instanceof    #115                // class MathOperation$Plus
      57: ifeq          70
      60: aload_0
      61: checkcast     #115                // class MathOperation$Plus
      64: invokevirtual #147                // Method MathOperation$Plus.getOperand1:()Ljava/lang/String;
      67: goto          99
      70: aload_1
      71: instanceof    #117                // class MathOperation$Value
      74: ifeq          91
      77: new           #26                 // class java/lang/IllegalStateException
      80: dup
      81: ldc_w         #265                // String MathOperation.Value doesn\'t have operands
      84: invokevirtual #123                // Method java/lang/Object.toString:()Ljava/lang/String;
      87: invokespecial #32                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      90: athrow
      91: new           #125                // class kotlin/NoWhenBranchMatchedException
      94: dup
      95: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
      98: athrow
      99: areturn

  private static final java.lang.String getOperand2(MathOperation);
    Code:
       0: aload_0
       1: astore_1
       2: aload_1
       3: instanceof    #109                // class MathOperation$Divide
       6: ifeq          19
       9: aload_0
      10: checkcast     #109                // class MathOperation$Divide
      13: invokevirtual #142                // Method MathOperation$Divide.getOperand2:()Ljava/lang/String;
      16: goto          99
      19: aload_1
      20: instanceof    #111                // class MathOperation$Minus
      23: ifeq          36
      26: aload_0
      27: checkcast     #111                // class MathOperation$Minus
      30: invokevirtual #144                // Method MathOperation$Minus.getOperand2:()Ljava/lang/String;
      33: goto          99
      36: aload_1
      37: instanceof    #113                // class MathOperation$Multiply
      40: ifeq          53
      43: aload_0
      44: checkcast     #113                // class MathOperation$Multiply
      47: invokevirtual #146                // Method MathOperation$Multiply.getOperand2:()Ljava/lang/String;
      50: goto          99
      53: aload_1
      54: instanceof    #115                // class MathOperation$Plus
      57: ifeq          70
      60: aload_0
      61: checkcast     #115                // class MathOperation$Plus
      64: invokevirtual #148                // Method MathOperation$Plus.getOperand2:()Ljava/lang/String;
      67: goto          99
      70: aload_1
      71: instanceof    #117                // class MathOperation$Value
      74: ifeq          91
      77: new           #26                 // class java/lang/IllegalStateException
      80: dup
      81: ldc_w         #265                // String MathOperation.Value doesn\'t have operands
      84: invokevirtual #123                // Method java/lang/Object.toString:()Ljava/lang/String;
      87: invokespecial #32                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      90: athrow
      91: new           #125                // class kotlin/NoWhenBranchMatchedException
      94: dup
      95: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
      98: athrow
      99: areturn

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