import java.util.*

fun main() {
    val testInput = readInput("Day24_test")
    val testMap = BlizzardMap(testInput)
    check(part1(testMap) == 18)
    check(part2(testMap) == 54)

    val input = readInput("Day24")
    val map = BlizzardMap(input)
    println(part1(map))
    println(part2(map))
}

private fun part1(map: BlizzardMap): Int {
    val initialMap = map[0]
    val startI = 0
    val startJ = initialMap[startI].indexOfFirst { it }
    val targetI = initialMap.lastIndex
    val targetJ = initialMap[targetI].indexOfFirst { it }

    return solve(
        map = map,
        startMinute = 0,
        startI = startI,
        startJ = startJ,
        targetI = targetI,
        targetJ = targetJ,
    )
}

private fun part2(map: BlizzardMap): Int {
    val initialMap = map[0]
    val startI = 0
    val startJ = initialMap[startI].indexOfFirst { it }
    val targetI = initialMap.lastIndex
    val targetJ = initialMap[targetI].indexOfFirst { it }

    val m1 = solve(
        map = map,
        startMinute = 0,
        startI = startI,
        startJ = startJ,
        targetI = targetI,
        targetJ = targetJ,
    )

    val m2 = solve(
        map = map,
        startMinute = m1,
        startI = targetI,
        startJ = targetJ,
        targetI = startI,
        targetJ = startJ,
    )

    val m3 = solve(
        map = map,
        startMinute = m2,
        startI = startI,
        startJ = startJ,
        targetI = targetI,
        targetJ = targetJ,
    )

    return m3
}

private fun solve(
    map: BlizzardMap,
    startMinute: Int,
    startI: Int,
    startJ: Int,
    targetI: Int,
    targetJ: Int
): Int {
    val queue = PriorityQueue<Item>()
    queue.offer(Item(startMinute, IJ(startI, startJ)))

    val visited = mutableSetOf<Int>()

    while (queue.isNotEmpty()) {
        val (minute, ij) = queue.poll()
        val (i, j) = ij

        val key = minute * 1_000_000 + i * 1_000 + j
        if (key in visited) {
            continue
        }
        visited.add(key)

        if (i == targetI && j == targetJ) {
            return minute
        }

        val currentMap = map[minute + 1]

        if (currentMap[i][j]) {
            queue.offer(Item(minute + 1, IJ(i, j)))
        }

        if (i > 0 && currentMap[i - 1][j]) {
            queue.offer(Item(minute + 1, IJ(i - 1, j)))
        }
        if (i < currentMap.lastIndex && currentMap[i + 1][j]) {
            queue.offer(Item(minute + 1, IJ(i + 1, j)))
        }
        if (j > 0 && currentMap[i][j - 1]) {
            queue.offer(Item(minute + 1, IJ(i, j - 1)))
        }
        if (j < currentMap[i].lastIndex && currentMap[i][j + 1]) {
            queue.offer(Item(minute + 1, IJ(i, j + 1)))
        }
    }

    error("Path not found")
}

private class BlizzardMap(initialState: List<String>) {
    private val cache = mutableListOf<BooleanMatrix>()
    private val template: BooleanMatrix
    private val blizzards: List<Blizzard>

    init {
        blizzards = buildList {
            initialState.forEachIndexed { i, row ->
                row.forEachIndexed { j, ch ->
                    when (ch) {
                        '>' -> add(Blizzard(MutableIJ(i, j), BlizzardDirection.RIGHT))
                        'v' -> add(Blizzard(MutableIJ(i, j), BlizzardDirection.DOWN))
                        '<' -> add(Blizzard(MutableIJ(i, j), BlizzardDirection.LEFT))
                        '^' -> add(Blizzard(MutableIJ(i, j), BlizzardDirection.UP))
                    }
                }
            }
        }

        template = Array(initialState.size) { i ->
            BooleanArray(initialState[i].length) { j ->
                initialState[i][j] != '#'
            }
        }

        //generate default map
        generateNextMap()
    }

    operator fun get(i: Int): BooleanMatrix {
        while (cache.lastIndex < i) {
            generateNextMap()
        }

        return cache[i]
    }

    private fun generateNextMap() {
        val next = template.deepCopyOf()

        blizzards.forEach {
            with(it) {
                next[position.i][position.j] = false

                //Also, move blizzard to the new position
                when (direction) {
                    BlizzardDirection.RIGHT -> position.j = if (position.j < (template[0].lastIndex - 1)) {
                        position.j + 1
                    } else {
                        1
                    }
                    BlizzardDirection.DOWN -> position.i = if (position.i < (template.lastIndex - 1)) {
                        position.i + 1
                    } else {
                        1
                    }
                    BlizzardDirection.LEFT -> position.j = if (position.j > 1) {
                        position.j - 1
                    } else {
                        template[0].lastIndex - 1
                    }
                    BlizzardDirection.UP -> position.i = if (position.i > 1) {
                        position.i - 1
                    } else {
                        template.lastIndex - 1
                    }
                }
            }
        }

        cache.add(next)
    }
}

private enum class BlizzardDirection { RIGHT, DOWN, LEFT, UP }

private class Blizzard(
    val position: MutableIJ,
    val direction: BlizzardDirection,
)

