package adventofcode2019

import kotlin.math.abs

class Day03CrossedWires

data class DistanceCoordinate(
    val distance: Int,
    val coordinate: Pair<Int, Int>
)

data class GravityWire(val coordinates: List<Pair<Int, Int>> = emptyList()) {
    val distanceCoordinates = mutableListOf<DistanceCoordinate>()

    fun buildPathFromString(input: String) {
        var currentX = 0
        var currentY = 0
        var distance = 0
        val parts = input.split(",")

        parts.forEach { part ->
            val dist = part.substring(1).toInt()
            when (part.first()) {
                'R' -> {
                    repeat(dist) {
                        distanceCoordinates.add(DistanceCoordinate(++distance, ++currentX to currentY))
                    }
                }

                'D' -> {
                    repeat(dist) {
                        distanceCoordinates.add(DistanceCoordinate(++distance, currentX to ++currentY))
                    }
                }

                'L' -> {
                    repeat(dist) {
                        distanceCoordinates.add(DistanceCoordinate(++distance, --currentX to currentY))
                    }
                }

                else -> {
                    repeat(dist) {
                        distanceCoordinates.add(DistanceCoordinate(++distance, currentX to --currentY))
                    }
                }
            }
        }
    }

    companion object {
        var currentX = 0
        var currentY = 0
        var path = mutableListOf<Pair<Int, Int>>()

        fun fromString(input: String): GravityWire {
            if (input.isBlank()) return GravityWire()
            currentX = 0
            currentY = 0
            path = mutableListOf()
            val parts = input.split(",")

            parts.forEach { direction ->
                move(direction.first(), direction.substring(1))
            }

            return GravityWire(path.toList())
        }

        private fun move(direction: Char, distance: String) {
            val dist = distance.toInt()
            when (direction) {
                'R' -> {
                    repeat(dist) {
                        path.add(++currentX to currentY)
                    }
                }

                'D' -> {
                    repeat(dist) {
                        path.add(currentX to ++currentY)
                    }
                }

                'L' -> {
                    repeat(dist) {
                        path.add(--currentX to currentY)
                    }
                }

                else -> {
                    repeat(dist) {
                        path.add(currentX to --currentY)
                    }
                }
            }
        }
    }
}

class FuelManagementSystem(firstWireDirections: String = "", secondWireDirections: String = "") {
    var firstWire: GravityWire
    var secondWire: GravityWire

    init {
        firstWire = GravityWire.fromString(firstWireDirections)
        secondWire = GravityWire.fromString(secondWireDirections)
    }

    fun findClosestTwistDistance(): Int {
        val intersections = mutableListOf<Pair<Int, Int>>()
        firstWire.coordinates.forEach { firstCoordinate ->
            secondWire.coordinates.forEach { secondCoordinate ->
                if (firstCoordinate == secondCoordinate) intersections.add(firstCoordinate)
            }
        }
        val closestTwist = intersections.sortedBy { abs(it.first) + abs(it.second) }.first()
        return abs(closestTwist.first) + abs(closestTwist.second)
    }

    fun findClosestTwistDistanceSteps(): Int {
        val intersections = mutableListOf<Int>()
        firstWire.distanceCoordinates.forEach { firstCoordinate ->
            secondWire.distanceCoordinates.forEach { secondCoordinate ->
                if (firstCoordinate.coordinate == secondCoordinate.coordinate) intersections.add(firstCoordinate.distance + secondCoordinate.distance)
            }
        }
        return intersections.min()
    }
}

Compiled from "Day03CrossedWires.kt"
public final class adventofcode2019.Day03CrossedWires {
  public adventofcode2019.Day03CrossedWires();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2019

import java.lang.Math.toDegrees
import kotlin.math.abs
import kotlin.math.atan2

class Day10MonitoringStation

data class Asteroid(
    val x: Int,
    val y: Int,
    var isVaborized: Boolean = false
)

class Ceres(map: List<String>) {
    val asteroids: List<Asteroid>

    init {
        asteroids = map.flatMapIndexed { y, line ->
            line.mapIndexed { x, element ->
                if (element == '#') Asteroid(x, y) else null
            }
        }.filterNotNull()
    }

    fun detectionsFromBestLocation(): Int {
        val (bestX, bestY) = detectBestLocation()
        return asteroids.size - 1 - (hiddenAsteroidsFrom(bestX, bestY))
    }

    fun detectBestLocation(): Pair<Int, Int> {
        val (bestX, bestY) = asteroids.minBy { asteroid -> hiddenAsteroidsFrom(asteroid.x, asteroid.y) }
        return bestX to bestY
    }

    fun vaborize(): Int {
        val (bestX, bestY) = detectBestLocation()

        val groupsByAngle = asteroids
            .filterNot { asteroid -> (asteroid.x == bestX && asteroid.y == bestY) }
            .groupBy { asteroid -> calculateAngleFromNorth(bestX, bestY, asteroid.x, asteroid.y) }.toSortedMap()

        var counter = 0
        var nextAsteroidToVaborize: Asteroid?

        while (true) {
            groupsByAngle.forEach { group ->
                nextAsteroidToVaborize = group.value
                    .filter { asteroid -> asteroid.isVaborized == false }
                    .sortedBy { asteroid -> manhattanDistance(bestX, bestY, asteroid.x, asteroid.y) }.firstOrNull()
                nextAsteroidToVaborize?.let {
                    it.isVaborized = true
                    if (counter == 199) {
                        return (it.x * 100) + it.y
                    }
                    counter++
                }
            }
        }
    }

    fun hiddenAsteroidsFrom(x: Int, y: Int): Int {
        val u = if (upNeighborsCount(x, y) > 0) upNeighborsCount(x, y) - 1 else 0
        val d = if (downNeighborsCount(x, y) > 0) downNeighborsCount(x, y) - 1 else 0
        val l = if (leftNeighborsCount(x, y) > 0) leftNeighborsCount(x, y) - 1 else 0
        val r = if (rightNeighborsCount(x, y) > 0) rightNeighborsCount(x, y) - 1 else 0
        val a = hiddenBySameAngleCount(x, y)

        return u + d + l + r + a
    }

    fun upNeighborsCount(x: Int, y: Int) = asteroids.count { asteroid -> asteroid.x == x && asteroid.y < y }

    fun downNeighborsCount(x: Int, y: Int) = asteroids.count { asteroid -> asteroid.x == x && asteroid.y > y }

    fun leftNeighborsCount(x: Int, y: Int) = asteroids.count { asteroid -> asteroid.x < x && asteroid.y == y }

    fun rightNeighborsCount(x: Int, y: Int) = asteroids.count { asteroid -> asteroid.x > x && asteroid.y == y }

    fun hiddenBySameAngleCount(x: Int, y: Int): Int {
        val matches = asteroids.filterNot { asteroid -> asteroid.x == x || asteroid.y == y }
            .groupBy { asteroid -> calculateAngleFromNorth(x, y, asteroid.x, asteroid.y) }
        var totalCount = 0

        matches.forEach { group ->
            totalCount += if (group.value.size > 1) group.value.size - 1 else 0
        }

        return totalCount
    }

    fun calculateAngleFromNorth(referenceX: Int, referenceY: Int, asteroidX: Int, asteroidY: Int): Double {
        val angle = toDegrees(
            atan2(
                (asteroidY - referenceY).toDouble(),
                (asteroidX - referenceX).toDouble()
            )
        ) + 90

        return if (angle < 0) angle + 360 else angle
    }

    fun manhattanDistance(referenceX: Int, referenceY: Int, asteroidX: Int, asteroidY: Int) =
        abs(referenceX - asteroidX) + abs(referenceY - asteroidY)
}

Compiled from "Day10MonitoringStation.kt"
public final class adventofcode2019.Day10MonitoringStation {
  public adventofcode2019.Day10MonitoringStation();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2019

import kotlin.math.abs
import kotlin.math.max
import kotlin.math.sqrt

class Day12TheNbodyProblem

data class MoonVelocity(var x: Int, var y: Int, var z: Int) {
    val kineticEnergy: Int
        get() = abs(x) + abs(y) + abs(z)
}

data class JupiterMoon(val id: Int, var x: Int, var y: Int, var z: Int, val velocity: MoonVelocity) {
    val totalEnergy: Int
        get() = (abs(x) + abs(y) + abs(z)) * velocity.kineticEnergy
    val currentState: List<Int>
        get() = listOf(x, y, z, velocity.x, velocity.y, velocity.z)
    val currentCoordinates: List<Int>
        get() = listOf(x, y, z)

    fun applyGravityFromPeer(peer: JupiterMoon) {
        if (x < peer.x) velocity.x++
        else if (x > peer.x) velocity.x--
        if (y < peer.y) velocity.y++
        else if (y > peer.y) velocity.y--
        if (z < peer.z) velocity.z++
        else if (z > peer.z) velocity.z--
    }

    fun adjustCoordinatesByVelocity() {
        x += velocity.x
        y += velocity.y
        z += velocity.z
    }
}

class JupiterOrbit(moonCoordinates: List<String>) {
    val moons: List<JupiterMoon>

    init {
        moons = moonCoordinates.mapIndexed { index, coordinates -> parseMoon(index, coordinates) }
    }

    private fun parseMoon(id: Int, coordinates: String): JupiterMoon {
        val x = coordinates.substringAfter("x=").substringBefore(",").toInt()
        val y = coordinates.substringAfter("y=").substringBefore(",").toInt()
        val z = coordinates.substringAfter("z=").substringBefore(">").toInt()
        return JupiterMoon(id, x, y, z, MoonVelocity(0, 0, 0))
    }

    fun step(stepCount: Int) {
        repeat(stepCount) {
            applyGravity()
            applyVelocity()
        }
    }

    fun stepsUntilCircle(): Long {
        val startingX: List<Pair<Int, Int>> = moons.map { it.x to it.velocity.x }
        val startingY: List<Pair<Int, Int>> = moons.map { it.y to it.velocity.y }
        val startingZ: List<Pair<Int, Int>> = moons.map { it.z to it.velocity.z }
        var foundX: Long? = null
        var foundY: Long? = null
        var foundZ: Long? = null

        var stepCount = 0L
        do {
            stepCount++
            step(1)
            foundX = if (foundX == null && startingX == moons.map { it.x to it.velocity.x }) stepCount else foundX
            foundY = if (foundY == null && startingY == moons.map { it.y to it.velocity.y }) stepCount else foundY
            foundZ = if (foundZ == null && startingZ == moons.map { it.z to it.velocity.z }) stepCount else foundZ
        } while (foundX == null || foundY == null || foundZ == null)

        return lcm(foundX, foundY, foundZ)
    }

    fun lcm(vararg numbers: Long): Long {

        val groups = mutableListOf<List<Pair<Long, Long>>>()

        for (n in numbers) {
            groups.add(groupNumbers(factorize(n)))
        }

        val numberGroups = groups.flatMap { it }

        val orderedGroups =
            numberGroups.map { g -> g.first to numberGroups.filter { it.first == g.first }.maxOf { it.second } }.toSet()

        return orderedGroups.fold(1) { acc, pair -> acc * (pair.first.pow(pair.second)) }
    }

    private fun Long.pow(exponent: Long) = Math.pow(this.toDouble(), exponent.toDouble()).toInt()

    fun factorize(number: Long): List<Long> {
        val result: ArrayList<Long> = arrayListOf()

        var n = number

        while (n % 2L == 0L) {
            result.add(2)
            n /= 2
        }

        val squareRoot = sqrt(number.toDouble()).toInt()

        for (i in 3..squareRoot step 2) {
            while (n % i == 0L) {
                result.add(i.toLong())
                n /= i
            }
        }

        if (n > 2) {
            result.add(n)
        }

        return result
    }

    fun groupNumbers(nums: List<Long>): List<Pair<Long, Long>> {
        val groups = nums.groupBy { it }
        val groupCounts = groups.map { it.key to it.value.size.toLong() }
        return groupCounts
    }

    private fun applyGravity() {
        val oldState = moons.toList()

        moons.forEach { moon ->
            oldState.filter { it.id != moon.id }.forEach { moon.applyGravityFromPeer(it) }
        }
    }

    private fun applyVelocity() {
        moons.forEach { it.adjustCoordinatesByVelocity() }
    }

    fun totalEnergy() = moons.sumOf { moon -> moon.totalEnergy }
}

Compiled from "Day12TheNbodyProblem.kt"
public final class adventofcode2019.Day12TheNbodyProblem {
  public adventofcode2019.Day12TheNbodyProblem();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

import adventofcode2018.AreaElement.*
import java.lang.Math.min
import java.util.*
import kotlin.math.max

class Day18SettlersOfTheNorthPole

sealed class AreaElement(val sign: Char) {
    object Open : AreaElement('.')
    object Tree : AreaElement('|')
    object Lumberyard : AreaElement('#')

    override fun toString(): String = sign.toString()
}

fun List<List<AreaElement>>.hash(): Int {
    return Arrays.deepHashCode(this.toTypedArray())
}

class NorthPoleArea(input: List<String>) {
    var elements: List<List<AreaElement>>
    val rounds = mutableMapOf<Int, List<List<AreaElement>>>()
    val roundHashes = mutableMapOf<Int, Int>()
    val totalResource: Int
        get() {
            val treeCount = elements.flatten().filter { it is Tree }.count()
            val lumberyardCount = elements.flatten().filter { it is Lumberyard }.count()
            return treeCount * lumberyardCount
        }

    init {
        elements = input.map { line ->
            line.toCharArray().map { sign ->
                elementFromSign(sign)
            }
        }
    }

    private fun elementFromSign(sign: Char): AreaElement {
        return when (sign) {
            '|' -> Tree
            '#' -> Lumberyard
            else -> Open
        }
    }

    fun transform(count: Long) {
        var loop = 0
        var counter = 0
        while (loop == 0) {
            val transformedElements = List(elements.size) {
                elements[it].mapIndexed { x, element -> transformElement(element, it, x) }
            }
            if (roundHashes.values.contains(transformedElements.hash())) {
                println("Loop found via hash at $counter")
            }
            if (rounds.values.contains(transformedElements)) {
                loop = counter
                println("Loop at iteration: $counter")
            } else {
                rounds[counter] = transformedElements
                roundHashes[counter] = transformedElements.hash()
                counter++
            }
            elements = transformedElements
        }
        if (loop > 0) {
            val effectiveRound = Math.floorMod(count, loop) - 1
            println("Effective round: $effectiveRound")
            elements = rounds[effectiveRound]!!
        }
    }

    private fun transformElement(element: AreaElement, posY: Int, posX: Int): AreaElement {
        return when (element) {
            is Open -> transformOpen(posY, posX)
            is Tree -> transformTree(posY, posX)
            is Lumberyard -> transformLumberyard(posY, posX)
        }
    }

    private fun transformTree(posY: Int, posX: Int) =
        if (neighborsAt(posY, posX).filter { it is Lumberyard }.count() > 2) Lumberyard else Tree

    private fun transformOpen(posY: Int, posX: Int) =
        if (neighborsAt(posY, posX).filter { it is Tree }.count() > 2) Tree else Open

    private fun transformLumberyard(posY: Int, posX: Int): AreaElement {
        val containsLumberyard = neighborsAt(posY, posX).any { it is Lumberyard }
        val containsTree = neighborsAt(posY, posX).any { it is Tree }
        return if (containsLumberyard && containsTree) Lumberyard else Open
    }

    fun neighborsAt(posY: Int, posX: Int): List<AreaElement> {
        val minX = max(0, posX - 1)
        val maxX = min(elements[0].size - 1, posX + 1)
        val minY = max(0, posY - 1)
        val maxY = min(elements.size - 1, posY + 1)
        val result = mutableListOf<AreaElement>()
        (minY..maxY).forEach { y ->
            (minX..maxX).forEach { x ->
                if (!(y == posY && x == posX)) result.add(elements[y][x])
            }
        }
        return result.toList()
    }

    fun printArea() {
        println()
        elements.forEach { println(it.joinToString(separator = "")) }
        println()
    }
}

Compiled from "Day18SettlersOfTheNorthPole.kt"
public final class adventofcode2018.Day18SettlersOfTheNorthPoleKt {
  public static final int hash(java.util.List<? extends java.util.List<? extends adventofcode2018.AreaElement>>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/util/Collection
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: astore_3
      15: aload_3
      16: iconst_0
      17: anewarray     #20                 // class java/util/List
      20: invokeinterface #24,  2           // InterfaceMethod java/util/Collection.toArray:([Ljava/lang/Object;)[Ljava/lang/Object;
      25: invokestatic  #30                 // Method java/util/Arrays.deepHashCode:([Ljava/lang/Object;)I
      28: ireturn
}

Compiled from "Day18SettlersOfTheNorthPole.kt"
public final class adventofcode2018.Day18SettlersOfTheNorthPole {
  public adventofcode2018.Day18SettlersOfTheNorthPole();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class Day04ReposeRecord

data class Guard(val id: Int)

data class SleepPeriod(val start: LocalDateTime, val stop: LocalDateTime)

sealed class ShiftEntry(
    val dateTime: LocalDateTime,
    val guard: Guard = Guard(-1),
    val awake: Boolean = false,
    val asleep: Boolean = false
) {
    companion object {
        val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
        fun fromString(input: String): ShiftEntry {
            val dateTime = LocalDateTime.parse(input.substring(1).substringBefore("] "), dateFormatter)
            return when {
                input.contains("Guard") -> NewGuardEntry(
                    dateTime,
                    Guard(input.substringAfter("#").substringBefore(" ").toInt())
                )

                input.contains("asleep") -> AsleepEntry(dateTime)
                else -> AwakeEntry(dateTime)
            }
        }
    }

    override fun toString(): String {
        return "ShiftEntry(dateTime=$dateTime, guard=$guard, awake=$awake, asleep=$asleep)"
    }

}

class NewGuardEntry(dateTime: LocalDateTime, guard: Guard) : ShiftEntry(dateTime, guard, awake = true)
class AsleepEntry(dateTime: LocalDateTime) : ShiftEntry(dateTime, asleep = true)
class AwakeEntry(dateTime: LocalDateTime) : ShiftEntry(dateTime, awake = true)

class ShiftPlan(input: List<String>) {
    val entries: List<ShiftEntry>
    var currentGuard = Guard(-1)
    var currentStartSleep = LocalDateTime.now()
    val guardRecords = mutableMapOf<Guard, MutableList<SleepPeriod>>()
    var guardSleeping = false

    init {
        entries = input.map { ShiftEntry.fromString(it) }.sortedBy { it.dateTime }
    }