Compiled from "Day24.kt"
public final class Day24Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String Day24_test
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: new           #16                 // class BlizzardMap
       9: dup
      10: aload_0
      11: invokespecial #20                 // Method BlizzardMap."<init>":(Ljava/util/List;)V
      14: astore_1
      15: aload_1
      16: invokestatic  #24                 // Method part1:(LBlizzardMap;)I
      19: bipush        18
      21: if_icmpne     28
      24: iconst_1
      25: goto          29
      28: iconst_0
      29: ifne          42
      32: new           #26                 // class java/lang/IllegalStateException
      35: dup
      36: ldc           #28                 // String Check failed.
      38: invokespecial #31                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      41: athrow
      42: aload_1
      43: invokestatic  #34                 // Method part2:(LBlizzardMap;)I
      46: bipush        54
      48: if_icmpne     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 #31                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      68: athrow
      69: ldc           #36                 // String Day24
      71: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      74: astore_2
      75: new           #16                 // class BlizzardMap
      78: dup
      79: aload_2
      80: invokespecial #20                 // Method BlizzardMap."<init>":(Ljava/util/List;)V
      83: astore_3
      84: aload_3
      85: invokestatic  #24                 // Method part1:(LBlizzardMap;)I
      88: istore        4
      90: getstatic     #42                 // Field java/lang/System.out:Ljava/io/PrintStream;
      93: iload         4
      95: invokevirtual #48                 // Method java/io/PrintStream.println:(I)V
      98: aload_3
      99: invokestatic  #34                 // Method part2:(LBlizzardMap;)I
     102: istore        4
     104: getstatic     #42                 // Field java/lang/System.out:Ljava/io/PrintStream;
     107: iload         4
     109: invokevirtual #48                 // Method java/io/PrintStream.println:(I)V
     112: return

  private static final int part1(BlizzardMap);
    Code:
       0: aload_0
       1: iconst_0
       2: invokevirtual #60                 // Method BlizzardMap.get:(I)[[Z
       5: astore_1
       6: iconst_0
       7: istore_2
       8: aload_1
       9: iload_2
      10: aaload
      11: astore        4
      13: iconst_0
      14: istore        5
      16: iconst_0
      17: istore        6
      19: aload         4
      21: arraylength
      22: istore        7
      24: iload         6
      26: iload         7
      28: if_icmpge     57
      31: aload         4
      33: iload         6
      35: baload
      36: istore        8
      38: iconst_0
      39: istore        9
      41: iload         8
      43: ifeq          51
      46: iload         6
      48: goto          58
      51: iinc          6, 1
      54: goto          24
      57: iconst_m1
      58: istore_3
      59: aload_1
      60: checkcast     #62                 // class "[Ljava/lang/Object;"
      63: invokestatic  #68                 // Method kotlin/collections/ArraysKt.getLastIndex:([Ljava/lang/Object;)I
      66: istore        4
      68: aload_1
      69: iload         4
      71: aaload
      72: astore        6
      74: iconst_0
      75: istore        7
      77: iconst_0
      78: istore        8
      80: aload         6
      82: arraylength
      83: istore        9
      85: iload         8
      87: iload         9
      89: if_icmpge     118
      92: aload         6
      94: iload         8
      96: baload
      97: istore        10
      99: iconst_0
     100: istore        11
     102: iload         10
     104: ifeq          112
     107: iload         8
     109: goto          119
     112: iinc          8, 1
     115: goto          85
     118: iconst_m1
     119: istore        5
     121: aload_0
     122: iconst_0
     123: iload_2
     124: iload_3
     125: iload         4
     127: iload         5
     129: invokestatic  #72                 // Method solve:(LBlizzardMap;IIIII)I
     132: ireturn

  private static final int part2(BlizzardMap);
    Code:
       0: aload_0
       1: iconst_0
       2: invokevirtual #60                 // Method BlizzardMap.get:(I)[[Z
       5: astore_1
       6: iconst_0
       7: istore_2
       8: aload_1
       9: iload_2
      10: aaload
      11: astore        4
      13: iconst_0
      14: istore        5
      16: iconst_0
      17: istore        6
      19: aload         4
      21: arraylength
      22: istore        7
      24: iload         6
      26: iload         7
      28: if_icmpge     57
      31: aload         4
      33: iload         6
      35: baload
      36: istore        8
      38: iconst_0
      39: istore        9
      41: iload         8
      43: ifeq          51
      46: iload         6
      48: goto          58
      51: iinc          6, 1
      54: goto          24
      57: iconst_m1
      58: istore_3
      59: aload_1
      60: checkcast     #62                 // class "[Ljava/lang/Object;"
      63: invokestatic  #68                 // Method kotlin/collections/ArraysKt.getLastIndex:([Ljava/lang/Object;)I
      66: istore        4
      68: aload_1
      69: iload         4
      71: aaload
      72: astore        6
      74: iconst_0
      75: istore        7
      77: iconst_0
      78: istore        8
      80: aload         6
      82: arraylength
      83: istore        9
      85: iload         8
      87: iload         9
      89: if_icmpge     118
      92: aload         6
      94: iload         8
      96: baload
      97: istore        10
      99: iconst_0
     100: istore        11
     102: iload         10
     104: ifeq          112
     107: iload         8
     109: goto          119
     112: iinc          8, 1
     115: goto          85
     118: iconst_m1
     119: istore        5
     121: aload_0
     122: iconst_0
     123: iload_2
     124: iload_3
     125: iload         4
     127: iload         5
     129: invokestatic  #72                 // Method solve:(LBlizzardMap;IIIII)I
     132: istore        6
     134: aload_0
     135: iload         6
     137: iload         4
     139: iload         5
     141: iload_2
     142: iload_3
     143: invokestatic  #72                 // Method solve:(LBlizzardMap;IIIII)I
     146: istore        7
     148: aload_0
     149: iload         7
     151: iload_2
     152: iload_3
     153: iload         4
     155: iload         5
     157: invokestatic  #72                 // Method solve:(LBlizzardMap;IIIII)I
     160: istore        8
     162: iload         8
     164: ireturn

  private static final int solve(BlizzardMap, int, int, int, int, int);
    Code:
       0: new           #96                 // class java/util/PriorityQueue
       3: dup
       4: invokespecial #98                 // Method java/util/PriorityQueue."<init>":()V
       7: astore        6
       9: aload         6
      11: new           #100                // class Item
      14: dup
      15: iload_1
      16: new           #102                // class IJ
      19: dup
      20: iload_2
      21: iload_3
      22: invokespecial #105                // Method IJ."<init>":(II)V
      25: invokespecial #108                // Method Item."<init>":(ILIJ;)V
      28: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
      31: pop
      32: new           #114                // class java/util/LinkedHashSet
      35: dup
      36: invokespecial #115                // Method java/util/LinkedHashSet."<init>":()V
      39: checkcast     #117                // class java/util/Set
      42: astore        7
      44: aload         6
      46: checkcast     #119                // class java/util/Collection
      49: invokeinterface #123,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      54: ifne          61
      57: iconst_1
      58: goto          62
      61: iconst_0
      62: ifeq          428
      65: aload         6
      67: invokevirtual #127                // Method java/util/PriorityQueue.poll:()Ljava/lang/Object;
      70: checkcast     #100                // class Item
      73: astore        8
      75: aload         8
      77: invokevirtual #131                // Method Item.component1:()I
      80: istore        9
      82: aload         8
      84: invokevirtual #135                // Method Item.component2:()LIJ;
      87: astore        10
      89: aload         10
      91: invokevirtual #136                // Method IJ.component1:()I
      94: istore        11
      96: aload         10
      98: invokevirtual #138                // Method IJ.component2:()I
     101: istore        12
     103: iload         9
     105: ldc           #139                // int 1000000
     107: imul
     108: iload         11
     110: sipush        1000
     113: imul
     114: iadd
     115: iload         12
     117: iadd
     118: istore        13
     120: aload         7
     122: iload         13
     124: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     127: invokeinterface #148,  2          // InterfaceMethod java/util/Set.contains:(Ljava/lang/Object;)Z
     132: ifeq          138
     135: goto          44
     138: aload         7
     140: iload         13
     142: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     145: invokeinterface #151,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
     150: pop
     151: iload         11
     153: iload         4
     155: if_icmpne     168
     158: iload         12
     160: iload         5
     162: if_icmpne     168
     165: iload         9
     167: ireturn
     168: aload_0
     169: iload         9
     171: iconst_1
     172: iadd
     173: invokevirtual #60                 // Method BlizzardMap.get:(I)[[Z
     176: astore        14
     178: aload         14
     180: iload         11
     182: aaload
     183: iload         12
     185: baload
     186: ifeq          217
     189: aload         6
     191: new           #100                // class Item
     194: dup
     195: iload         9
     197: iconst_1
     198: iadd
     199: new           #102                // class IJ
     202: dup
     203: iload         11
     205: iload         12
     207: invokespecial #105                // Method IJ."<init>":(II)V
     210: invokespecial #108                // Method Item."<init>":(ILIJ;)V
     213: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
     216: pop
     217: iload         11
     219: ifle          265
     222: aload         14
     224: iload         11
     226: iconst_1
     227: isub
     228: aaload
     229: iload         12
     231: baload
     232: ifeq          265
     235: aload         6
     237: new           #100                // class Item
     240: dup
     241: iload         9
     243: iconst_1
     244: iadd
     245: new           #102                // class IJ
     248: dup
     249: iload         11
     251: iconst_1
     252: isub
     253: iload         12
     255: invokespecial #105                // Method IJ."<init>":(II)V
     258: invokespecial #108                // Method Item."<init>":(ILIJ;)V
     261: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
     264: pop
     265: iload         11
     267: aload         14
     269: checkcast     #62                 // class "[Ljava/lang/Object;"
     272: invokestatic  #68                 // Method kotlin/collections/ArraysKt.getLastIndex:([Ljava/lang/Object;)I
     275: if_icmpge     321
     278: aload         14
     280: iload         11
     282: iconst_1
     283: iadd
     284: aaload
     285: iload         12
     287: baload
     288: ifeq          321
     291: aload         6
     293: new           #100                // class Item
     296: dup
     297: iload         9
     299: iconst_1
     300: iadd
     301: new           #102                // class IJ
     304: dup
     305: iload         11
     307: iconst_1
     308: iadd
     309: iload         12
     311: invokespecial #105                // Method IJ."<init>":(II)V
     314: invokespecial #108                // Method Item."<init>":(ILIJ;)V
     317: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
     320: pop
     321: iload         12
     323: ifle          369
     326: aload         14
     328: iload         11
     330: aaload
     331: iload         12
     333: iconst_1
     334: isub
     335: baload
     336: ifeq          369
     339: aload         6
     341: new           #100                // class Item
     344: dup
     345: iload         9
     347: iconst_1
     348: iadd
     349: new           #102                // class IJ
     352: dup
     353: iload         11
     355: iload         12
     357: iconst_1
     358: isub
     359: invokespecial #105                // Method IJ."<init>":(II)V
     362: invokespecial #108                // Method Item."<init>":(ILIJ;)V
     365: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
     368: pop
     369: iload         12
     371: aload         14
     373: iload         11
     375: aaload
     376: invokestatic  #154                // Method kotlin/collections/ArraysKt.getLastIndex:([Z)I
     379: if_icmpge     44
     382: aload         14
     384: iload         11
     386: aaload
     387: iload         12
     389: iconst_1
     390: iadd
     391: baload
     392: ifeq          44
     395: aload         6
     397: new           #100                // class Item
     400: dup
     401: iload         9
     403: iconst_1
     404: iadd
     405: new           #102                // class IJ
     408: dup
     409: iload         11
     411: iload         12
     413: iconst_1
     414: iadd
     415: invokespecial #105                // Method IJ."<init>":(II)V
     418: invokespecial #108                // Method Item."<init>":(ILIJ;)V
     421: invokevirtual #112                // Method java/util/PriorityQueue.offer:(Ljava/lang/Object;)Z
     424: pop
     425: goto          44
     428: new           #26                 // class java/lang/IllegalStateException
     431: dup
     432: ldc           #156                // String Path not found
     434: invokevirtual #160                // Method java/lang/Object.toString:()Ljava/lang/String;
     437: invokespecial #31                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     440: athrow

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


import kotlin.math.abs
import kotlin.math.sign