    fun scheduleShifts() {
        entries.forEach { entry ->
            when (entry) {
                is NewGuardEntry -> {
                    if (guardRecords[entry.guard] == null) {
                        guardRecords[entry.guard] = mutableListOf()
                    }
                    if (guardSleeping) {
                        recordSleep(entry.dateTime.minusMinutes(1))
                        guardSleeping = false
                    }
                    currentGuard = entry.guard
                }

                is AsleepEntry -> {
                    currentStartSleep = entry.dateTime
                    guardSleeping = true
                }

                is AwakeEntry -> {
                    recordSleep(entry.dateTime.minusMinutes(1))
                    guardSleeping = false
                }
            }
        }
    }

    private fun recordSleep(endSleep: LocalDateTime) {
        guardRecords[currentGuard]?.add(SleepPeriod(currentStartSleep, endSleep))
    }

    fun findBestGuardAndMinute(): Pair<Guard, Int> {
        val bestGuard = findBestGuard()
        val bestMinute = findBestMinute(bestGuard)
        return bestGuard to bestMinute
    }

    private fun findBestGuard(): Guard {
        val sleepTimes = guardRecords.map { records ->
            val totalSleep = records.value.sumOf { it.stop.minute - it.start.minute }
            records.key to totalSleep
        }

        return sleepTimes.maxBy { it.second }.first
    }

    private fun findBestMinute(guard: Guard): Int {
        var result = 0
        guardRecords[guard]?.let {
            result = getMostFrequentMinute(it).first
        }
        return result
    }

    fun findBestGuardMostFrequentMinute(): Pair<Guard, Int> {
        val groupedEntries = guardRecords
            .filter { it.value.size > 0 }
            .map { it.key to getMostFrequentMinute(it.value) }
        val maxEntry = groupedEntries.maxBy { it.second.second }
        return maxEntry.first to maxEntry.second.first
    }

    private fun getMostFrequentMinute(sleepPeriods: List<SleepPeriod>): Pair<Int, Int> {
        val minutes = mutableListOf<Int>()
        sleepPeriods.forEach { sleepPeriod ->
            (sleepPeriod.start.minute..sleepPeriod.stop.minute).forEach {
                minutes.add(it)
            }
        }
        val sleepMinutesGroups = minutes.groupBy { it }
        val result = sleepMinutesGroups.maxByOrNull { it.value.size }
        return result?.let {
            result.key to result.value.size
        } ?: (-1 to 0)
    }
}

Compiled from "Day04ReposeRecord.kt"
public final class adventofcode2018.Day04ReposeRecord {
  public adventofcode2018.Day04ReposeRecord();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day06ChronalCoordinates

data class Coordinate(val id: Int, val x: Int, val y: Int) {

    fun manhattanDistance(fromX: Int, fromY: Int): Int {
        val xDist = if (fromX > x) (fromX - x) else (x - fromX)
        val yDist = if (fromY > y) (fromY - y) else (y - fromY)
        return xDist + yDist
    }

    companion object {
        var counter = 0

        fun fromString(input: String): Coordinate {
            return Coordinate(counter++, input.substringBefore(",").toInt(), input.substringAfter(", ").toInt())
        }
    }
}

class CoordinateSystem(input: List<String>) {
    val coordinates: List<Coordinate>
    val fields = mutableListOf<Coordinate>()
    val xMin: Int
    val xMax: Int
    val yMin: Int
    val yMax: Int

    init {
        coordinates = input.map { Coordinate.fromString(it) }
        xMin = coordinates.minOf { it.x }
        xMax = coordinates.maxOf { it.x }
        yMin = coordinates.minOf { it.y }
        yMax = coordinates.maxOf { it.y }
    }

    fun innerCoordinates(): List<Coordinate> {
        return coordinates.filter {
            it.x > xMin && it.x < xMax && it.y > yMin && it.y < yMax
        }
    }

    private fun mapFields() {
        (0..xMax).forEach { x ->
            (0..yMax).forEach { y ->
                findClosestInnerCoordinate(x, y)?.run { fields.add(this) }
            }
        }
    }

    private fun findClosestInnerCoordinate(x: Int, y: Int): Coordinate? {
        val inner = innerCoordinates()
        val distances = coordinates.map { it to it.manhattanDistance(x, y) }.sortedBy { it.second }
            .filter { x >= xMin && x <= xMax && y >= yMin && y <= yMax }
        if (distances.isEmpty()) return Coordinate(-1, x, y)
        if (distances[0].second == distances[1].second) return Coordinate(-1, x, y)
        if (!(inner.contains(distances[0].first))) return Coordinate(-1, x, y)
        return Coordinate(distances[0].first.id, x, y)
    }

    fun calcLargestInnerFieldSize(): Int {
        mapFields()
        val innerFields = fields.filterNot { it.id == -1 }
        val groupedFields = innerFields.groupBy { it.id }
        return groupedFields.filterNot { isInfiniteGroup(it.value) }.maxOf { it.value.size }
    }

    private fun isInfiniteGroup(group: List<Coordinate>) = group.any { outOfBounds(it) }

    private fun outOfBounds(it: Coordinate) = it.x <= xMin || it.x >= xMax || it.y <= yMin || it.y >= yMax

    fun printSystem() {
        (0..yMax).forEach { y ->
            (0..xMax).forEach { x ->
                fields.firstOrNull { it.x == x && it.y == y }?.run {
                    if (id == -1) print('.') else print(id)
                } ?: print('.')
            }
            println()
        }
    }

    fun sizeOfLargestSafeRegion(range: Int): Int {
        var counter = 0
        (0..yMax).forEach { y ->
            (0..xMax).forEach { x ->
                if (calcTotalDistance(x, y) < range) counter++
            }
        }
        return counter
    }

    private fun calcTotalDistance(x: Int, y: Int): Int {
        return coordinates.sumOf { it.manhattanDistance(x, y) }
    }
}

Compiled from "Day06ChronalCoordinates.kt"
public final class adventofcode2018.Day06ChronalCoordinates {
  public adventofcode2018.Day06ChronalCoordinates();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

import kotlin.math.abs

class Day23ExperimentalEmergencyTeleportation

data class TeleportCoordinate(val x: Int, val y: Int, val z: Int)

data class Nanobot(val x: Int, val y: Int, val z: Int, val radius: Int) {

    fun inRange(otherBot: Nanobot): Boolean {
        val manhattanDistance = distanceTo(otherBot.x, otherBot.y, otherBot.z)
        return manhattanDistance <= otherBot.radius
    }

    fun withinRangeOfSharedPoint(otherBot: Nanobot) =
        distanceTo(otherBot.x, otherBot.y, otherBot.z) <= radius + otherBot.radius

    fun inRange(xDist: Int, yDist: Int, zDist: Int) = distanceTo(xDist, yDist, zDist) <= radius

    internal fun distanceTo(xDist: Int, yDist: Int, zDist: Int) =
        abs(x - xDist) + abs(y - yDist) + abs(z - zDist)
}

class TeleportationDevice(val input: List<String>) {
    val bots: List<Nanobot>
    val strongestBot: Nanobot
        get() = bots.maxBy { it.radius }

    init {
        bots = input.map { parseBot(it) }
    }

    private fun parseBot(input: String): Nanobot {
        val coordinates = input.substringAfter("<").substringBefore(">")
        val (x, y, z) = coordinates.split(",").map { it.toInt() }
        return Nanobot(x, y, z, input.substringAfterLast("=").toInt())
    }

    fun numberOfBotsInRangeOfStrongest() = bots.count { it.inRange(strongestBot) }

    fun strongestCoordinate(): TeleportCoordinate {
        var strongest = TeleportCoordinate(0, 0, 0)
        var strongestCount = 0

        val minX = bots.minOf { it.x }
        val maxX = bots.maxOf { it.x }
        val minY = bots.minOf { it.y }
        val maxY = bots.maxOf { it.y }
        val minZ = bots.minOf { it.z }
        val maxZ = bots.maxOf { it.z }

        var botsCount: Int
        (minX..maxX).forEach { x ->
            (minY..maxY).forEach { y ->
                (minZ..maxZ).forEach { z ->
                    botsCount = bots.count { it.inRange(x, y, z) }
                    if (botsCount > strongestCount) {
                        strongestCount = botsCount
                        strongest = TeleportCoordinate(x, y, z)
                    }
                }
            }
        }
        return strongest
    }

    fun strongestDistance(): Int {
        val neighbors: Map<Nanobot, Set<Nanobot>> = bots.map { bot ->
            Pair(bot, bots.filterNot { it == bot }.filter { bot.withinRangeOfSharedPoint(it) }.toSet())
        }.toMap()

        val clique: Set<Nanobot> = BronKerbosch(neighbors).largestClique()
        return clique.map { it.distanceTo(0, 0, 0) - it.radius }.max()
    }
}

class BronKerbosch<T>(val neighbors: Map<T, Set<T>>) {

    private var bestR: Set<T> = emptySet()

    fun largestClique(): Set<T> {
        execute(neighbors.keys)
        return bestR
    }

    private fun execute(p: Set<T>, r: Set<T> = emptySet(), x: Set<T> = emptySet()) {
        if (p.isEmpty() && x.isEmpty()) {
            if (r.size > bestR.size) bestR = r
        } else {
            val mostNeighborsOfPandX: T = (p + x).maxBy { neighbors.getValue(it).size }!!
            val pWithoutNeighbors = p.minus(neighbors[mostNeighborsOfPandX]!!)
            pWithoutNeighbors.forEach { v ->
                val neighborsOfV = neighbors[v]!!
                execute(p.intersect(neighborsOfV), r + v, x.intersect(neighborsOfV))
            }
        }
    }
}

Compiled from "Day23ExperimentalEmergencyTeleportation.kt"
public final class adventofcode2018.Day23ExperimentalEmergencyTeleportation {
  public adventofcode2018.Day23ExperimentalEmergencyTeleportation();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day15BeverageBandits

sealed class Token(val sign: Char, var posX: Int, var posY: Int) : Comparable<Token> {

    open fun nextEnemy(): Token = NullToken()

    override fun toString(): String = sign.toString()

    override fun compareTo(other: Token): Int {
        return when {
            posY < other.posY -> -1
            posY > other.posY -> 1
            posX < other.posX -> -1
            posX > other.posX -> 1
            else -> 0
        }
    }

    fun adjacentCoordinates(): List<Pair<Int, Int>> {
        return listOf(posX to posY - 1, posX + 1 to posY, posX to posY + 1, posX - 1 to posY)
    }

    companion object {

        fun fromChar(c: Char, posX: Int, posY: Int): Token {
            return when (c) {
                '#' -> Wall(posX, posY)
                '.' -> Cavern(posX, posY)
                'G' -> Goblin(posX, posY)
                'E' -> Elf(posX, posY)
                else -> NullToken()
            }
        }
    }
}

class Wall(posX: Int, posY: Int) : Token('#', posX, posY)
class Cavern(posX: Int, posY: Int) : Token('.', posX, posY)
class Goblin(posX: Int, posY: Int) : Token('G', posX, posY)
class Elf(posX: Int, posY: Int) : Token('E', posX, posY)
class NullToken : Token(' ', -1, -1)

class Cave(input: List<String>) {
    val caveMap: List<Token>
    val caveWidth = input[0].length
    val caveHeight = input.size
    val sortedFighters: List<Token>
        get() = caveMap.sorted().filter { it is Goblin || it is Elf }

    init {
        caveMap = input.flatMapIndexed { posY, line ->
            line.mapIndexed { posX, token ->
                Token.fromChar(token, posX, posY)
            }
        }
    }

    fun playRound() {
        sortedFighters.forEach { fighter ->
            val caverns = getAdjacentCaverns(fighter)
            val enemies = findEnemies(fighter)
            val targets = findTargets(fighter)
            println(caverns)
        }
    }

    private fun getAdjacentCaverns(token: Token): List<Token> {
        return caveMap.filter { it is Cavern }.filter { it.posX to it.posY in token.adjacentCoordinates() }
    }

    private fun findEnemies(token: Token): List<Token> {
        return when (token) {
            is Goblin ->  caveMap.filter { it is Elf }
            is Elf -> caveMap.filter{ it is Goblin }
            else -> emptyList()
        }
    }

    private fun findTargets(token: Token): List<Token> {
        val enemies = findEnemies(token)
        return enemies.flatMap { getAdjacentCaverns(it) }
    }

    fun printCaveMap() {
        caveMap.sorted().forEachIndexed { index, token ->
            if (index % caveWidth == 0) { println() }
            print(token)
        }
        println()
    }
}

Compiled from "Day15BeverageBandits.kt"
public final class adventofcode2018.Day15BeverageBandits {
  public adventofcode2018.Day15BeverageBandits();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day22ModeMaze

class MazeCalculator(val depth: Int, val targetX: Int, val targetY: Int) {
    val regions: List<MutableList<Int>>
    val errosionLevels: List<MutableList<Int>> = List(targetY + 1) { MutableList(targetX + 1) { 0 } }
    val riskLevel: Int
        get() = regions.map { line -> line.sum() }.sum()

    init {
        regions = (0..targetY).map { y ->
            (0..targetX).map { x ->
                0
            }.toMutableList()
        }
        calculateErosionLevels()
    }

    private fun calculateErosionLevels() {
        (0..targetY).forEach { y ->
            (0..targetX).forEach { x ->
                regions[y][x] = getRegionType(y, x)
            }
        }
    }

    private fun getRegionType(y: Int, x: Int): Int {
        val erosionLevel = getErosionLevel(y, x)

        return erosionLevel % 3
    }

    private fun getErosionLevel(y: Int, x: Int): Int {
        val geologicalIndex = getGeologicalIndex(y, x)
        val errosionLevel = (geologicalIndex + depth) % 20183
        errosionLevels[y][x] = errosionLevel
        return errosionLevel
    }

    private fun getGeologicalIndex(y: Int, x: Int): Int {
        if (y == 0 && x == 0) return 0
        if (y == targetY && x == targetX) return 0
        if (y == 0) {
            return x * 16807
        }
        if (x == 0) {
            return y * 48271
        }
        return errosionLevels[y - 1][x] * errosionLevels[y][x - 1]
    }

    fun printMaze() {
        regions.forEach { line ->
            line.forEach { region ->
                when (region) {
                    0 -> print(".")
                    1 -> print("=")
                    else -> print("|")
                }
            }
            println()
        }
    }
}

Compiled from "Day22ModeMaze.kt"
public final class adventofcode2018.Day22ModeMaze {
  public adventofcode2018.Day22ModeMaze();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day12SubterraneanSustainability

data class PotRule(val input: String, val result: Char) {
    companion object {
        fun fromString(rule: String): PotRule {
            return PotRule(rule.substringBefore(" ="), rule.last())
        }
    }
}

class RulesSet(val rules: List<PotRule>) {

    fun getResultForInput(input: List<Char>): Char {
        val pattern = input.joinToString(separator = "")
        return rules.firstOrNull { it.input == pattern }?.result ?: '.'
    }

    companion object {
        fun fromRules(rules: List<String>): RulesSet {
            val potRules = rules.map { PotRule.fromString(it) }
            return RulesSet(potRules)
        }
    }
}

class Tunnel(initialState: String, rules: List<String>) {
    var pots = ArrayDeque(initialState.toList())
    var nullIndex = 0
    val rulesSet: RulesSet = RulesSet.fromRules(rules)

    private fun extendPots() {
        repeat(3) {
            pots.addFirst('.')
            pots.addLast('.')
        }
    }

    fun computeGenerations(iterations: Long): Long {
        if (iterations < 2000) {
            (0 until iterations).forEach {
                computeNextGeneration()
            }
            return computeTotalPotsSum()
        } else {
            return computeVeryOldGeneration(iterations)
        }
    }

    private fun computeVeryOldGeneration(iterations: Long): Long {
        computeGenerations(1000)
        val oneThousandGenerationCount = computeTotalPotsSum()
        computeGenerations(1000)
        val twoThousandGenerationCount = computeTotalPotsSum()
        val oneThousandIntervalCount = twoThousandGenerationCount - oneThousandGenerationCount
        val numberOfIntervalls = ((iterations - 1000)/1000)
        return (numberOfIntervalls) * oneThousandIntervalCount + oneThousandGenerationCount
    }

    fun computeNextGeneration(): Boolean {
        extendPots()
        val newList = pots.windowed(5, 1, false).map {
            rulesSet.getResultForInput(it)
        }
        if (newList.first() == '#') {
            nullIndex++
            pots = ArrayDeque(newList)
        } else {
            pots = ArrayDeque(newList.drop(1))
        }
        return false
    }

    fun computeTotalPotsSum(): Long {
        var result = 0L
        pots.forEachIndexed { index, pot ->
            if (pot == '#') {
                result += (index - nullIndex)
            }
        }
        return result
    }
}

Compiled from "Day12SubterraneanSustainability.kt"
public final class adventofcode2018.Day12SubterraneanSustainability {
  public adventofcode2018.Day12SubterraneanSustainability();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day11ChronalCharge

data class FuelCell(val x: Int, val y: Int, val powerLevel: Int) {

    companion object {
        fun forSerialNumber(x: Int, y: Int, serialNumber: Int): FuelCell =
            FuelCell(x, y, computePowerLevel(x, y, serialNumber))

        private fun computePowerLevel(x: Int, y: Int, serialNumber: Int): Int {
            var powerLevel = ((x + 10) * y + serialNumber) * (x + 10)
            if (powerLevel > 99) {
                powerLevel = (powerLevel / 100) % 10
            } else {
                powerLevel = 0
            }
            powerLevel -= 5
            return powerLevel
        }
    }
}

class PowerGrid(val serialNumber: Int) {
    val fuelCells: List<FuelCell>
    val squareScores = mutableMapOf<FuelCell, Int>()

    init {
        fuelCells = (1..300).flatMap { x ->
            (1..300).map { y ->
                FuelCell.forSerialNumber(x, y, serialNumber)
            }
        }
    }

    fun calculateScores(maxGridSize: Int) {
        (1..89397).forEach { index ->
            squareScores[fuelCells[index]] = computeScoreAt(index, maxGridSize)
        }
    }

    fun findLargestGrid(): String {
        var largestGrid = ""
        var maxScore = 0
        (1 .. 300).forEach { gridSize ->
            (0 until (300 - gridSize)).forEach { x ->
                (0 until (300 - gridSize)).forEach { y ->
                    val currentScore = computeScoreAt(y + (300 * x), gridSize)
                    if (currentScore > maxScore) {
                        maxScore = currentScore
                        largestGrid = "${x + 1},${y + 1},$gridSize"
                    }
                }
            }
        }
        return largestGrid
    }