fun main() {
    val testInput1 = readInput("Day09_test1")
    val testInput2 = readInput("Day09_test2")
    check(part1(testInput1) == 13)
    check(part2(testInput1) == 1)
    check(part2(testInput2) == 36)

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

private fun part1(input: List<String>): Int = solve(input, ropeSize = 2)
private fun part2(input: List<String>): Int = solve(input, ropeSize = 10)

private fun solve(input: List<String>, ropeSize: Int): Int {
    val rope = List(ropeSize) { MutableXY(0, 0) }
    val adjacentKnots = rope.windowed(2, 1)
    val head = rope.first()
    val tail = rope.last()
    val visitedCells = mutableSetOf<XY>()
    var dx = 0
    var dy = 0

    input.forEach { action ->
        val cnt = action.substringAfter(" ").toInt()
        when {
            action.startsWith("L") -> {
                dx = -1
                dy = 0
            }
            action.startsWith("R") -> {
                dx = 1
                dy = 0
            }
            action.startsWith("U") -> {
                dx = 0
                dy = 1
            }
            action.startsWith("D") -> {
                dx = 0
                dy = -1
            }
        }

        repeat(cnt) {
            head.x += dx
            head.y += dy

            adjacentKnots.forEach { (first, second) ->
                adjustKnotes(first, second)
            }

            visitedCells.add(tail.toXY())
        }
    }

    return visitedCells.size
}

private fun adjustKnotes(first: MutableXY, second: MutableXY) {
    if (abs(first.x - second.x) >= 2 || abs(first.y - second.y) >= 2) {
        second.x = second.x + 1 * (first.x - second.x).sign
        second.y = second.y + 1 * (first.y - second.y).sign
    }
}

Compiled from "Day09.kt"
public final class Day09Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String Day09_test1
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: ldc           #16                 // String Day09_test2
       8: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      11: astore_1
      12: aload_0
      13: invokestatic  #20                 // Method part1:(Ljava/util/List;)I
      16: bipush        13
      18: if_icmpne     25
      21: iconst_1
      22: goto          26
      25: iconst_0
      26: ifne          39
      29: new           #22                 // class java/lang/IllegalStateException
      32: dup
      33: ldc           #24                 // String Check failed.
      35: invokespecial #28                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      38: athrow
      39: aload_0
      40: invokestatic  #31                 // Method part2:(Ljava/util/List;)I
      43: iconst_1
      44: if_icmpne     51
      47: iconst_1
      48: goto          52
      51: iconst_0
      52: ifne          65
      55: new           #22                 // class java/lang/IllegalStateException
      58: dup
      59: ldc           #24                 // String Check failed.
      61: invokespecial #28                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      64: athrow
      65: aload_1
      66: invokestatic  #31                 // Method part2:(Ljava/util/List;)I
      69: bipush        36
      71: if_icmpne     78
      74: iconst_1
      75: goto          79
      78: iconst_0
      79: ifne          92
      82: new           #22                 // class java/lang/IllegalStateException
      85: dup
      86: ldc           #24                 // String Check failed.
      88: invokespecial #28                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      91: athrow
      92: ldc           #33                 // String Day09
      94: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
      97: astore_2
      98: aload_2
      99: invokestatic  #20                 // Method part1:(Ljava/util/List;)I
     102: istore_3
     103: getstatic     #39                 // Field java/lang/System.out:Ljava/io/PrintStream;
     106: iload_3
     107: invokevirtual #45                 // Method java/io/PrintStream.println:(I)V
     110: aload_2
     111: invokestatic  #31                 // Method part2:(Ljava/util/List;)I
     114: istore_3
     115: getstatic     #39                 // Field java/lang/System.out:Ljava/io/PrintStream;
     118: iload_3
     119: invokevirtual #45                 // Method java/io/PrintStream.println:(I)V
     122: return

  private static final int part1(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: iconst_2
       2: invokestatic  #56                 // Method solve:(Ljava/util/List;I)I
       5: ireturn

  private static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: bipush        10
       3: invokestatic  #56                 // Method solve:(Ljava/util/List;I)I
       6: ireturn

  private static final int solve(java.util.List<java.lang.String>, int);
    Code:
       0: new           #59                 // class java/util/ArrayList
       3: dup
       4: iload_1
       5: invokespecial #61                 // Method java/util/ArrayList."<init>":(I)V
       8: astore_3
       9: iconst_0
      10: istore        4
      12: iload         4
      14: iload_1
      15: if_icmpge     54
      18: iload         4
      20: istore        5
      22: aload_3
      23: iload         5
      25: istore        6
      27: astore        27
      29: iconst_0
      30: istore        7
      32: new           #63                 // class MutableXY
      35: dup
      36: iconst_0
      37: iconst_0
      38: invokespecial #66                 // Method MutableXY."<init>":(II)V
      41: aload         27
      43: swap
      44: invokevirtual #70                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      47: pop
      48: iinc          4, 1
      51: goto          12
      54: aload_3
      55: checkcast     #51                 // class java/util/List
      58: astore_2
      59: aload_2
      60: checkcast     #72                 // class java/lang/Iterable
      63: iconst_2
      64: iconst_1
      65: iconst_0
      66: iconst_4
      67: aconst_null
      68: invokestatic  #78                 // Method kotlin/collections/CollectionsKt.windowed$default:(Ljava/lang/Iterable;IIZILjava/lang/Object;)Ljava/util/List;
      71: astore_3
      72: aload_2
      73: invokestatic  #82                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      76: checkcast     #63                 // class MutableXY
      79: astore        4
      81: aload_2
      82: invokestatic  #85                 // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      85: checkcast     #63                 // class MutableXY
      88: astore        5
      90: new           #87                 // class java/util/LinkedHashSet
      93: dup
      94: invokespecial #89                 // Method java/util/LinkedHashSet."<init>":()V
      97: checkcast     #91                 // class java/util/Set
     100: astore        6
     102: iconst_0
     103: istore        7
     105: iconst_0
     106: istore        8
     108: aload_0
     109: checkcast     #72                 // class java/lang/Iterable
     112: astore        9
     114: iconst_0
     115: istore        10
     117: aload         9
     119: invokeinterface #95,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     124: astore        11
     126: aload         11
     128: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     133: ifeq          410
     136: aload         11
     138: invokeinterface #105,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     143: astore        12
     145: aload         12
     147: checkcast     #107                // class java/lang/String
     150: astore        13
     152: iconst_0
     153: istore        14
     155: aload         13
     157: ldc           #109                // String
     159: aconst_null
     160: iconst_2
     161: aconst_null
     162: invokestatic  #115                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     165: invokestatic  #121                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     168: istore        15
     170: nop
     171: aload         13
     173: ldc           #123                // String L
     175: iconst_0
     176: iconst_2
     177: aconst_null
     178: invokestatic  #127                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
     181: ifeq          193
     184: iconst_m1
     185: istore        7
     187: iconst_0
     188: istore        8
     190: goto          256
     193: aload         13
     195: ldc           #129                // String R
     197: iconst_0
     198: iconst_2
     199: aconst_null
     200: invokestatic  #127                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
     203: ifeq          215
     206: iconst_1
     207: istore        7
     209: iconst_0
     210: istore        8
     212: goto          256
     215: aload         13
     217: ldc           #131                // String U
     219: iconst_0
     220: iconst_2
     221: aconst_null
     222: invokestatic  #127                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
     225: ifeq          237
     228: iconst_0
     229: istore        7
     231: iconst_1
     232: istore        8
     234: goto          256
     237: aload         13
     239: ldc           #133                // String D
     241: iconst_0
     242: iconst_2
     243: aconst_null
     244: invokestatic  #127                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
     247: ifeq          256
     250: iconst_0
     251: istore        7
     253: iconst_m1
     254: istore        8
     256: iconst_0
     257: istore        16
     259: iload         16
     261: iload         15
     263: if_icmpge     405
     266: iload         16
     268: istore        17
     270: iconst_0
     271: istore        18
     273: aload         4
     275: aload         4
     277: invokevirtual #137                // Method MutableXY.getX:()I
     280: iload         7
     282: iadd
     283: invokevirtual #140                // Method MutableXY.setX:(I)V
     286: aload         4
     288: aload         4
     290: invokevirtual #143                // Method MutableXY.getY:()I
     293: iload         8
     295: iadd
     296: invokevirtual #146                // Method MutableXY.setY:(I)V
     299: aload_3
     300: checkcast     #72                 // class java/lang/Iterable
     303: astore        19
     305: iconst_0
     306: istore        20
     308: aload         19
     310: invokeinterface #95,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     315: astore        21
     317: aload         21
     319: invokeinterface #101,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     324: ifeq          384
     327: aload         21
     329: invokeinterface #105,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     334: astore        22
     336: aload         22
     338: checkcast     #51                 // class java/util/List
     341: astore        23
     343: iconst_0
     344: istore        24
     346: aload         23
     348: iconst_0
     349: invokeinterface #150,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     354: checkcast     #63                 // class MutableXY
     357: astore        25
     359: aload         23
     361: iconst_1
     362: invokeinterface #150,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     367: checkcast     #63                 // class MutableXY
     370: astore        26
     372: aload         25
     374: aload         26
     376: invokestatic  #154                // Method adjustKnotes:(LMutableXY;LMutableXY;)V
     379: nop
     380: nop
     381: goto          317
     384: nop
     385: aload         6
     387: aload         5
     389: invokevirtual #158                // Method MutableXY.toXY:()LXY;
     392: invokeinterface #159,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
     397: pop
     398: nop
     399: iinc          16, 1
     402: goto          259
     405: nop
     406: nop
     407: goto          126
     410: nop
     411: aload         6
     413: invokeinterface #162,  1          // InterfaceMethod java/util/Set.size:()I
     418: ireturn

  private static final void adjustKnotes(MutableXY, MutableXY);
    Code:
       0: aload_0
       1: invokevirtual #137                // Method MutableXY.getX:()I
       4: aload_1
       5: invokevirtual #137                // Method MutableXY.getX:()I
       8: isub
       9: invokestatic  #193                // Method java/lang/Math.abs:(I)I
      12: iconst_2
      13: if_icmpge     32
      16: aload_0
      17: invokevirtual #143                // Method MutableXY.getY:()I
      20: aload_1
      21: invokevirtual #143                // Method MutableXY.getY:()I
      24: isub
      25: invokestatic  #193                // Method java/lang/Math.abs:(I)I
      28: iconst_2
      29: if_icmplt     78
      32: aload_1
      33: aload_1
      34: invokevirtual #137                // Method MutableXY.getX:()I
      37: iconst_1
      38: aload_0
      39: invokevirtual #137                // Method MutableXY.getX:()I
      42: aload_1
      43: invokevirtual #137                // Method MutableXY.getX:()I
      46: isub
      47: invokestatic  #198                // Method kotlin/math/MathKt.getSign:(I)I
      50: imul
      51: iadd
      52: invokevirtual #140                // Method MutableXY.setX:(I)V
      55: aload_1
      56: aload_1
      57: invokevirtual #143                // Method MutableXY.getY:()I
      60: iconst_1
      61: aload_0
      62: invokevirtual #143                // Method MutableXY.getY:()I
      65: aload_1
      66: invokevirtual #143                // Method MutableXY.getY:()I
      69: isub
      70: invokestatic  #198                // Method kotlin/math/MathKt.getSign:(I)I
      73: imul
      74: iadd
      75: invokevirtual #146                // Method MutableXY.setY:(I)V
      78: return

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


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

fun main() {
    val testInput = readInput("Day19_test")
    val testBlueprints = testInput.map(Blueprint.Companion::fromString)
    check(part1(testBlueprints) == 33)

    val input = readInput("Day19")
    val blueprints = input.map(Blueprint.Companion::fromString)
    println(part1(blueprints))
    println(part2(blueprints))
}

private fun part1(blueprints: List<Blueprint>): Int {
    return blueprints.sumOf {
        it.number * calculateMaxGeodes(it, 24)
    }
}

private fun part2(blueprints: List<Blueprint>): Int {
    return calculateMaxGeodes(blueprints[0], 32) *
            calculateMaxGeodes(blueprints[1], 32) *
            calculateMaxGeodes(blueprints[2], 32)
}

private fun calculateMaxGeodes(
    blueprint: Blueprint,
    minutesLeft: Int,
    memo: MutableMap<Long, Int> = mutableMapOf(),
    oreRobotsCount: Int = 1,
    clayRobotsCount: Int = 0,
    obsidianRobotsCount: Int = 0,
    geodesRobotsCount: Int = 0,
    oreCount: Int = 0,
    clayCount: Int = 0,
    obsidianCount: Int = 0,
    geodesCount: Int = 0,
): Int {
    if (minutesLeft == 0) {
        return geodesCount
    }

    //Throw out resources, which can't be potentially spend by the end of the minutesLeft.
    //This reduces a lot of recursive calls because it collapse overlapping states
    val oreForKey = min(oreCount, minutesLeft * blueprint.oreMax)
    val clayForKey = min(clayCount, minutesLeft * blueprint.clayMax)
    val obsidianForKey = min(obsidianCount, minutesLeft * blueprint.obsidianMax)

    val key = minutesLeft * 1_000_000_000_000_000_000L +
            oreRobotsCount * 10_000_000_000_000_000L +
            clayRobotsCount * 100_000_000_000_000L +
            obsidianRobotsCount * 1000_000_000_000L +
            geodesRobotsCount * 10_000_000_000L +
            oreForKey * 100_000_000L +
            clayForKey * 1_000_000L +
            obsidianForKey * 10_000L +
            geodesCount * 100L

    if (key in memo) {
        return memo.getValue(key)
    }

    var result = 0

    val canBuildOreRobot = oreCount >= blueprint.oreForOreRobot && oreRobotsCount < blueprint.oreMax
    val canBuildClayRobot = oreCount >= blueprint.oreForClayRobot && clayRobotsCount < blueprint.clayMax
    val canBuildObsidianRobot =
        oreCount >= blueprint.oreForObsidianRobot && clayCount >= blueprint.clayForObsidianRobot && obsidianCount <= blueprint.obsidianMax
    val canBuildGeodeRobot = oreCount >= blueprint.oreForGeodeRobot && obsidianCount >= blueprint.obsidianForGeodeRobot

    if (canBuildGeodeRobot) {
        result = max(
            result,
            calculateMaxGeodes(
                blueprint = blueprint,
                minutesLeft = minutesLeft - 1,
                memo = memo,
                oreRobotsCount = oreRobotsCount,
                clayRobotsCount = clayRobotsCount,
                obsidianRobotsCount = obsidianRobotsCount,
                geodesRobotsCount = geodesRobotsCount + 1,
                oreCount = oreCount + oreRobotsCount - blueprint.oreForGeodeRobot,
                clayCount = clayCount + clayRobotsCount,
                obsidianCount = obsidianCount + obsidianRobotsCount - blueprint.obsidianForGeodeRobot,
                geodesCount = geodesCount + geodesRobotsCount
            )
        )
    }

    if (canBuildObsidianRobot) {
        result = max(
            result,
            calculateMaxGeodes(
                blueprint = blueprint,
                minutesLeft = minutesLeft - 1,
                memo = memo,
                oreRobotsCount = oreRobotsCount,
                clayRobotsCount = clayRobotsCount,
                obsidianRobotsCount = obsidianRobotsCount + 1,
                geodesRobotsCount = geodesRobotsCount,
                oreCount = oreCount + oreRobotsCount - blueprint.oreForObsidianRobot,
                clayCount = clayCount + clayRobotsCount - blueprint.clayForObsidianRobot,
                obsidianCount = obsidianCount + obsidianRobotsCount,
                geodesCount = geodesCount + geodesRobotsCount
            )
        )
    }

    if (canBuildClayRobot) {
        result = max(
            result,
            calculateMaxGeodes(
                blueprint = blueprint,
                minutesLeft = minutesLeft - 1,
                memo = memo,
                oreRobotsCount = oreRobotsCount,
                clayRobotsCount = clayRobotsCount + 1,
                obsidianRobotsCount = obsidianRobotsCount,
                geodesRobotsCount = geodesRobotsCount,
                oreCount = oreCount + oreRobotsCount - blueprint.oreForClayRobot,
                clayCount = clayCount + clayRobotsCount,
                obsidianCount = obsidianCount + obsidianRobotsCount,
                geodesCount = geodesCount + geodesRobotsCount
            )
        )
    }

    if (canBuildOreRobot) {
        result = max(
            result,
            calculateMaxGeodes(
                blueprint = blueprint,
                minutesLeft = minutesLeft - 1,
                memo = memo,
                oreRobotsCount = oreRobotsCount + 1,
                clayRobotsCount = clayRobotsCount,
                obsidianRobotsCount = obsidianRobotsCount,
                geodesRobotsCount = geodesRobotsCount,
                oreCount = oreCount + oreRobotsCount - blueprint.oreForOreRobot,
                clayCount = clayCount + clayRobotsCount,
                obsidianCount = obsidianCount + obsidianRobotsCount,
                geodesCount = geodesCount + geodesRobotsCount
            )
        )
    }

    result = max(
        result,
        calculateMaxGeodes(
            blueprint = blueprint,
            minutesLeft = minutesLeft - 1,
            memo = memo,
            oreRobotsCount = oreRobotsCount,
            clayRobotsCount = clayRobotsCount,
            obsidianRobotsCount = obsidianRobotsCount,
            geodesRobotsCount = geodesRobotsCount,
            oreCount = oreCount + oreRobotsCount,
            clayCount = clayCount + clayRobotsCount,
            obsidianCount = obsidianCount + obsidianRobotsCount,
            geodesCount = geodesCount + geodesRobotsCount
        )
    )

    memo[key] = result

    return result
}

private val BLUEPRINT_FORMAT =
    Regex("Blueprint (\\d+): Each ore robot costs (\\d+) ore. Each clay robot costs (\\d+) ore. Each obsidian robot costs (\\d+) ore and (\\d+) clay. Each geode robot costs (\\d+) ore and (\\d+) obsidian.")

private class Blueprint(
    val number: Int,
    val oreForOreRobot: Int,
    val oreForClayRobot: Int,
    val oreForObsidianRobot: Int,
    val clayForObsidianRobot: Int,
    val oreForGeodeRobot: Int,
    val obsidianForGeodeRobot: Int,
) {
    val oreMax: Int by lazy { maxOf(oreForOreRobot, oreForClayRobot, oreForObsidianRobot, oreForGeodeRobot) }
    val clayMax: Int
        get() = clayForObsidianRobot
    val obsidianMax: Int
        get() = obsidianForGeodeRobot

    companion object {
        fun fromString(str: String): Blueprint {
            val match = BLUEPRINT_FORMAT.find(str)
            val (number, oreForOreRobot, oreForClayRobot, oreForObsidianRobot, clayForObsidianRobot, oreForGeodeRobot, obsidianForGeodeRobot) = requireNotNull(
                match
            ).destructured

            return Blueprint(
                number.toInt(),
                oreForOreRobot.toInt(),
                oreForClayRobot.toInt(),
                oreForObsidianRobot.toInt(),
                clayForObsidianRobot.toInt(),
                oreForGeodeRobot.toInt(),
                obsidianForGeodeRobot.toInt()
            )
        }
    }
}

Compiled from "Day19.kt"
public final class Day19Kt {
  private static final kotlin.text.Regex BLUEPRINT_FORMAT;

  public static final void main();
    Code:
       0: ldc           #8                  // String Day19_test
       2: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: checkcast     #16                 // class java/lang/Iterable
      10: astore_2
      11: getstatic     #22                 // Field Blueprint.Companion:LBlueprint$Companion;
      14: astore_3
      15: iconst_0
      16: istore        4
      18: aload_2
      19: astore        5
      21: new           #24                 // class java/util/ArrayList
      24: dup
      25: aload_2
      26: bipush        10
      28: invokestatic  #30                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      31: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
      34: checkcast     #36                 // class java/util/Collection
      37: astore        6
      39: iconst_0
      40: istore        7
      42: aload         5
      44: invokeinterface #40,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      49: astore        8
      51: aload         8
      53: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      58: ifeq          102
      61: aload         8
      63: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      68: astore        9
      70: aload         6
      72: aload         9
      74: checkcast     #52                 // class java/lang/String
      77: astore        10
      79: astore        14
      81: iconst_0
      82: istore        11
      84: aload_3
      85: aload         10
      87: invokevirtual #58                 // Method Blueprint$Companion.fromString:(Ljava/lang/String;)LBlueprint;
      90: aload         14
      92: swap
      93: invokeinterface #62,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      98: pop
      99: goto          51
     102: aload         6
     104: checkcast     #64                 // class java/util/List
     107: nop
     108: astore_1
     109: aload_1
     110: invokestatic  #68                 // Method part1:(Ljava/util/List;)I
     113: bipush        33
     115: if_icmpne     122
     118: iconst_1
     119: goto          123
     122: iconst_0
     123: ifne          136
     126: new           #70                 // class java/lang/IllegalStateException
     129: dup
     130: ldc           #72                 // String Check failed.
     132: invokespecial #75                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     135: athrow
     136: ldc           #77                 // String Day19
     138: invokestatic  #14                 // Method UtilsKt.readInput:(Ljava/lang/String;)Ljava/util/List;
     141: astore_2
     142: aload_2
     143: checkcast     #16                 // class java/lang/Iterable
     146: astore        4
     148: getstatic     #22                 // Field Blueprint.Companion:LBlueprint$Companion;
     151: astore        5
     153: iconst_0
     154: istore        6
     156: aload         4
     158: astore        7
     160: new           #24                 // class java/util/ArrayList
     163: dup
     164: aload         4
     166: bipush        10
     168: invokestatic  #30                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     171: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
     174: checkcast     #36                 // class java/util/Collection
     177: astore        8
     179: iconst_0
     180: istore        9
     182: aload         7
     184: invokeinterface #40,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     189: astore        10
     191: aload         10
     193: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     198: ifeq          243
     201: aload         10
     203: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     208: astore        11
     210: aload         8
     212: aload         11
     214: checkcast     #52                 // class java/lang/String
     217: astore        12
     219: astore        14
     221: iconst_0
     222: istore        13
     224: aload         5
     226: aload         12
     228: invokevirtual #58                 // Method Blueprint$Companion.fromString:(Ljava/lang/String;)LBlueprint;
     231: aload         14
     233: swap
     234: invokeinterface #62,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     239: pop
     240: goto          191
     243: aload         8
     245: checkcast     #64                 // class java/util/List
     248: nop
     249: astore_3
     250: aload_3
     251: invokestatic  #68                 // Method part1:(Ljava/util/List;)I
     254: istore        4
     256: getstatic     #83                 // Field java/lang/System.out:Ljava/io/PrintStream;
     259: iload         4
     261: invokevirtual #88                 // Method java/io/PrintStream.println:(I)V
     264: aload_3
     265: invokestatic  #91                 // Method part2:(Ljava/util/List;)I
     268: istore        4
     270: getstatic     #83                 // Field java/lang/System.out:Ljava/io/PrintStream;
     273: iload         4
     275: invokevirtual #88                 // Method java/io/PrintStream.println:(I)V
     278: return

  private static final int part1(java.util.List<Blueprint>);
    Code:
       0: aload_0
       1: checkcast     #16                 // class java/lang/Iterable
       4: astore_1
       5: iconst_0
       6: istore_2
       7: aload_1
       8: invokeinterface #40,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      13: astore_3
      14: aload_3
      15: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      20: ifeq          81
      23: aload_3
      24: invokeinterface #50,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      29: astore        4
      31: iload_2
      32: aload         4
      34: checkcast     #18                 // class Blueprint
      37: astore        5
      39: istore        7
      41: iconst_0
      42: istore        6
      44: aload         5
      46: invokevirtual #115                // Method Blueprint.getNumber:()I
      49: aload         5
      51: bipush        24
      53: aconst_null
      54: iconst_0
      55: iconst_0
      56: iconst_0
      57: iconst_0
      58: iconst_0
      59: iconst_0
      60: iconst_0
      61: iconst_0
      62: sipush        2044
      65: aconst_null
      66: invokestatic  #119                // Method calculateMaxGeodes$default:(LBlueprint;ILjava/util/Map;IIIIIIIIILjava/lang/Object;)I
      69: imul
      70: istore        8
      72: iload         7
      74: iload         8
      76: iadd
      77: istore_2
      78: goto          14
      81: iload_2
      82: ireturn

  private static final int part2(java.util.List<Blueprint>);
    Code:
       0: aload_0
       1: iconst_0
       2: invokeinterface #126,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
       7: checkcast     #18                 // class Blueprint
      10: bipush        32
      12: aconst_null
      13: iconst_0
      14: iconst_0
      15: iconst_0
      16: iconst_0
      17: iconst_0
      18: iconst_0
      19: iconst_0
      20: iconst_0
      21: sipush        2044
      24: aconst_null
      25: invokestatic  #119                // Method calculateMaxGeodes$default:(LBlueprint;ILjava/util/Map;IIIIIIIIILjava/lang/Object;)I
      28: aload_0
      29: iconst_1
      30: invokeinterface #126,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      35: checkcast     #18                 // class Blueprint
      38: bipush        32
      40: aconst_null
      41: iconst_0
      42: iconst_0
      43: iconst_0
      44: iconst_0
      45: iconst_0
      46: iconst_0
      47: iconst_0
      48: iconst_0
      49: sipush        2044
      52: aconst_null
      53: invokestatic  #119                // Method calculateMaxGeodes$default:(LBlueprint;ILjava/util/Map;IIIIIIIIILjava/lang/Object;)I
      56: imul
      57: aload_0
      58: iconst_2
      59: invokeinterface #126,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      64: checkcast     #18                 // class Blueprint
      67: bipush        32
      69: aconst_null
      70: iconst_0
      71: iconst_0
      72: iconst_0
      73: iconst_0
      74: iconst_0
      75: iconst_0
      76: iconst_0
      77: iconst_0
      78: sipush        2044
      81: aconst_null
      82: invokestatic  #119                // Method calculateMaxGeodes$default:(LBlueprint;ILjava/util/Map;IIIIIIIIILjava/lang/Object;)I
      85: imul
      86: ireturn

  private static final int calculateMaxGeodes(Blueprint, int, java.util.Map<java.lang.Long, java.lang.Integer>, int, int, int, int, int, int, int, int);
    Code:
       0: iload_1
       1: ifne          7
       4: iload         10
       6: ireturn
       7: iload         7
       9: iload_1
      10: aload_0
      11: invokevirtual #132                // Method Blueprint.getOreMax:()I
      14: imul
      15: invokestatic  #138                // Method java/lang/Math.min:(II)I
      18: istore        11
      20: iload         8
      22: iload_1
      23: aload_0
      24: invokevirtual #141                // Method Blueprint.getClayMax:()I
      27: imul
      28: invokestatic  #138                // Method java/lang/Math.min:(II)I
      31: istore        12
      33: iload         9
      35: iload_1
      36: aload_0
      37: invokevirtual #144                // Method Blueprint.getObsidianMax:()I
      40: imul
      41: invokestatic  #138                // Method java/lang/Math.min:(II)I
      44: istore        13
      46: iload_1
      47: i2l
      48: ldc2_w        #145                // long 1000000000000000000l
      51: lmul
      52: iload_3
      53: i2l
      54: ldc2_w        #147                // long 10000000000000000l
      57: lmul
      58: ladd
      59: iload         4
      61: i2l
      62: ldc2_w        #149                // long 100000000000000l
      65: lmul
      66: ladd
      67: iload         5
      69: i2l
      70: ldc2_w        #151                // long 1000000000000l
      73: lmul
      74: ladd
      75: iload         6
      77: i2l
      78: ldc2_w        #153                // long 10000000000l
      81: lmul
      82: ladd
      83: iload         11
      85: i2l
      86: ldc2_w        #155                // long 100000000l
      89: lmul
      90: ladd
      91: iload         12
      93: i2l
      94: ldc2_w        #157                // long 1000000l
      97: lmul
      98: ladd
      99: iload         13
     101: i2l
     102: ldc2_w        #159                // long 10000l
     105: lmul
     106: ladd
     107: iload         10
     109: i2l
     110: ldc2_w        #161                // long 100l
     113: lmul
     114: ladd
     115: lstore        14
     117: lload         14
     119: invokestatic  #168                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     122: aload_2
     123: swap
     124: invokeinterface #173,  2          // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
     129: ifeq          148
     132: aload_2
     133: lload         14
     135: invokestatic  #168                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     138: invokestatic  #179                // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
     141: checkcast     #181                // class java/lang/Number
     144: invokevirtual #184                // Method java/lang/Number.intValue:()I
     147: ireturn
     148: iconst_0
     149: istore        16
     151: iload         7
     153: aload_0
     154: invokevirtual #187                // Method Blueprint.getOreForOreRobot:()I
     157: if_icmplt     172
     160: iload_3
     161: aload_0
     162: invokevirtual #132                // Method Blueprint.getOreMax:()I
     165: if_icmpge     172
     168: iconst_1
     169: goto          173
     172: iconst_0
     173: istore        17
     175: iload         7
     177: aload_0
     178: invokevirtual #190                // Method Blueprint.getOreForClayRobot:()I
     181: if_icmplt     197
     184: iload         4
     186: aload_0
     187: invokevirtual #141                // Method Blueprint.getClayMax:()I
     190: if_icmpge     197
     193: iconst_1
     194: goto          198
     197: iconst_0
     198: istore        18
     200: iload         7
     202: aload_0
     203: invokevirtual #193                // Method Blueprint.getOreForObsidianRobot:()I
     206: if_icmplt     231
     209: iload         8
     211: aload_0
     212: invokevirtual #196                // Method Blueprint.getClayForObsidianRobot:()I
     215: if_icmplt     231
     218: iload         9
     220: aload_0
     221: invokevirtual #144                // Method Blueprint.getObsidianMax:()I
     224: if_icmpgt     231
     227: iconst_1
     228: goto          232
     231: iconst_0
     232: istore        19
     234: iload         7
     236: aload_0
     237: invokevirtual #199                // Method Blueprint.getOreForGeodeRobot:()I
     240: if_icmplt     256
     243: iload         9
     245: aload_0
     246: invokevirtual #202                // Method Blueprint.getObsidianForGeodeRobot:()I
     249: if_icmplt     256
     252: iconst_1
     253: goto          257
     256: iconst_0
     257: istore        20
     259: iload         20
     261: ifeq          317
     264: iload         16
     266: aload_0
     267: iload_1
     268: iconst_1
     269: isub
     270: aload_2
     271: iload_3
     272: iload         4
     274: iload         5
     276: iload         6
     278: iconst_1
     279: iadd
     280: iload         7
     282: iload_3
     283: iadd
     284: aload_0
     285: invokevirtual #199                // Method Blueprint.getOreForGeodeRobot:()I
     288: isub
     289: iload         8
     291: iload         4
     293: iadd
     294: iload         9
     296: iload         5
     298: iadd
     299: aload_0
     300: invokevirtual #202                // Method Blueprint.getObsidianForGeodeRobot:()I
     303: isub
     304: iload         10
     306: iload         6
     308: iadd
     309: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     312: invokestatic  #207                // Method java/lang/Math.max:(II)I
     315: istore        16
     317: iload         19
     319: ifeq          375
     322: iload         16
     324: aload_0
     325: iload_1
     326: iconst_1
     327: isub
     328: aload_2
     329: iload_3
     330: iload         4
     332: iload         5
     334: iconst_1
     335: iadd
     336: iload         6
     338: iload         7
     340: iload_3
     341: iadd
     342: aload_0
     343: invokevirtual #193                // Method Blueprint.getOreForObsidianRobot:()I
     346: isub
     347: iload         8
     349: iload         4
     351: iadd
     352: aload_0
     353: invokevirtual #196                // Method Blueprint.getClayForObsidianRobot:()I
     356: isub
     357: iload         9
     359: iload         5
     361: iadd
     362: iload         10
     364: iload         6
     366: iadd
     367: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     370: invokestatic  #207                // Method java/lang/Math.max:(II)I
     373: istore        16
     375: iload         18
     377: ifeq          428
     380: iload         16
     382: aload_0
     383: iload_1
     384: iconst_1
     385: isub
     386: aload_2
     387: iload_3
     388: iload         4
     390: iconst_1
     391: iadd
     392: iload         5
     394: iload         6
     396: iload         7
     398: iload_3
     399: iadd
     400: aload_0
     401: invokevirtual #190                // Method Blueprint.getOreForClayRobot:()I
     404: isub
     405: iload         8
     407: iload         4
     409: iadd
     410: iload         9
     412: iload         5
     414: iadd
     415: iload         10
     417: iload         6
     419: iadd
     420: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     423: invokestatic  #207                // Method java/lang/Math.max:(II)I
     426: istore        16
     428: iload         17
     430: ifeq          481
     433: iload         16
     435: aload_0
     436: iload_1
     437: iconst_1
     438: isub
     439: aload_2
     440: iload_3
     441: iconst_1
     442: iadd
     443: iload         4
     445: iload         5
     447: iload         6
     449: iload         7
     451: iload_3
     452: iadd
     453: aload_0
     454: invokevirtual #187                // Method Blueprint.getOreForOreRobot:()I
     457: isub
     458: iload         8
     460: iload         4
     462: iadd
     463: iload         9
     465: iload         5
     467: iadd
     468: iload         10
     470: iload         6
     472: iadd
     473: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     476: invokestatic  #207                // Method java/lang/Math.max:(II)I
     479: istore        16
     481: iload         16
     483: aload_0
     484: iload_1
     485: iconst_1
     486: isub
     487: aload_2
     488: iload_3
     489: iload         4
     491: iload         5
     493: iload         6
     495: iload         7
     497: iload_3
     498: iadd
     499: iload         8
     501: iload         4
     503: iadd
     504: iload         9
     506: iload         5
     508: iadd
     509: iload         10
     511: iload         6
     513: iadd
     514: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     517: invokestatic  #207                // Method java/lang/Math.max:(II)I
     520: istore        16
     522: lload         14
     524: invokestatic  #168                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     527: astore        21
     529: iload         16
     531: invokestatic  #212                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     534: astore        22
     536: aload_2
     537: aload         21
     539: aload         22
     541: invokeinterface #216,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     546: pop
     547: iload         16
     549: ireturn

  static int calculateMaxGeodes$default(Blueprint, int, java.util.Map, int, int, int, int, int, int, int, int, int, java.lang.Object);
    Code:
       0: iload         11
       2: iconst_4
       3: iand
       4: ifeq          18
       7: new           #241                // class java/util/LinkedHashMap
      10: dup
      11: invokespecial #243                // Method java/util/LinkedHashMap."<init>":()V
      14: checkcast     #170                // class java/util/Map
      17: astore_2
      18: iload         11
      20: bipush        8
      22: iand
      23: ifeq          28
      26: iconst_1
      27: istore_3
      28: iload         11
      30: bipush        16
      32: iand
      33: ifeq          39
      36: iconst_0
      37: istore        4
      39: iload         11
      41: bipush        32
      43: iand
      44: ifeq          50
      47: iconst_0
      48: istore        5
      50: iload         11
      52: bipush        64
      54: iand
      55: ifeq          61
      58: iconst_0
      59: istore        6
      61: iload         11
      63: sipush        128
      66: iand
      67: ifeq          73
      70: iconst_0
      71: istore        7
      73: iload         11
      75: sipush        256
      78: iand
      79: ifeq          85
      82: iconst_0
      83: istore        8
      85: iload         11
      87: sipush        512
      90: iand
      91: ifeq          97
      94: iconst_0
      95: istore        9
      97: iload         11
      99: sipush        1024
     102: iand
     103: ifeq          109
     106: iconst_0
     107: istore        10
     109: aload_0
     110: iload_1
     111: aload_2
     112: iload_3
     113: iload         4
     115: iload         5
     117: iload         6
     119: iload         7
     121: iload         8
     123: iload         9
     125: iload         10
     127: invokestatic  #204                // Method calculateMaxGeodes:(LBlueprint;ILjava/util/Map;IIIIIIII)I
     130: ireturn

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

  public static final kotlin.text.Regex access$getBLUEPRINT_FORMAT$p();
    Code:
       0: getstatic     #254                // Field BLUEPRINT_FORMAT:Lkotlin/text/Regex;
       3: areturn

  static {};
    Code:
       0: new           #257                // class kotlin/text/Regex
       3: dup
       4: ldc_w         #259                // String Blueprint (\\d+): Each ore robot costs (\\d+) ore. Each clay robot costs (\\d+) ore. Each obsidian robot costs (\\d+) ore and (\\d+) clay. Each geode robot costs (\\d+) ore and (\\d+) obsidian.
       7: invokespecial #260                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      10: putstatic     #254                // Field BLUEPRINT_FORMAT:Lkotlin/text/Regex;
      13: return
}


import kotlin.math.max

fun main() {
    val testInput = readInput("Day18_test")
    check(part1(testInput) == 64)
    check(part2(testInput) == 58)

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

private fun part1(input: List<String>): Int {
    val cubes = input.to3DMatrix()

    return solve(input, cubes)
}

private fun part2(input: List<String>): Int {
    val cubes = input.to3DMatrix()
    val water = fillWithWater(cubes)

    return solve(input, water)
}

private fun solve(input: List<String>, emptyCubes: Boolean3DMatrix): Int {
    return input.sumOf {
        var cnt = 0

        val (xStr,yStr,zStr) = it.split(",")
        val x = xStr.toInt()
        val y = yStr.toInt()
        val z = zStr.toInt()

        if (emptyCubes.isEmpty(x + 1, y, z)) cnt++
        if (emptyCubes.isEmpty(x - 1, y, z)) cnt++
        if (emptyCubes.isEmpty(x, y + 1, z)) cnt++
        if (emptyCubes.isEmpty(x, y - 1, z)) cnt++
        if (emptyCubes.isEmpty(x, y, z + 1)) cnt++
        if (emptyCubes.isEmpty(x, y, z - 1)) cnt++

        cnt
    }
}

private fun List<String>.to3DMatrix(): Boolean3DMatrix {
    var xMax = 0
    var yMax = 0
    var zMax = 0

    this.forEach {
        val (x,y,z) = it.split(",")
        xMax = max(xMax, x.toInt())
        yMax = max(yMax, y.toInt())
        zMax = max(zMax, z.toInt())
    }

    val result = Array(xMax + 1) {
        Array(yMax + 1) {
            BooleanArray(zMax + 1)
        }
    }

    this.forEach {
        val (x, y, z) = it.split(",")
        result[x.toInt()][y.toInt()][z.toInt()] = true
    }

    return result
}

private fun fillWithWater(cubes: Boolean3DMatrix): Boolean3DMatrix {
    val result = Array(cubes.size) {
        Array(cubes[0].size) {
            BooleanArray(cubes[0][0].size) { true }
        }
    }

    val xLastIndex = cubes.lastIndex
    val yLastIndex = cubes[0].lastIndex
    val zLastIndex = cubes[0][0].lastIndex

    for (x in cubes.indices) {
        for (y in cubes[0].indices) {
            fill(cubes, result, x, y, 0)
            fill(cubes, result, x, y, zLastIndex)
        }
    }

    for (x in cubes.indices) {
        for (z in cubes[0][0].indices) {
            fill(cubes, result, x, 0, z)
            fill(cubes, result, x, yLastIndex, z)
        }
    }
    for (y in cubes[0].indices) {
        for (z in cubes[0][0].indices) {
            fill(cubes, result, 0, y, z)
            fill(cubes, result, xLastIndex, y, z)
        }
    }

    return result
}

private fun fill(cubes: Boolean3DMatrix, water: Boolean3DMatrix, x: Int, y: Int, z: Int) {
    if (!water.isXYZInside(x, y, z) || cubes[x][y][z] || !water[x][y][z]) {
        return
    }

    water[x][y][z] = false
    fill(cubes, water, x + 1, y, z)
    fill(cubes, water, x - 1, y, z)
    fill(cubes, water, x, y + 1, z)
    fill(cubes, water, x, y - 1, z)
    fill(cubes, water, x, y, z + 1)
    fill(cubes, water, x, y, z - 1)
}

private fun Boolean3DMatrix.isEmpty(x: Int, y: Int, z: Int): Boolean {
    return if (this.isXYZInside(x, y, z)) {
        !this[x][y][z]
    } else {
        true
    }
}

private fun Boolean3DMatrix.isXYZInside(x: Int, y: Int, z: Int): Boolean {
    return (x in this.indices && y in this[x].indices && z in this[x][y].indices)
}

Compiled from "Day18.kt"
public final class Day18Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String Day18_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        64
      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        58
      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 Day18
      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: aload_0
       1: invokestatic  #53                 // Method to3DMatrix:(Ljava/util/List;)[[[Z
       4: astore_1
       5: aload_0
       6: aload_1
       7: invokestatic  #57                 // Method solve:(Ljava/util/List;[[[Z)I
      10: ireturn

  private static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: invokestatic  #53                 // Method to3DMatrix:(Ljava/util/List;)[[[Z
       4: astore_1
       5: aload_1
       6: invokestatic  #63                 // Method fillWithWater:([[[Z)[[[Z
       9: astore_2
      10: aload_0
      11: aload_2
      12: invokestatic  #57                 // Method solve:(Ljava/util/List;[[[Z)I
      15: ireturn

  private static final int solve(java.util.List<java.lang.String>, boolean[][][]);
    Code:
       0: aload_0
       1: checkcast     #67                 // class java/lang/Iterable
       4: astore_2
       5: iconst_0
       6: istore_3
       7: aload_2
       8: invokeinterface #71,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      13: astore        4
      15: aload         4
      17: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      22: ifeq          260
      25: aload         4
      27: invokeinterface #81,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      32: astore        5
      34: iload_3
      35: aload         5
      37: checkcast     #83                 // class java/lang/String
      40: astore        6
      42: istore        16
      44: iconst_0
      45: istore        7
      47: iconst_0
      48: istore        8
      50: aload         6
      52: checkcast     #85                 // class java/lang/CharSequence
      55: iconst_1
      56: anewarray     #83                 // class java/lang/String
      59: astore        9
      61: aload         9
      63: iconst_0
      64: ldc           #87                 // String ,
      66: aastore
      67: aload         9
      69: iconst_0
      70: iconst_0
      71: bipush        6
      73: aconst_null
      74: invokestatic  #93                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      77: astore        10
      79: aload         10
      81: iconst_0
      82: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      87: checkcast     #83                 // class java/lang/String
      90: astore        9
      92: aload         10
      94: iconst_1
      95: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     100: checkcast     #83                 // class java/lang/String
     103: astore        11
     105: aload         10
     107: iconst_2
     108: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     113: checkcast     #83                 // class java/lang/String
     116: astore        12
     118: aload         9
     120: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     123: istore        13
     125: aload         11
     127: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     130: istore        14
     132: aload         12
     134: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     137: istore        15
     139: aload_1
     140: iload         13
     142: iconst_1
     143: iadd
     144: iload         14
     146: iload         15
     148: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     151: ifeq          157
     154: iinc          8, 1
     157: aload_1
     158: iload         13
     160: iconst_1
     161: isub
     162: iload         14
     164: iload         15
     166: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     169: ifeq          175
     172: iinc          8, 1
     175: aload_1
     176: iload         13
     178: iload         14
     180: iconst_1
     181: iadd
     182: iload         15
     184: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     187: ifeq          193
     190: iinc          8, 1
     193: aload_1
     194: iload         13
     196: iload         14
     198: iconst_1
     199: isub
     200: iload         15
     202: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     205: ifeq          211
     208: iinc          8, 1
     211: aload_1
     212: iload         13
     214: iload         14
     216: iload         15
     218: iconst_1
     219: iadd
     220: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     223: ifeq          229
     226: iinc          8, 1
     229: aload_1
     230: iload         13
     232: iload         14
     234: iload         15
     236: iconst_1
     237: isub
     238: invokestatic  #107                // Method isEmpty:([[[ZIII)Z
     241: ifeq          247
     244: iinc          8, 1
     247: iload         8
     249: istore        17
     251: iload         16
     253: iload         17
     255: iadd
     256: istore_3
     257: goto          15
     260: iload_3
     261: ireturn

  private static final boolean[][][] to3DMatrix(java.util.List<java.lang.String>);
    Code:
       0: iconst_0
       1: istore_1
       2: iconst_0
       3: istore_2
       4: iconst_0
       5: istore_3
       6: aload_0
       7: checkcast     #67                 // class java/lang/Iterable
      10: astore        4
      12: iconst_0
      13: istore        5
      15: aload         4
      17: invokeinterface #71,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      22: astore        6
      24: aload         6
      26: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      31: ifeq          159
      34: aload         6
      36: invokeinterface #81,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      41: astore        7
      43: aload         7
      45: checkcast     #83                 // class java/lang/String
      48: astore        8
      50: iconst_0
      51: istore        9
      53: aload         8
      55: checkcast     #85                 // class java/lang/CharSequence
      58: iconst_1
      59: anewarray     #83                 // class java/lang/String
      62: astore        10
      64: aload         10
      66: iconst_0
      67: ldc           #87                 // String ,
      69: aastore
      70: aload         10
      72: iconst_0
      73: iconst_0
      74: bipush        6
      76: aconst_null
      77: invokestatic  #93                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      80: astore        11
      82: aload         11
      84: iconst_0
      85: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      90: checkcast     #83                 // class java/lang/String
      93: astore        10
      95: aload         11
      97: iconst_1
      98: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     103: checkcast     #83                 // class java/lang/String
     106: astore        12
     108: aload         11
     110: iconst_2
     111: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     116: checkcast     #83                 // class java/lang/String
     119: astore        13
     121: nop
     122: iload_1
     123: aload         10
     125: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     128: invokestatic  #127                // Method java/lang/Math.max:(II)I
     131: istore_1
     132: nop
     133: iload_2
     134: aload         12
     136: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     139: invokestatic  #127                // Method java/lang/Math.max:(II)I
     142: istore_2
     143: nop
     144: iload_3
     145: aload         13
     147: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     150: invokestatic  #127                // Method java/lang/Math.max:(II)I
     153: istore_3
     154: nop
     155: nop
     156: goto          24
     159: nop
     160: iconst_0
     161: istore        5
     163: iload_1
     164: iconst_1
     165: iadd
     166: istore        6
     168: iload         6
     170: anewarray     #129                // class "[[Z"
     173: astore        7
     175: iload         5
     177: iload         6
     179: if_icmpge     249
     182: iload         5
     184: istore        8
     186: aload         7
     188: iload         8
     190: iconst_0
     191: istore        9
     193: iload_2
     194: iconst_1
     195: iadd
     196: istore        10
     198: iload         10
     200: anewarray     #131                // class "[Z"
     203: astore        11
     205: istore        16
     207: astore        15
     209: iload         9
     211: iload         10
     213: if_icmpge     236
     216: iload         9
     218: istore        12
     220: aload         11
     222: iload         12
     224: iload_3
     225: iconst_1
     226: iadd
     227: newarray       boolean
     229: aastore
     230: iinc          9, 1
     233: goto          209
     236: aload         15
     238: iload         16
     240: aload         11
     242: aastore
     243: iinc          5, 1
     246: goto          175
     249: aload         7
     251: astore        4
     253: aload_0
     254: checkcast     #67                 // class java/lang/Iterable
     257: astore        5
     259: iconst_0
     260: istore        6
     262: aload         5
     264: invokeinterface #71,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     269: astore        7
     271: aload         7
     273: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     278: ifeq          394
     281: aload         7
     283: invokeinterface #81,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     288: astore        8
     290: aload         8
     292: checkcast     #83                 // class java/lang/String
     295: astore        9
     297: iconst_0
     298: istore        10
     300: aload         9
     302: checkcast     #85                 // class java/lang/CharSequence
     305: iconst_1
     306: anewarray     #83                 // class java/lang/String
     309: astore        11
     311: aload         11
     313: iconst_0
     314: ldc           #87                 // String ,
     316: aastore
     317: aload         11
     319: iconst_0
     320: iconst_0
     321: bipush        6
     323: aconst_null
     324: invokestatic  #93                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     327: astore        12
     329: aload         12
     331: iconst_0
     332: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     337: checkcast     #83                 // class java/lang/String
     340: astore        11
     342: aload         12
     344: iconst_1
     345: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     350: checkcast     #83                 // class java/lang/String
     353: astore        13
     355: aload         12
     357: iconst_2
     358: invokeinterface #97,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     363: checkcast     #83                 // class java/lang/String
     366: astore        14
     368: aload         4
     370: aload         11
     372: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     375: aaload
     376: aload         13
     378: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     381: aaload
     382: aload         14
     384: invokestatic  #103                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     387: iconst_1
     388: bastore
     389: nop
     390: nop
     391: goto          271
     394: nop
     395: aload         4
     397: areturn

  private static final boolean[][][] fillWithWater(boolean[][][]);
    Code:
       0: iconst_0
       1: istore_2
       2: aload_0
       3: checkcast     #145                // class "[Ljava/lang/Object;"
       6: arraylength
       7: istore_3
       8: iload_3
       9: anewarray     #129                // class "[[Z"
      12: astore        4
      14: iload_2
      15: iload_3
      16: if_icmpge     134
      19: iload_2
      20: istore        5
      22: aload         4
      24: iload         5
      26: iconst_0
      27: istore        6
      29: aload_0
      30: iconst_0
      31: aaload
      32: checkcast     #145                // class "[Ljava/lang/Object;"
      35: arraylength
      36: istore        7
      38: iload         7
      40: anewarray     #131                // class "[Z"
      43: astore        8
      45: istore        15
      47: astore        14
      49: iload         6
      51: iload         7
      53: if_icmpge     121
      56: iload         6
      58: istore        9
      60: aload         8
      62: iload         9
      64: iconst_0
      65: istore        10
      67: aload_0
      68: iconst_0
      69: aaload
      70: iconst_0
      71: aaload
      72: arraylength
      73: istore        11
      75: iload         11
      77: newarray       boolean
      79: astore        12
      81: istore        17
      83: astore        16
      85: iload         10
      87: iload         11
      89: if_icmpge     108
      92: iload         10
      94: istore        13
      96: aload         12
      98: iload         13
     100: iconst_1
     101: bastore
     102: iinc          10, 1
     105: goto          85
     108: aload         16
     110: iload         17
     112: aload         12
     114: aastore
     115: iinc          6, 1
     118: goto          49
     121: aload         14
     123: iload         15
     125: aload         8
     127: aastore
     128: iinc          2, 1
     131: goto          14
     134: aload         4
     136: astore_1
     137: aload_0
     138: checkcast     #145                // class "[Ljava/lang/Object;"
     141: invokestatic  #151                // Method kotlin/collections/ArraysKt.getLastIndex:([Ljava/lang/Object;)I
     144: istore_2
     145: aload_0
     146: iconst_0
     147: aaload
     148: checkcast     #145                // class "[Ljava/lang/Object;"
     151: invokestatic  #151                // Method kotlin/collections/ArraysKt.getLastIndex:([Ljava/lang/Object;)I
     154: istore_3
     155: aload_0
     156: iconst_0
     157: aaload
     158: iconst_0
     159: aaload
     160: invokestatic  #154                // Method kotlin/collections/ArraysKt.getLastIndex:([Z)I
     163: istore        4
     165: iconst_0
     166: istore        5
     168: aload_0
     169: checkcast     #145                // class "[Ljava/lang/Object;"
     172: arraylength
     173: istore        6
     175: iload         5
     177: iload         6
     179: if_icmpge     234
     182: iconst_0
     183: istore        7
     185: aload_0
     186: iconst_0
     187: aaload
     188: checkcast     #145                // class "[Ljava/lang/Object;"
     191: arraylength
     192: istore        8
     194: iload         7
     196: iload         8
     198: if_icmpge     228
     201: aload_0
     202: aload_1
     203: iload         5
     205: iload         7
     207: iconst_0
     208: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     211: aload_0
     212: aload_1
     213: iload         5
     215: iload         7
     217: iload         4
     219: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     222: iinc          7, 1
     225: goto          194
     228: iinc          5, 1
     231: goto          175
     234: iconst_0
     235: istore        5
     237: aload_0
     238: checkcast     #145                // class "[Ljava/lang/Object;"
     241: arraylength
     242: istore        6
     244: iload         5
     246: iload         6
     248: if_icmpge     301
     251: iconst_0
     252: istore        7
     254: aload_0
     255: iconst_0
     256: aaload
     257: iconst_0
     258: aaload
     259: arraylength
     260: istore        8
     262: iload         7
     264: iload         8
     266: if_icmpge     295
     269: aload_0
     270: aload_1
     271: iload         5
     273: iconst_0
     274: iload         7
     276: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     279: aload_0
     280: aload_1
     281: iload         5
     283: iload_3
     284: iload         7
     286: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     289: iinc          7, 1
     292: goto          262
     295: iinc          5, 1
     298: goto          244
     301: iconst_0
     302: istore        5
     304: aload_0
     305: iconst_0
     306: aaload
     307: checkcast     #145                // class "[Ljava/lang/Object;"
     310: arraylength
     311: istore        6
     313: iload         5
     315: iload         6
     317: if_icmpge     370
     320: iconst_0
     321: istore        7
     323: aload_0
     324: iconst_0
     325: aaload
     326: iconst_0
     327: aaload
     328: arraylength
     329: istore        8
     331: iload         7
     333: iload         8
     335: if_icmpge     364
     338: aload_0
     339: aload_1
     340: iconst_0
     341: iload         5
     343: iload         7
     345: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     348: aload_0
     349: aload_1
     350: iload_2
     351: iload         5
     353: iload         7
     355: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     358: iinc          7, 1
     361: goto          331
     364: iinc          5, 1
     367: goto          313
     370: aload_1
     371: areturn

  private static final void fill(boolean[][][], boolean[][][], int, int, int);
    Code:
       0: aload_1
       1: iload_2
       2: iload_3
       3: iload         4
       5: invokestatic  #164                // Method isXYZInside:([[[ZIII)Z
       8: ifeq          33
      11: aload_0
      12: iload_2
      13: aaload
      14: iload_3
      15: aaload
      16: iload         4
      18: baload
      19: ifne          33
      22: aload_1
      23: iload_2
      24: aaload
      25: iload_3
      26: aaload
      27: iload         4
      29: baload
      30: ifne          34
      33: return
      34: aload_1
      35: iload_2
      36: aaload
      37: iload_3
      38: aaload
      39: iload         4
      41: iconst_0
      42: bastore
      43: aload_0
      44: aload_1
      45: iload_2
      46: iconst_1
      47: iadd
      48: iload_3
      49: iload         4
      51: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
      54: aload_0
      55: aload_1
      56: iload_2
      57: iconst_1
      58: isub
      59: iload_3
      60: iload         4
      62: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
      65: aload_0
      66: aload_1
      67: iload_2
      68: iload_3
      69: iconst_1
      70: iadd
      71: iload         4
      73: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
      76: aload_0
      77: aload_1
      78: iload_2
      79: iload_3
      80: iconst_1
      81: isub
      82: iload         4
      84: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
      87: aload_0
      88: aload_1
      89: iload_2
      90: iload_3
      91: iload         4
      93: iconst_1
      94: iadd
      95: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
      98: aload_0
      99: aload_1
     100: iload_2
     101: iload_3
     102: iload         4
     104: iconst_1
     105: isub
     106: invokestatic  #158                // Method fill:([[[Z[[[ZIII)V
     109: return

  private static final boolean isEmpty(boolean[][][], int, int, int);
    Code:
       0: aload_0
       1: iload_1
       2: iload_2
       3: iload_3
       4: invokestatic  #164                // Method isXYZInside:([[[ZIII)Z
       7: ifeq          28
      10: aload_0
      11: iload_1
      12: aaload
      13: iload_2
      14: aaload
      15: iload_3
      16: baload
      17: ifne          24
      20: iconst_1
      21: goto          29
      24: iconst_0
      25: goto          29
      28: iconst_1
      29: ireturn

  private static final boolean isXYZInside(boolean[][][], int, int, int);
    Code:
       0: iconst_0
       1: iload_1
       2: if_icmpgt     22
       5: iload_1
       6: aload_0
       7: checkcast     #145                // class "[Ljava/lang/Object;"
      10: arraylength
      11: if_icmpge     18
      14: iconst_1
      15: goto          23
      18: iconst_0
      19: goto          23
      22: iconst_0
      23: ifeq          85
      26: iconst_0
      27: iload_2
      28: if_icmpgt     50
      31: iload_2
      32: aload_0
      33: iload_1
      34: aaload
      35: checkcast     #145                // class "[Ljava/lang/Object;"
      38: arraylength
      39: if_icmpge     46
      42: iconst_1
      43: goto          51
      46: iconst_0
      47: goto          51
      50: iconst_0
      51: ifeq          85
      54: iconst_0
      55: iload_3
      56: if_icmpgt     77
      59: iload_3
      60: aload_0
      61: iload_1
      62: aaload
      63: iload_2
      64: aaload
      65: arraylength
      66: if_icmpge     73
      69: iconst_1
      70: goto          78
      73: iconst_0
      74: goto          78
      77: iconst_0
      78: ifeq          85
      81: iconst_1
      82: goto          86
      85: iconst_0
      86: ireturn

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