    private fun computeScoreAt(index: Int, gridSize: Int): Int {
        var result = 0

        (0 until gridSize).forEach { y ->
            (300 * y until (300 * y + gridSize)).forEach { result += fuelCells[index + it].powerLevel }
        }

        return result
    }

    fun getHighestPowerLevelCoordinates(): String {
        val highScoreCell = squareScores.maxBy { it.value }
        return "${highScoreCell.key.x},${highScoreCell.key.y}"
    }
}

Compiled from "Day11ChronalCharge.kt"
public final class adventofcode2018.Day11ChronalCharge {
  public adventofcode2018.Day11ChronalCharge();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2018

class Day07TheSumOfItsParts

enum class Step {
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
}

data class Instruction(val step: Step, val preSteps: MutableSet<Step> = mutableSetOf())

data class ConcurrentWorker(var executionTime: Int = 0, var busy: Boolean = false) {
    fun isAvailable(processTime: Int) = executionTime <= processTime
}

class SleighProcessor(input: List<String>, private val numberOfSteps: Int) {
    val instructions: MutableList<Instruction>

    init {
        instructions = Step.values().take(numberOfSteps).map { Instruction(it) }.toMutableList()
        parseInput(input)
    }

    private fun parseInput(input: List<String>) {
        input.forEach { instruction ->
            val step = Step.valueOf(instruction.substringAfter("step ").substring(0, 1))
            val preStep = Step.valueOf(instruction.substringAfter("Step ").substring(0, 1))
            instructions.find { it.step == step }?.preSteps?.add(preStep)
        }
    }

    fun executeInstructions(): String {
        return buildString {
            while (instructions.isNotEmpty()) {
                val nextInstruction = instructions.first { it.preSteps.isEmpty() }
                append(nextInstruction.step)
                instructions.forEach { instruction -> instruction.preSteps.remove(nextInstruction.step) }
                instructions.remove(nextInstruction)
            }
        }
    }

    fun executeConcurrently(numberOfWorkers: Int): Int {
        var totalTime = 0
        var maxTime = 0
        val workers = List(numberOfWorkers) { ConcurrentWorker() }

        while (instructions.isNotEmpty()) {
            var subTime = 0
            val pendingInstructions = instructions.filter { it.preSteps.isEmpty() }
            pendingInstructions.forEach { nextInstruction ->
                val availableWorker = workers.firstOrNull { !(it.busy) } ?: workers.minBy { it.executionTime }
                val currentExecutionTime = nextInstruction.step.ordinal + 1
                availableWorker.executionTime = totalTime + subTime + currentExecutionTime

                subTime += currentExecutionTime

                instructions.forEach { instruction -> instruction.preSteps.remove(nextInstruction.step) }
                instructions.remove(nextInstruction)

                workers.forEach { worker ->
                    worker.busy = worker.executionTime >= totalTime + subTime + 1
                }
            }
            totalTime += subTime
        }

        println("total time: $totalTime")

        return workers.maxOf { it.executionTime }
    }
}

Compiled from "Day07TheSumOfItsParts.kt"
public final class adventofcode2018.Day07TheSumOfItsParts {
  public adventofcode2018.Day07TheSumOfItsParts();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2020

class Day21AllergenAssessment

data class Food(val ingredients: Set<String>, val allergens: Set<String>) {
    companion object {
        fun fromString(input: String): Food {
            val parts = input.split(" (contains ")
            val ing = parts[0].split(" ").toHashSet()
            val allg = parts[1].dropLast(1).split(" ").map { it.replace(",", "") }.toHashSet()
            return Food(ing, allg)
        }
    }
}

class Grocery(val foods: List<Food>) {

    companion object {
        fun buildGroceryFromStrings(lines: List<String>): Grocery {
            val goods = lines.map { Food.fromString(it) }
            return Grocery(goods)
        }
    }

    fun allAllergens(): Set<String> = foods.flatMap { food -> food.allergens }.toHashSet()

    fun foodsContainingAllergen(allergen: String): Set<String> {
        val foodCandidates = foods.filter { food -> food.allergens.contains(allergen) }
        val ingredientCandidates = foodCandidates.map { food -> food.ingredients }
        val intersection = ingredientCandidates.reduce { acc, current -> acc.intersect(current) }
        return intersection
    }

    fun ingredientsWithAllergen(): Set<String> {
        val candidates = allAllergens().map { allergen -> foodsContainingAllergen(allergen) }
        return candidates.reduce { acc, current -> acc + current }
    }

    fun allIngredients(): List<String> =
        foods.map { food -> food.ingredients.toList() }.reduce { acc, current -> acc + current }

    fun allIngredientsWithoutAllergens(): List<String> {
        val allIngredients = allIngredients()
        val ingredientsWithAllergens = ingredientsWithAllergen()
        return allIngredients.filter { ingredient -> ingredient !in ingredientsWithAllergens }
    }
}

Compiled from "Day21AllergenAssessment.kt"
public final class adventofcode2020.Day21AllergenAssessment {
  public adventofcode2020.Day21AllergenAssessment();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2020

class Day19MonsterMessage

data class MessageRule(
    var ruleExpression: String = "",
) {
    val fullRule: String
        get() = ruleExpression

    override fun toString(): String = (ruleExpression).replace(" ", "")

    val isEvaluated: Boolean
        get() {
            val regex = "[ab |()]*".toRegex()
            return (regex.matches(ruleExpression))
        }

    fun substituteRule(ruleNumber: String, rule: String) {
        val regex = " $ruleNumber ".toRegex()
        ruleExpression = ruleExpression.replace(regex, " ( " + rule + " ) ")
        ruleExpression = ruleExpression.replace(regex, " ( " + rule + " ) ")
    }

    fun matches(message: String): Boolean {
        val regex = (ruleExpression.replace(" ", "")).toRegex()
        return regex.matches(message)
    }
}

class RulesChecker {
    val rules = mutableMapOf<Int, MessageRule>()

    fun buildRulesFromLines(rules: List<String>) {
        rules.forEach { rule ->
            this.rules.put(
                rule.substringBefore(":").toInt(),
                MessageRule(rule.substringAfter(":").replace("\"", "").replace("\"", "") + " ")
            )
        }
        buildRulesFromRawRules()
    }

    private fun buildRulesFromRawRules() {
        var evaluatedRules = mapOf<Int, MessageRule>()
        val substitutedRules = mutableListOf<Int>()
        do {
            evaluatedRules = rules.filter { (_, messageRule) -> messageRule.isEvaluated }
            if (evaluatedRules.isNotEmpty()) {
                val rulesToReplace =
                    evaluatedRules.entries.filter { (ruleNumber, _) -> ruleNumber !in substitutedRules }
                if (rulesToReplace.isNotEmpty()) {
                    rulesToReplace.forEach { nextRuleToReplace ->
                        rules.values.forEach {
                            it.substituteRule(
                                nextRuleToReplace.key.toString(),
                                nextRuleToReplace.value.fullRule
                            )
                        }
                        substitutedRules.add(nextRuleToReplace.key)
                    }
                }
            }
        } while (evaluatedRules.size != rules.size)
    }

    fun evaluateMessage(message: String): Boolean {
        return rules.get(0)?.matches(message) ?: false
    }
}

Compiled from "Day19MonsterMessage.kt"
public final class adventofcode2020.Day19MonsterMessage {
  public adventofcode2020.Day19MonsterMessage();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package adventofcode2020

class Day07HandyHaversacks

data class Bag(val type: String, val color: String, val canContain: Pair<Bag, Int>?) {
    val bagName: String
        get() = type + " " + color

    fun containsBag(type: String, color: String, count: Int, recursive: Boolean = false): Boolean {
        if (recursive) {
            if (this.type == type && this.color == color) return true
        }
        val result = false
        canContain ?: return false
        val (containingBag, containingCount) = canContain
        if (containingBag.type == type && containingBag.color == color) return true
        else if (containingBag.canContain != null) return containingBag.canContain.first.containsBag(
            type,
            color,
            count,
            recursive = true
        )

        return result
    }

    fun containingBags(): List<Pair<Bag, Int>> {
        val result = mutableListOf<Pair<Bag, Int>>()
        var currentPair = canContain
        while (currentPair != null) {
            result.add(Bag(currentPair.first.type, currentPair.first.color, null) to currentPair.second)
            currentPair = currentPair.first.canContain
        }
        return result
    }

    fun getNumberOfContainingBags(): Int {
        canContain ?: return 1
        return canContain.second + canContain.first.getNumberOfContainingBags()
    }
}

object BagCreator {
    fun createBag(input: String): Bag {
        if (!input.contains(',')) {
            val parts = input.split(" ")
            val type = parts[0]
            val color = parts[1]
            if (parts.size == 3 || parts[4] == "no") return Bag(type, color, null)
            val otherType = parts[5]
            val otherColor = parts[6]
            return Bag(type, color, Pair(Bag(otherType, otherColor, null), parts[4].toInt()))
        } else {
            val subbags = input.split(".")
            val part = subbags[0].trim()
            val parts = part.split(" ")
            val type = parts[0]
            val color = parts[1]
            val count = parts[4]
            val otherType = parts[5]
            val otherColor = parts[6]
            if (subbags.size == 1) {
                return Bag(type, color, Pair(Bag(otherType, otherColor, null), count.toInt()))
            } else {
                val remaining = input.substringAfter(",").trim()
                val (remainingCount, remainingBag) = createBagWithCount(remaining)
                return Bag(
                    type,
                    color,
                    Pair(
                        Bag(
                            otherType,
                            otherColor,
                            Pair(remainingBag, remainingCount)
                        ), count.toInt()
                    )
                )
            }
        }
    }

    fun createBagWithCount(input: String): Pair<Int, Bag> {
        val count = input.first { it.isDigit() }.toString()
        var remaining = input.substring(input.indexOf(count) + 2).trim()
        remaining = remaining.replaceFirst(", ", " contains ")
        return Pair(Integer.parseInt(count), createBag(remaining))
    }
}

data class HandBag(
    val type: String,
    val color: String,
    val canContain: MutableList<Pair<HandBag, Int>> = mutableListOf()
) {
    val name: String
        get() = type + " " + color

    companion object {

        fun from(input: String): HandBag {
            if (!input.contains(',')) {
                val parts = input.split(" ")
                val type = parts[0]
                val color = parts[1]
                if (parts.size == 3 || parts[4] == "no") return HandBag(type, color)
                val otherCount = parts[4].toInt()
                val otherType = parts[5]
                val otherColor = parts[6]
                return HandBag(type, color, mutableListOf(Pair(HandBag(otherType, otherColor), otherCount)))
            } else {
                val firstBag = input.substringBefore("contain").trim().split(" ")
                val result = HandBag(firstBag[0], firstBag[1])
                val subbags = input.substringAfter("contain").trim().split(",")
                val containingBags = mutableListOf<Pair<HandBag, Int>>()
                subbags.forEach { containingBags.add(handBagFromString(it)) }
                result.canContain.addAll(containingBags)
                return result
            }
        }

        private fun handBagFromString(input: String): Pair<HandBag, Int> {
            val parts = input.trim().split(" ")
            return Pair(HandBag(parts[1], parts[2]), parts[0].toInt())
        }
    }
}

Compiled from "Day07HandyHaversacks.kt"
public final class adventofcode2020.Day07HandyHaversacks {
  public adventofcode2020.Day07HandyHaversacks();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package q1_50.q21_30

import java.util.*

/**
 * https://leetcode-cn.com/problems/merge-k-sorted-lists
 */
class Solution23 {
    /**
     * 优先队列
     * 时间复杂度：与分治合并算法一样都是 O(kn×log(k))
     */
    fun mergeKLists(lists: Array<ListNode?>): ListNode? {
        val nodePriorityQueue = PriorityQueue<ListNode> { a, b ->  a.`val` - b.`val`}
        for (node in lists) {
            node?.let { nodePriorityQueue.add(node) }
        }
        val head = ListNode(0)
        var tail = head
        while (nodePriorityQueue.isNotEmpty()) {
            tail.next = nodePriorityQueue.poll()
            tail = tail.next!!
            tail.next?.let { nodePriorityQueue.add(it) }
        }
        return head.next
    }

    /*
     * 分治合并算法
     */
    fun mergeKLists0(lists: Array<ListNode?>): ListNode? {
        fun mergeTwoLinked(n1:ListNode?, n2:ListNode?): ListNode? {
            val head = ListNode(0)
            var tail = head
            var node1 = n1
            var node2 = n2
            while (node1!=null || node2!=null) {
                if (node2 == null || (node1!=null && node1.`val` <= node2.`val`)) {
                    tail.next = node1
                    node1 = node1!!.next
                }else{
                    tail.next = node2
                    node2 = node2.next
                }
                tail = tail.next!!
            }
            return head.next
        }

        fun merging(ls: Array<ListNode?>): ListNode? {
            if (ls.size == 1) return ls[0]
            val mergeArray = arrayOfNulls<ListNode>(if (ls.size % 2 == 0) ls.size / 2 else ls.size / 2 + 1)
            var i = 0
            while (i < ls.size) {
                if (i == ls.size - 1) mergeArray[i / 2] = ls[i]
                else {
                    mergeTwoLinked(ls[i], ls[i+1])?.let { mergeArray[i / 2] = it }
                }
                i += 2
            }
            return merging(mergeArray)
        }
        if (lists.isEmpty()) return null
        return merging(lists)
    }

    class ListNode(var `val`: Int) {
        var next: ListNode? = null
    }
}

Compiled from "Solution23.kt"
public final class q1_50.q21_30.Solution23 {
  public q1_50.q21_30.Solution23();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final q1_50.q21_30.Solution23$ListNode mergeKLists(q1_50.q21_30.Solution23$ListNode[]);
    Code:
       0: aload_1
       1: ldc           #16                 // String lists
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #24                 // class java/util/PriorityQueue
       9: dup
      10: invokedynamic #44,  0             // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function2;
      15: invokedynamic #55,  0             // InvokeDynamic #1:compare:(Lkotlin/jvm/functions/Function2;)Ljava/util/Comparator;
      20: invokespecial #58                 // Method java/util/PriorityQueue."<init>":(Ljava/util/Comparator;)V
      23: astore_2
      24: iconst_0
      25: istore_3
      26: aload_1
      27: arraylength
      28: istore        4
      30: iload_3
      31: iload         4
      33: if_icmpge     70
      36: aload_1
      37: iload_3
      38: aaload
      39: astore        5
      41: aload         5
      43: dup
      44: ifnull        62
      47: astore        6
      49: iconst_0
      50: istore        7
      52: aload_2
      53: aload         5
      55: invokevirtual #62                 // Method java/util/PriorityQueue.add:(Ljava/lang/Object;)Z
      58: pop
      59: goto          64
      62: pop
      63: nop
      64: iinc          3, 1
      67: goto          30
      70: new           #64                 // class q1_50/q21_30/Solution23$ListNode
      73: dup
      74: iconst_0
      75: invokespecial #67                 // Method q1_50/q21_30/Solution23$ListNode."<init>":(I)V
      78: astore_3
      79: aload_3
      80: astore        4
      82: aload_2
      83: checkcast     #69                 // class java/util/Collection
      86: invokeinterface #73,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
      91: ifne          98
      94: iconst_1
      95: goto          99
      98: iconst_0
      99: ifeq          153
     102: aload         4
     104: aload_2
     105: invokevirtual #77                 // Method java/util/PriorityQueue.poll:()Ljava/lang/Object;
     108: checkcast     #64                 // class q1_50/q21_30/Solution23$ListNode
     111: invokevirtual #81                 // Method q1_50/q21_30/Solution23$ListNode.setNext:(Lq1_50/q21_30/Solution23$ListNode;)V
     114: aload         4
     116: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
     119: dup
     120: invokestatic  #89                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     123: astore        4
     125: aload         4
     127: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
     130: dup
     131: ifnull        149
     134: astore        6
     136: iconst_0
     137: istore        7
     139: aload_2
     140: aload         6
     142: invokevirtual #62                 // Method java/util/PriorityQueue.add:(Ljava/lang/Object;)Z
     145: pop
     146: goto          82
     149: pop
     150: goto          82
     153: aload_3
     154: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
     157: areturn

  public final q1_50.q21_30.Solution23$ListNode mergeKLists0(q1_50.q21_30.Solution23$ListNode[]);
    Code:
       0: aload_1
       1: ldc           #16                 // String lists
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: arraylength
       8: ifne          15
      11: iconst_1
      12: goto          16
      15: iconst_0
      16: ifeq          21
      19: aconst_null
      20: areturn
      21: aload_1
      22: invokestatic  #105                // Method mergeKLists0$merging:([Lq1_50/q21_30/Solution23$ListNode;)Lq1_50/q21_30/Solution23$ListNode;
      25: areturn

  private static final int mergeKLists$lambda$0(q1_50.q21_30.Solution23$ListNode, q1_50.q21_30.Solution23$ListNode);
    Code:
       0: aload_0
       1: invokevirtual #109                // Method q1_50/q21_30/Solution23$ListNode.getVal:()I
       4: aload_1
       5: invokevirtual #109                // Method q1_50/q21_30/Solution23$ListNode.getVal:()I
       8: isub
       9: ireturn

  private static final int mergeKLists$lambda$1(kotlin.jvm.functions.Function2, java.lang.Object, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: aload_2
       3: invokeinterface #115,  3          // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
       8: checkcast     #117                // class java/lang/Number
      11: invokevirtual #120                // Method java/lang/Number.intValue:()I
      14: ireturn

  private static final q1_50.q21_30.Solution23$ListNode mergeKLists0$mergeTwoLinked(q1_50.q21_30.Solution23$ListNode, q1_50.q21_30.Solution23$ListNode);
    Code:
       0: new           #64                 // class q1_50/q21_30/Solution23$ListNode
       3: dup
       4: iconst_0
       5: invokespecial #67                 // Method q1_50/q21_30/Solution23$ListNode."<init>":(I)V
       8: astore_2
       9: aload_2
      10: astore_3
      11: aload_0
      12: astore        4
      14: aload_1
      15: astore        5
      17: aload         4
      19: ifnonnull     27
      22: aload         5
      24: ifnull        95
      27: aload         5
      29: ifnull        50
      32: aload         4
      34: ifnull        70
      37: aload         4
      39: invokevirtual #109                // Method q1_50/q21_30/Solution23$ListNode.getVal:()I
      42: aload         5
      44: invokevirtual #109                // Method q1_50/q21_30/Solution23$ListNode.getVal:()I
      47: if_icmpgt     70
      50: aload_3
      51: aload         4
      53: invokevirtual #81                 // Method q1_50/q21_30/Solution23$ListNode.setNext:(Lq1_50/q21_30/Solution23$ListNode;)V
      56: aload         4
      58: dup
      59: invokestatic  #89                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      62: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
      65: astore        4
      67: goto          83
      70: aload_3
      71: aload         5
      73: invokevirtual #81                 // Method q1_50/q21_30/Solution23$ListNode.setNext:(Lq1_50/q21_30/Solution23$ListNode;)V
      76: aload         5
      78: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
      81: astore        5
      83: aload_3
      84: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
      87: dup
      88: invokestatic  #89                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      91: astore_3
      92: goto          17
      95: aload_2
      96: invokevirtual #85                 // Method q1_50/q21_30/Solution23$ListNode.getNext:()Lq1_50/q21_30/Solution23$ListNode;
      99: areturn

  private static final q1_50.q21_30.Solution23$ListNode mergeKLists0$merging(q1_50.q21_30.Solution23$ListNode[]);
    Code:
       0: aload_0
       1: arraylength
       2: iconst_1
       3: if_icmpne     10
       6: aload_0
       7: iconst_0
       8: aaload
       9: areturn
      10: aload_0
      11: arraylength
      12: iconst_2
      13: irem
      14: ifne          24
      17: aload_0
      18: arraylength
      19: iconst_2
      20: idiv
      21: goto          30
      24: aload_0
      25: arraylength
      26: iconst_2
      27: idiv
      28: iconst_1
      29: iadd
      30: anewarray     #64                 // class q1_50/q21_30/Solution23$ListNode
      33: astore_1
      34: iconst_0
      35: istore_2
      36: iload_2
      37: aload_0
      38: arraylength
      39: if_icmpge     98
      42: iload_2
      43: aload_0
      44: arraylength
      45: iconst_1
      46: isub
      47: if_icmpne     61
      50: aload_1
      51: iload_2
      52: iconst_2
      53: idiv
      54: aload_0
      55: iload_2
      56: aaload
      57: aastore
      58: goto          91
      61: aload_0
      62: iload_2
      63: aaload
      64: aload_0
      65: iload_2
      66: iconst_1
      67: iadd
      68: aaload
      69: invokestatic  #133                // Method mergeKLists0$mergeTwoLinked:(Lq1_50/q21_30/Solution23$ListNode;Lq1_50/q21_30/Solution23$ListNode;)Lq1_50/q21_30/Solution23$ListNode;
      72: dup
      73: ifnull        89
      76: astore_3
      77: iconst_0
      78: istore        4
      80: aload_1
      81: iload_2
      82: iconst_2
      83: idiv
      84: aload_3
      85: aastore
      86: goto          91
      89: pop
      90: nop
      91: iload_2
      92: iconst_2
      93: iadd
      94: istore_2
      95: goto          36
      98: aload_1
      99: invokestatic  #105                // Method mergeKLists0$merging:([Lq1_50/q21_30/Solution23$ListNode;)Lq1_50/q21_30/Solution23$ListNode;
     102: areturn
}

Compiled from "Solution23.kt"
public final class q1_50.q21_30.Solution23$ListNode {
  private int val;

  private q1_50.q21_30.Solution23$ListNode next;

  public q1_50.q21_30.Solution23$ListNode(int);
    Code:
       0: aload_0
       1: invokespecial #9                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iload_1
       6: putfield      #13                 // Field val:I
       9: return

  public final int getVal();
    Code:
       0: aload_0
       1: getfield      #13                 // Field val:I
       4: ireturn

  public final void setVal(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #13                 // Field val:I
       5: return

  public final q1_50.q21_30.Solution23$ListNode getNext();
    Code:
       0: aload_0
       1: getfield      #25                 // Field next:Lq1_50/q21_30/Solution23$ListNode;
       4: areturn

  public final void setNext(q1_50.q21_30.Solution23$ListNode);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #25                 // Field next:Lq1_50/q21_30/Solution23$ListNode;
       5: return
}


package q1_50.q11_20

import java.util.*

/**
 * https://leetcode-cn.com/problems/4sum
 */
class Solution18 {
    fun fourSum(nums: IntArray, target: Int): List<List<Int>> {
        val result = LinkedList<List<Int>>()
        if(nums.size < 4) return result
        nums.sort()
        val n = nums.size
        for (i1 in 0 until n - 3) {
            if (i1 > 0 && nums[i1] == nums[i1 - 1]) continue
            if (nums[i1] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target) continue
            if (nums[i1] + nums[i1 + 1] + nums[i1 + 2] + nums[i1 + 3] > target) break
            for (i2 in i1 + 1 until n - 2) {
                if (i2 > i1 + 1 && nums[i2] == nums[i2 - 1]) continue
                if (nums[i1] + nums[i2] + nums[n - 1] + nums[n - 2] < target) continue
                if (nums[i1] + nums[i2] + nums[i2 + 1] + nums[i2 + 2] > target) break
                var i3 = i2 + 1
                var i4 = n - 1
                while (i3 < i4) {
                    if (i3 > i2 + 1 && nums[i3] == nums[i3 - 1]) {
                        i3++
                        continue
                    }
                    if (i4 < n - 1 && nums[i4] == nums[i4 + 1]) {
                        i4--
                        continue
                    }
                    when {
                        nums[i1] + nums[i2] + nums[i3] + nums[i4] < target -> i3++
                        nums[i1] + nums[i2] + nums[i3] + nums[i4] > target -> i4--
                        else -> result.add(listOf(nums[i1], nums[i2], nums[i3++], nums[i4]))
                    }
                }
            }
        }
        return result
    }
}

Compiled from "Solution18.kt"
public final class q1_50.q11_20.Solution18 {
  public q1_50.q11_20.Solution18();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final java.util.List<java.util.List<java.lang.Integer>> fourSum(int[], int);
    Code:
       0: aload_1
       1: ldc           #16                 // String nums
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #24                 // class java/util/LinkedList
       9: dup
      10: invokespecial #25                 // Method java/util/LinkedList."<init>":()V
      13: astore_3
      14: aload_1
      15: arraylength
      16: iconst_4
      17: if_icmpge     25
      20: aload_3
      21: checkcast     #27                 // class java/util/List
      24: areturn
      25: aload_1
      26: invokestatic  #33                 // Method kotlin/collections/ArraysKt.sort:([I)V
      29: aload_1
      30: arraylength
      31: istore        4
      33: iconst_0
      34: istore        5
      36: iload         4
      38: iconst_3
      39: isub
      40: istore        6
      42: iload         5
      44: iload         6
      46: if_icmpge     438
      49: iload         5
      51: ifle          67
      54: aload_1
      55: iload         5
      57: iaload
      58: aload_1
      59: iload         5
      61: iconst_1
      62: isub
      63: iaload
      64: if_icmpeq     432
      67: aload_1
      68: iload         5
      70: iaload
      71: aload_1
      72: iload         4
      74: iconst_1
      75: isub
      76: iaload
      77: iadd
      78: aload_1
      79: iload         4
      81: iconst_2
      82: isub
      83: iaload
      84: iadd
      85: aload_1
      86: iload         4
      88: iconst_3
      89: isub
      90: iaload
      91: iadd
      92: iload_2
      93: if_icmplt     432
      96: aload_1
      97: iload         5
      99: iaload
     100: aload_1
     101: iload         5
     103: iconst_1
     104: iadd
     105: iaload
     106: iadd
     107: aload_1
     108: iload         5
     110: iconst_2
     111: iadd
     112: iaload
     113: iadd
     114: aload_1
     115: iload         5
     117: iconst_3
     118: iadd
     119: iaload
     120: iadd
     121: iload_2
     122: if_icmpgt     438
     125: iload         5
     127: iconst_1
     128: iadd
     129: istore        7
     131: iload         4
     133: iconst_2
     134: isub
     135: istore        8
     137: iload         7
     139: iload         8
     141: if_icmpge     432
     144: iload         7
     146: iload         5
     148: iconst_1
     149: iadd
     150: if_icmple     166
     153: aload_1
     154: iload         7
     156: iaload
     157: aload_1
     158: iload         7
     160: iconst_1
     161: isub
     162: iaload
     163: if_icmpeq     426
     166: aload_1
     167: iload         5
     169: iaload
     170: aload_1
     171: iload         7
     173: iaload
     174: iadd
     175: aload_1
     176: iload         4
     178: iconst_1
     179: isub
     180: iaload
     181: iadd
     182: aload_1
     183: iload         4
     185: iconst_2
     186: isub
     187: iaload
     188: iadd
     189: iload_2
     190: if_icmplt     426
     193: aload_1
     194: iload         5
     196: iaload
     197: aload_1
     198: iload         7
     200: iaload
     201: iadd
     202: aload_1
     203: iload         7
     205: iconst_1
     206: iadd
     207: iaload
     208: iadd
     209: aload_1
     210: iload         7
     212: iconst_2
     213: iadd
     214: iaload
     215: iadd
     216: iload_2
     217: if_icmpgt     432
     220: iload         7
     222: iconst_1
     223: iadd
     224: istore        9
     226: iload         4
     228: iconst_1
     229: isub
     230: istore        10
     232: iload         9
     234: iload         10
     236: if_icmpge     426
     239: iload         9
     241: iload         7
     243: iconst_1
     244: iadd
     245: if_icmple     267
     248: aload_1
     249: iload         9
     251: iaload
     252: aload_1
     253: iload         9
     255: iconst_1
     256: isub
     257: iaload
     258: if_icmpne     267
     261: iinc          9, 1
     264: goto          232
     267: iload         10
     269: iload         4
     271: iconst_1
     272: isub
     273: if_icmpge     295
     276: aload_1
     277: iload         10
     279: iaload
     280: aload_1
     281: iload         10
     283: iconst_1
     284: iadd
     285: iaload
     286: if_icmpne     295
     289: iinc          10, -1
     292: goto          232
     295: nop
     296: aload_1
     297: iload         5
     299: iaload
     300: aload_1
     301: iload         7
     303: iaload
     304: iadd
     305: aload_1
     306: iload         9
     308: iaload
     309: iadd
     310: aload_1
     311: iload         10
     313: iaload
     314: iadd
     315: iload_2
     316: if_icmpge     328
     319: iload         9
     321: iinc          9, 1
     324: pop
     325: goto          232
     328: aload_1
     329: iload         5
     331: iaload
     332: aload_1
     333: iload         7
     335: iaload
     336: iadd
     337: aload_1
     338: iload         9
     340: iaload
     341: iadd
     342: aload_1
     343: iload         10
     345: iaload
     346: iadd
     347: iload_2
     348: if_icmple     360
     351: iload         10
     353: iinc          10, -1
     356: pop
     357: goto          232
     360: aload_3
     361: iconst_4
     362: anewarray     #35                 // class java/lang/Integer
     365: astore        11
     367: aload         11
     369: iconst_0
     370: aload_1
     371: iload         5
     373: iaload
     374: invokestatic  #39                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     377: aastore
     378: aload         11
     380: iconst_1
     381: aload_1
     382: iload         7
     384: iaload
     385: invokestatic  #39                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     388: aastore
     389: aload         11
     391: iconst_2
     392: aload_1
     393: iload         9
     395: iinc          9, 1
     398: iaload
     399: invokestatic  #39                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     402: aastore
     403: aload         11
     405: iconst_3
     406: aload_1
     407: iload         10
     409: iaload
     410: invokestatic  #39                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     413: aastore
     414: aload         11
     416: invokestatic  #45                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     419: invokevirtual #49                 // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
     422: pop
     423: goto          232
     426: iinc          7, 1
     429: goto          137
     432: iinc          5, 1
     435: goto          42
     438: aload_3
     439: checkcast     #27                 // class java/util/List
     442: areturn
}


package q51_100.q61_70

/**
 * https://leetcode-cn.com/problems/climbing-stairs/
 */
class Solution70 {

    /**
     * f(x) = f(x1) + f(x2)
     *
     * f(x1) = 最后一步为 1 个台阶的个数 = f(x - 1)
     * f(x2) = 最后一步为 2 个台阶的个数 = f(x - 2)
     *
     * f(x) = f(x-1) + f(x-2)
     *
     * 矩阵快速幂
     *
     * M^n * [1, 1].h = [f(n + 1), f(n)].h
     *
     * M^n = [f(n), f(n-1)]
     */
    fun climbStairs(n: Int): Int {
        val m = arrayOf(
            arrayOf(1, 1),
            arrayOf(1, 0)
        )
        var un = n
        val r = arrayOf(
            arrayOf(1, 0),
            arrayOf(0, 1)
        )
        while (un != 0) {
            if (un.and(1) == 1) matrix(m, r, r)
            matrix(m, m, m)
            un = un shr 1
        }
        return r[0][0]
    }

    private fun matrix(x: Array<Array<Int>>, y: Array<Array<Int>>, save: Array<Array<Int>>) {
        val v1 = x[0][0] * y[0][0] + x[0][1] * y[1][0]
        val v2 = x[0][0] * y[0][1] + x[0][1] * y[1][1]
        val v3 = x[1][0] * y[0][0] + x[1][1] * y[1][0]
        val v4 = x[1][0] * y[0][1] + x[1][1] * y[1][1]
        save[0][0] = v1
        save[0][1] = v2
        save[1][0] = v3
        save[1][1] = v4
    }
}

Compiled from "Solution70.kt"
public final class q51_100.q61_70.Solution70 {
  public q51_100.q61_70.Solution70();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final int climbStairs(int);
    Code:
       0: iconst_2
       1: anewarray     #14                 // class "[Ljava/lang/Integer;"
       4: astore_3
       5: aload_3
       6: iconst_0
       7: iconst_2
       8: anewarray     #16                 // class java/lang/Integer
      11: astore        4
      13: aload         4
      15: iconst_0
      16: iconst_1
      17: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      20: aastore
      21: aload         4
      23: iconst_1
      24: iconst_1
      25: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      28: aastore
      29: aload         4
      31: aastore
      32: aload_3
      33: iconst_1
      34: iconst_2
      35: anewarray     #16                 // class java/lang/Integer
      38: astore        4
      40: aload         4
      42: iconst_0
      43: iconst_1
      44: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      47: aastore
      48: aload         4
      50: iconst_1
      51: iconst_0
      52: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      55: aastore
      56: aload         4
      58: aastore
      59: aload_3
      60: astore_2
      61: iload_1
      62: istore_3
      63: iconst_2
      64: anewarray     #14                 // class "[Ljava/lang/Integer;"
      67: astore        5
      69: aload         5
      71: iconst_0
      72: iconst_2
      73: anewarray     #16                 // class java/lang/Integer
      76: astore        6
      78: aload         6
      80: iconst_0
      81: iconst_1
      82: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      85: aastore
      86: aload         6
      88: iconst_1
      89: iconst_0
      90: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      93: aastore
      94: aload         6
      96: aastore
      97: aload         5
      99: iconst_1
     100: iconst_2
     101: anewarray     #16                 // class java/lang/Integer
     104: astore        6
     106: aload         6
     108: iconst_0
     109: iconst_0
     110: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     113: aastore
     114: aload         6
     116: iconst_1
     117: iconst_1
     118: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     121: aastore
     122: aload         6
     124: aastore
     125: aload         5
     127: astore        4
     129: iload_3
     130: ifeq          163
     133: iload_3
     134: iconst_1
     135: iand
     136: iconst_1
     137: if_icmpne     149
     140: aload_0
     141: aload_2
     142: aload         4
     144: aload         4
     146: invokespecial #24                 // Method matrix:([[Ljava/lang/Integer;[[Ljava/lang/Integer;[[Ljava/lang/Integer;)V
     149: aload_0
     150: aload_2
     151: aload_2
     152: aload_2
     153: invokespecial #24                 // Method matrix:([[Ljava/lang/Integer;[[Ljava/lang/Integer;[[Ljava/lang/Integer;)V
     156: iload_3
     157: iconst_1
     158: ishr
     159: istore_3
     160: goto          129
     163: aload         4
     165: iconst_0
     166: aaload
     167: iconst_0
     168: aaload
     169: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     172: ireturn

  private final void matrix(java.lang.Integer[][], java.lang.Integer[][], java.lang.Integer[][]);
    Code:
       0: aload_1
       1: iconst_0
       2: aaload
       3: iconst_0
       4: aaload
       5: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
       8: aload_2
       9: iconst_0
      10: aaload
      11: iconst_0
      12: aaload
      13: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      16: imul
      17: aload_1
      18: iconst_0
      19: aaload
      20: iconst_1
      21: aaload
      22: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      25: aload_2
      26: iconst_1
      27: aaload
      28: iconst_0
      29: aaload
      30: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      33: imul
      34: iadd
      35: istore        4
      37: aload_1
      38: iconst_0
      39: aaload
      40: iconst_0
      41: aaload
      42: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      45: aload_2
      46: iconst_0
      47: aaload
      48: iconst_1
      49: aaload
      50: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      53: imul
      54: aload_1
      55: iconst_0
      56: aaload
      57: iconst_1
      58: aaload
      59: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      62: aload_2
      63: iconst_1
      64: aaload
      65: iconst_1
      66: aaload
      67: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      70: imul
      71: iadd
      72: istore        5
      74: aload_1
      75: iconst_1
      76: aaload
      77: iconst_0
      78: aaload
      79: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      82: aload_2
      83: iconst_0
      84: aaload
      85: iconst_0
      86: aaload
      87: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      90: imul
      91: aload_1
      92: iconst_1
      93: aaload
      94: iconst_1
      95: aaload
      96: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
      99: aload_2
     100: iconst_1
     101: aaload
     102: iconst_0
     103: aaload
     104: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     107: imul
     108: iadd
     109: istore        6
     111: aload_1
     112: iconst_1
     113: aaload
     114: iconst_0
     115: aaload
     116: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     119: aload_2
     120: iconst_0
     121: aaload
     122: iconst_1
     123: aaload
     124: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     127: imul
     128: aload_1
     129: iconst_1
     130: aaload
     131: iconst_1
     132: aaload
     133: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     136: aload_2
     137: iconst_1
     138: aaload
     139: iconst_1
     140: aaload
     141: invokevirtual #28                 // Method java/lang/Integer.intValue:()I
     144: imul
     145: iadd
     146: istore        7
     148: aload_3
     149: iconst_0
     150: aaload
     151: iconst_0
     152: iload         4
     154: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     157: aastore
     158: aload_3
     159: iconst_0
     160: aaload
     161: iconst_1
     162: iload         5
     164: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     167: aastore
     168: aload_3
     169: iconst_1
     170: aaload
     171: iconst_0
     172: iload         6
     174: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     177: aastore
     178: aload_3
     179: iconst_1
     180: aaload
     181: iconst_1
     182: iload         7
     184: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     187: aastore
     188: return
}