import java.util.*
import java.util.concurrent.locks.Lock

fun isValidTriangle(values: List<Int>): Boolean =
        values[0] + values[1] > values[2] &&
                values[0] + values[2] > values[1] &&
                values[1] + values[2] > values[0]

inline fun <reified T> List<T>.grouped(by: Int): List<List<T>> {
    require(by > 0) { "Groupings can't be less than 1" }
    return if (isEmpty()) {
        emptyList()
    } else {
        (0..lastIndex / by).map {
            val fromIndex = it * by
            val toIndex = Math.min(fromIndex + by, this.size)
            subList(fromIndex, toIndex)
        }
    }
}

/**
 * Not a very good transpose function. Works for squares though...
 */
inline fun <reified T> transpose(values: List<List<T>>): List<List<T>> {
    return values.indices.map { i -> values[0].indices.map { values[it][i] } }
}

fun randomSequence(upper: Int = 10, lower: Int = 0): List<Int> {
    return (lower..upper).distinct().toMutableList().apply { Collections.shuffle(this) }
}

fun <T> List<T>.pickRandom(num: Int = 4): List<T> {
    return randomSequence(upper = this.size, lower = 0).take(num).map { this[it] }
}

Compiled from "Extensions.kt"
public final class ExtensionsKt {
  public static final boolean isValidTriangle(java.util.List<java.lang.Integer>);
    Code:
       0: aload_0
       1: ldc           #10                 // String values
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iconst_0
       8: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      13: checkcast     #24                 // class java/lang/Number
      16: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      19: aload_0
      20: iconst_1
      21: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      26: checkcast     #24                 // class java/lang/Number
      29: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      32: iadd
      33: aload_0
      34: iconst_2
      35: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      40: checkcast     #24                 // class java/lang/Number
      43: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      46: if_icmple     139
      49: aload_0
      50: iconst_0
      51: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      56: checkcast     #24                 // class java/lang/Number
      59: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      62: aload_0
      63: iconst_2
      64: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      69: checkcast     #24                 // class java/lang/Number
      72: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      75: iadd
      76: aload_0
      77: iconst_1
      78: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      83: checkcast     #24                 // class java/lang/Number
      86: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      89: if_icmple     139
      92: aload_0
      93: iconst_1
      94: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      99: checkcast     #24                 // class java/lang/Number
     102: invokevirtual #28                 // Method java/lang/Number.intValue:()I
     105: aload_0
     106: iconst_2
     107: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     112: checkcast     #24                 // class java/lang/Number
     115: invokevirtual #28                 // Method java/lang/Number.intValue:()I
     118: iadd
     119: aload_0
     120: iconst_0
     121: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     126: checkcast     #24                 // class java/lang/Number
     129: invokevirtual #28                 // Method java/lang/Number.intValue:()I
     132: if_icmple     139
     135: iconst_1
     136: goto          140
     139: iconst_0
     140: ireturn

  public static final <T> java.util.List<java.util.List<T>> grouped(java.util.List<? extends T>, int);
    Code:
       0: aload_0
       1: ldc           #34                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_2
       8: iload_1
       9: ifle          16
      12: iconst_1
      13: goto          17
      16: iconst_0
      17: ifne          40
      20: iconst_0
      21: istore        4
      23: ldc           #36                 // String Groupings can\'t be less than 1
      25: astore        4
      27: new           #38                 // class java/lang/IllegalArgumentException
      30: dup
      31: aload         4
      33: invokevirtual #42                 // Method java/lang/Object.toString:()Ljava/lang/String;
      36: invokespecial #46                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      39: athrow
      40: aload_0
      41: invokeinterface #50,  1           // InterfaceMethod java/util/List.isEmpty:()Z
      46: ifeq          55
      49: invokestatic  #56                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      52: goto          189
      55: new           #58                 // class kotlin/ranges/IntRange
      58: dup
      59: iconst_0
      60: aload_0
      61: invokestatic  #62                 // Method kotlin/collections/CollectionsKt.getLastIndex:(Ljava/util/List;)I
      64: iload_1
      65: idiv
      66: invokespecial #65                 // Method kotlin/ranges/IntRange."<init>":(II)V
      69: checkcast     #67                 // class java/lang/Iterable
      72: astore_3
      73: iconst_0
      74: istore        4
      76: aload_3
      77: astore        5
      79: new           #69                 // class java/util/ArrayList
      82: dup
      83: aload_3
      84: bipush        10
      86: invokestatic  #73                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      89: invokespecial #76                 // Method java/util/ArrayList."<init>":(I)V
      92: checkcast     #78                 // class java/util/Collection
      95: astore        6
      97: iconst_0
      98: istore        7
     100: aload         5
     102: invokeinterface #82,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     107: astore        8
     109: aload         8
     111: invokeinterface #87,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     116: ifeq          183
     119: aload         8
     121: checkcast     #89                 // class kotlin/collections/IntIterator
     124: invokevirtual #92                 // Method kotlin/collections/IntIterator.nextInt:()I
     127: istore        9
     129: aload         6
     131: iload         9
     133: istore        10
     135: astore        14
     137: iconst_0
     138: istore        11
     140: iload         10
     142: iload_1
     143: imul
     144: istore        12
     146: iload         12
     148: iload_1
     149: iadd
     150: aload_0
     151: invokeinterface #95,  1           // InterfaceMethod java/util/List.size:()I
     156: invokestatic  #101                // Method java/lang/Math.min:(II)I
     159: istore        13
     161: aload_0
     162: iload         12
     164: iload         13
     166: invokeinterface #105,  3          // InterfaceMethod java/util/List.subList:(II)Ljava/util/List;
     171: aload         14
     173: swap
     174: invokeinterface #109,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     179: pop
     180: goto          109
     183: aload         6
     185: checkcast     #18                 // class java/util/List
     188: nop
     189: areturn

  public static final <T> java.util.List<java.util.List<T>> transpose(java.util.List<? extends java.util.List<? extends T>>);
    Code:
       0: aload_0
       1: ldc           #10                 // String values
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_1
       8: aload_0
       9: checkcast     #78                 // class java/util/Collection
      12: invokestatic  #133                // Method kotlin/collections/CollectionsKt.getIndices:(Ljava/util/Collection;)Lkotlin/ranges/IntRange;
      15: checkcast     #67                 // class java/lang/Iterable
      18: astore_2
      19: iconst_0
      20: istore_3
      21: aload_2
      22: astore        4
      24: new           #69                 // class java/util/ArrayList
      27: dup
      28: aload_2
      29: bipush        10
      31: invokestatic  #73                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      34: invokespecial #76                 // Method java/util/ArrayList."<init>":(I)V
      37: checkcast     #78                 // class java/util/Collection
      40: astore        5
      42: iconst_0
      43: istore        6
      45: aload         4
      47: invokeinterface #82,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      52: astore        7
      54: aload         7
      56: invokeinterface #87,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      61: ifeq          221
      64: aload         7
      66: checkcast     #89                 // class kotlin/collections/IntIterator
      69: invokevirtual #92                 // Method kotlin/collections/IntIterator.nextInt:()I
      72: istore        8
      74: aload         5
      76: iload         8
      78: istore        9
      80: astore        21
      82: iconst_0
      83: istore        10
      85: aload_0
      86: iconst_0
      87: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      92: checkcast     #78                 // class java/util/Collection
      95: invokestatic  #133                // Method kotlin/collections/CollectionsKt.getIndices:(Ljava/util/Collection;)Lkotlin/ranges/IntRange;
      98: checkcast     #67                 // class java/lang/Iterable
     101: astore        11
     103: iconst_0
     104: istore        12
     106: aload         11
     108: astore        13
     110: new           #69                 // class java/util/ArrayList
     113: dup
     114: aload         11
     116: bipush        10
     118: invokestatic  #73                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     121: invokespecial #76                 // Method java/util/ArrayList."<init>":(I)V
     124: checkcast     #78                 // class java/util/Collection
     127: astore        14
     129: iconst_0
     130: istore        15
     132: aload         13
     134: invokeinterface #82,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     139: astore        16
     141: aload         16
     143: invokeinterface #87,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     148: ifeq          202
     151: aload         16
     153: checkcast     #89                 // class kotlin/collections/IntIterator
     156: invokevirtual #92                 // Method kotlin/collections/IntIterator.nextInt:()I
     159: istore        17
     161: aload         14
     163: iload         17
     165: istore        18
     167: astore        19
     169: iconst_0
     170: istore        20
     172: aload_0
     173: iload         18
     175: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     180: checkcast     #18                 // class java/util/List
     183: iload         9
     185: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     190: aload         19
     192: swap
     193: invokeinterface #109,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     198: pop
     199: goto          141
     202: aload         14
     204: checkcast     #18                 // class java/util/List
     207: nop
     208: nop
     209: aload         21
     211: swap
     212: invokeinterface #109,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     217: pop
     218: goto          54
     221: aload         5
     223: checkcast     #18                 // class java/util/List
     226: nop
     227: areturn

  public static final java.util.List<java.lang.Integer> randomSequence(int, int);
    Code:
       0: new           #58                 // class kotlin/ranges/IntRange
       3: dup
       4: iload_1
       5: iload_0
       6: invokespecial #65                 // Method kotlin/ranges/IntRange."<init>":(II)V
       9: checkcast     #67                 // class java/lang/Iterable
      12: invokestatic  #143                // Method kotlin/collections/CollectionsKt.distinct:(Ljava/lang/Iterable;)Ljava/util/List;
      15: checkcast     #78                 // class java/util/Collection
      18: invokestatic  #147                // Method kotlin/collections/CollectionsKt.toMutableList:(Ljava/util/Collection;)Ljava/util/List;
      21: astore_2
      22: aload_2
      23: astore_3
      24: iconst_0
      25: istore        4
      27: aload_3
      28: invokestatic  #153                // Method java/util/Collections.shuffle:(Ljava/util/List;)V
      31: aload_2
      32: areturn

  public static java.util.List randomSequence$default(int, int, int, java.lang.Object);
    Code:
       0: iload_2
       1: iconst_1
       2: iand
       3: ifeq          9
       6: bipush        10
       8: istore_0
       9: iload_2
      10: iconst_2
      11: iand
      12: ifeq          17
      15: iconst_0
      16: istore_1
      17: iload_0
      18: iload_1
      19: invokestatic  #161                // Method randomSequence:(II)Ljava/util/List;
      22: areturn

  public static final <T> java.util.List<T> pickRandom(java.util.List<? extends T>, int);
    Code:
       0: aload_0
       1: ldc           #34                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokeinterface #95,  1           // InterfaceMethod java/util/List.size:()I
      12: iconst_0
      13: invokestatic  #161                // Method randomSequence:(II)Ljava/util/List;
      16: checkcast     #67                 // class java/lang/Iterable
      19: iload_1
      20: invokestatic  #167                // Method kotlin/collections/CollectionsKt.take:(Ljava/lang/Iterable;I)Ljava/util/List;
      23: checkcast     #67                 // class java/lang/Iterable
      26: astore_2
      27: iconst_0
      28: istore_3
      29: aload_2
      30: astore        4
      32: new           #69                 // class java/util/ArrayList
      35: dup
      36: aload_2
      37: bipush        10
      39: invokestatic  #73                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      42: invokespecial #76                 // Method java/util/ArrayList."<init>":(I)V
      45: checkcast     #78                 // class java/util/Collection
      48: astore        5
      50: iconst_0
      51: istore        6
      53: aload         4
      55: invokeinterface #82,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      60: astore        7
      62: aload         7
      64: invokeinterface #87,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      69: ifeq          118
      72: aload         7
      74: invokeinterface #171,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      79: astore        8
      81: aload         5
      83: aload         8
      85: checkcast     #24                 // class java/lang/Number
      88: invokevirtual #28                 // Method java/lang/Number.intValue:()I
      91: istore        9
      93: astore        11
      95: iconst_0
      96: istore        10
      98: aload_0
      99: iload         9
     101: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     106: aload         11
     108: swap
     109: invokeinterface #109,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     114: pop
     115: goto          62
     118: aload         5
     120: checkcast     #18                 // class java/util/List
     123: nop
     124: areturn

  public static java.util.List pickRandom$default(java.util.List, int, int, java.lang.Object);
    Code:
       0: iload_2
       1: iconst_1
       2: iand
       3: ifeq          8
       6: iconst_4
       7: istore_1
       8: aload_0
       9: iload_1
      10: invokestatic  #179                // Method pickRandom:(Ljava/util/List;I)Ljava/util/List;
      13: areturn
}


import kotlin.math.sqrt

/**
 * https://www.youtube.com/watch?v=V08g_lkKj6Q
 */
class EratosthenesSieve(n: Int) {
    val numbers: List<Boolean>

    init {
        val numbersArray = BooleanArray(n + 1)
        numbersArray.fill(true)

        var potentialPrime = 2
        while (potentialPrime * potentialPrime <= n) {
            // If prime[p] is not changed, then it is a prime
            if (numbersArray[potentialPrime]) { // Update all multiples of p

                var nextPow = potentialPrime * potentialPrime
                while (nextPow <= n) {
                    numbersArray[nextPow] = false
                    nextPow += potentialPrime
                }
            }
            potentialPrime++
        }

        numbers = numbersArray.toList()
    }

    fun isPrime(n: Int): Boolean {
        return numbers[n]
    }
}

object PrimeFactorization {
    private val incrementFunc: (t: Long, u: Long?) -> Long? = { _, old -> if (old == null) 1L else old + 1L }

    fun primeFactors(n: Long): Map<Long, Long> {
        val numberToPower = hashMapOf<Long, Long>()

        // Add the number of 2s that divide n.
        var number = n
        while (number % 2L == 0L) {
            numberToPower.compute(2L, incrementFunc)

            number /= 2L
        }

        // n must be odd at this point.  So we can
        // skip one element (Note i = i +2) as per sieve of Eratosthenes.
        var i = 3L
        while (i <= sqrt(number.toDouble())) {

            // While i divides n, add i and divide n
            while (number % i == 0L) {
                numberToPower.compute(i, incrementFunc)

                number /= i
            }
            i += 2L
        }

        // This condition is to handle the case when
        // n is a prime number greater than 2
        if (number > 2L) {
            numberToPower.compute(number, incrementFunc)
        }
        return numberToPower
    }
}

/**
 * σ0(N)
 * https://en.wikipedia.org/wiki/Divisor_function
 */
fun Long.dividers(): Long {
    var dividers = 1L
    val numberToPower = PrimeFactorization.primeFactors(this)

    for (entry in numberToPower) {
        dividers *= (entry.value + 1)
    }

    return dividers
}

fun Long.sequenceSumStartingFrom(a0: Long): Long {
    return sumFromTo(a0, this)
}

fun sumFromTo(a0: Long, aN: Long): Long {
    val n = aN - a0 + 1
    return (n.toDouble() / 2.0 * (a0 + aN)).toLong()
}

Compiled from "Utils.kt"
public final class UtilsKt {
  public static final long dividers(long);
    Code:
       0: lconst_1
       1: lstore_2
       2: getstatic     #12                 // Field PrimeFactorization.INSTANCE:LPrimeFactorization;
       5: lload_0
       6: invokevirtual #16                 // Method PrimeFactorization.primeFactors:(J)Ljava/util/Map;
       9: astore        4
      11: aload         4
      13: invokeinterface #22,  1           // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
      18: invokeinterface #28,  1           // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
      23: astore        5
      25: aload         5
      27: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      32: ifeq          68
      35: aload         5
      37: invokeinterface #38,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      42: checkcast     #40                 // class java/util/Map$Entry
      45: astore        6
      47: lload_2
      48: aload         6
      50: invokeinterface #43,  1           // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
      55: checkcast     #45                 // class java/lang/Number
      58: invokevirtual #49                 // Method java/lang/Number.longValue:()J
      61: lconst_1
      62: ladd
      63: lmul
      64: lstore_2
      65: goto          25
      68: lload_2
      69: lreturn

  public static final long sequenceSumStartingFrom(long, long);
    Code:
       0: lload_2
       1: lload_0
       2: invokestatic  #60                 // Method sumFromTo:(JJ)J
       5: lreturn

  public static final long sumFromTo(long, long);
    Code:
       0: lload_2
       1: lload_0
       2: lsub
       3: lconst_1
       4: ladd
       5: lstore        4
       7: lload         4
       9: l2d
      10: ldc2_w        #63                 // double 2.0d
      13: ddiv
      14: lload_0
      15: lload_2
      16: ladd
      17: l2d
      18: dmul
      19: d2l
      20: lreturn
}


fun main(args: Array<String>) {
    println("Res: " + findSolution())
}

/**
The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.
 */
private fun findSolution(): Long {
    val startingPoint = 999_999L
    var maxChain = 0L
    var startingPointWithMaxChain = 0L

    for (x in startingPoint downTo 1L) {
        val collatzSequence = collatzSequence(x)
        if (collatzSequence > maxChain) {
            maxChain = collatzSequence
            startingPointWithMaxChain = x
        }

    }

    return startingPointWithMaxChain
}

fun collatzSequence(startingPoint: Long): Long {
    var result = 1L
    var number = startingPoint
    while (number != 1L) {

        number = nextCollatzNumber(number)
        result++
    }

    return result
}

fun nextCollatzNumber(n: Long): Long {
    return if (n % 2 == 0L) n / 2 else (n * 3) + 1
}

Compiled from "P14LongestCollatzSequence.kt"
public final class P14LongestCollatzSequenceKt {
  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #9                  // String args
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #17                 // class java/lang/StringBuilder
       9: dup
      10: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #23                 // String Res:
      15: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: invokestatic  #31                 // Method findSolution:()J
      21: invokevirtual #34                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      24: invokevirtual #38                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: getstatic     #44                 // Field java/lang/System.out:Ljava/io/PrintStream;
      30: swap
      31: invokevirtual #50                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      34: return

  private static final long findSolution();
    Code:
       0: ldc2_w        #52                 // long 999999l
       3: lstore_0
       4: lconst_0
       5: lstore_2
       6: lconst_0
       7: lstore        4
       9: lload_0
      10: lstore        6
      12: lconst_0
      13: lload         6
      15: lcmp
      16: ifge          51
      19: lload         6
      21: invokestatic  #57                 // Method collatzSequence:(J)J
      24: lstore        8
      26: lload         8
      28: lload_2
      29: lcmp
      30: ifle          40
      33: lload         8
      35: lstore_2
      36: lload         6
      38: lstore        4
      40: lload         6
      42: ldc2_w        #58                 // long -1l
      45: ladd
      46: lstore        6
      48: goto          12
      51: lload         4
      53: lreturn

  public static final long collatzSequence(long);
    Code:
       0: lconst_1
       1: lstore_2
       2: lload_0
       3: lstore        4
       5: lload         4
       7: lconst_1
       8: lcmp
       9: ifeq          30
      12: lload         4
      14: invokestatic  #67                 // Method nextCollatzNumber:(J)J
      17: lstore        4
      19: lload_2
      20: lstore        6
      22: lload         6
      24: lconst_1
      25: ladd
      26: lstore_2
      27: goto          5
      30: lload_2
      31: lreturn

  public static final long nextCollatzNumber(long);
    Code:
       0: lload_0
       1: iconst_2
       2: i2l
       3: lrem
       4: lconst_0
       5: lcmp
       6: ifne          16
       9: lload_0
      10: iconst_2
      11: i2l
      12: ldiv
      13: goto          22
      16: lload_0
      17: iconst_3
      18: i2l
      19: lmul
      20: lconst_1
      21: ladd
      22: lreturn
}


fun main(args: Array<String>) {
    println("Res: " + findSolution())
}

/**
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Let us list the factors of the first seven triangle numbers:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?

Res:76576500
Solution: σ0(N)
https://en.wikipedia.org/wiki/Prime_omega_function
 */
private fun findSolution(): Long {
    val min = 10000 // 28 has 5
    val nThTriangleNumber = Long.MAX_VALUE

    for (nTh in min..nThTriangleNumber) {
        val triangleNumber = nTh.sequenceSumStartingFrom(1)
        if (triangleNumber % 2 != 0L && triangleNumber % 5 != 0L) {
            println(triangleNumber)
            continue
        }

        val numberOfDividers = triangleNumber.dividers()
        if (numberOfDividers >= 500L) {
            return triangleNumber
        }
    }

    return -1
}

Compiled from "P12HighlyDivisibleTriangularNumber.kt"
public final class P12HighlyDivisibleTriangularNumberKt {
  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #9                  // String args
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #17                 // class java/lang/StringBuilder
       9: dup
      10: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #23                 // String Res:
      15: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: invokestatic  #31                 // Method findSolution:()J
      21: invokevirtual #34                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      24: invokevirtual #38                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: getstatic     #44                 // Field java/lang/System.out:Ljava/io/PrintStream;
      30: swap
      31: invokevirtual #50                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      34: return

  private static final long findSolution();
    Code:
       0: sipush        10000
       3: istore_0
       4: ldc2_w        #52                 // long 9223372036854775807l
       7: lstore_1
       8: iload_0
       9: i2l
      10: lstore_3
      11: lload_3
      12: lload_1
      13: lcmp
      14: ifgt          87
      17: lload_3
      18: lconst_1
      19: invokestatic  #59                 // Method UtilsKt.sequenceSumStartingFrom:(JJ)J
      22: lstore        5
      24: lload         5
      26: iconst_2
      27: i2l
      28: lrem
      29: lconst_0
      30: lcmp
      31: ifeq          55
      34: lload         5
      36: iconst_5
      37: i2l
      38: lrem
      39: lconst_0
      40: lcmp
      41: ifeq          55
      44: getstatic     #44                 // Field java/lang/System.out:Ljava/io/PrintStream;
      47: lload         5
      49: invokevirtual #62                 // Method java/io/PrintStream.println:(J)V
      52: goto          74
      55: lload         5
      57: invokestatic  #66                 // Method UtilsKt.dividers:(J)J
      60: lstore        7
      62: lload         7
      64: ldc2_w        #67                 // long 500l
      67: lcmp
      68: iflt          74
      71: lload         5
      73: lreturn
      74: lload_3
      75: lload_1
      76: lcmp
      77: ifeq          87
      80: lload_3
      81: lconst_1
      82: ladd
      83: lstore_3
      84: goto          17
      87: ldc2_w        #69                 // long -1l
      90: lreturn
}


fun main(args: Array<String>) {
    println("Res: " + largestLargestPalindromeProduct())
}

/**
 * A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
 * Find the largest palindrome made from the product of two 3-digit numbers.
 */
private fun largestLargestPalindromeProduct(): Int {
    val largest = 999
    val smallest = 100
    // largest number * largest number could be the first largest palindrome result
    val palindrome = largest * largest

    for (x in palindrome downTo 1) {
        for (b in largest downTo smallest step 1) {
            val a = x / b;
            if (x % b == 0 && a <= largest && a >= smallest && isPalindrome(x.toString())) {
                return x
            }
        }
    }

    return 0
}

fun isPalindrome(palindrome: String): Boolean {
    var isPalindrome = true
    for (ch in 0 until (palindrome.length / 2) step 1) {
        isPalindrome = isPalindrome && palindrome[ch] == palindrome[palindrome.length - 1 - ch]
    }
    return isPalindrome;
}

Compiled from "P4LargersPalindromOf3Digits.kt"
public final class P4LargersPalindromOf3DigitsKt {
  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #9                  // String args
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #17                 // class java/lang/StringBuilder
       9: dup
      10: invokespecial #21                 // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #23                 // String Res:
      15: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: invokestatic  #31                 // Method largestLargestPalindromeProduct:()I
      21: invokevirtual #34                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      24: invokevirtual #38                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: getstatic     #44                 // Field java/lang/System.out:Ljava/io/PrintStream;
      30: swap
      31: invokevirtual #50                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      34: return

  private static final int largestLargestPalindromeProduct();
    Code:
       0: sipush        999
       3: istore_0
       4: bipush        100
       6: istore_1
       7: iload_0
       8: iload_0
       9: imul
      10: istore_2
      11: iload_2
      12: istore_3
      13: iconst_0
      14: iload_3
      15: if_icmpge     76
      18: iload_0
      19: istore        4
      21: iload_3
      22: iload         4
      24: idiv
      25: istore        5
      27: iload_3
      28: iload         4
      30: irem
      31: ifne          58
      34: iload         5
      36: iload_0
      37: if_icmpgt     58
      40: iload         5
      42: iload_1
      43: if_icmplt     58
      46: iload_3
      47: invokestatic  #57                 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      50: invokestatic  #61                 // Method isPalindrome:(Ljava/lang/String;)Z
      53: ifeq          58
      56: iload_3
      57: ireturn
      58: iload         4
      60: iload_1
      61: if_icmpeq     70
      64: iinc          4, -1
      67: goto          21
      70: iinc          3, -1
      73: goto          13
      76: iconst_0
      77: ireturn

  public static final boolean isPalindrome(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #69                 // String palindrome
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_1
       7: istore_1
       8: iconst_0
       9: aload_0
      10: invokevirtual #72                 // Method java/lang/String.length:()I
      13: iconst_2
      14: idiv
      15: invokestatic  #78                 // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
      18: checkcast     #80                 // class kotlin/ranges/IntProgression
      21: iconst_1
      22: invokestatic  #84                 // Method kotlin/ranges/RangesKt.step:(Lkotlin/ranges/IntProgression;I)Lkotlin/ranges/IntProgression;
      25: astore_2
      26: aload_2
      27: invokevirtual #87                 // Method kotlin/ranges/IntProgression.getFirst:()I
      30: istore_3
      31: aload_2
      32: invokevirtual #90                 // Method kotlin/ranges/IntProgression.getLast:()I
      35: istore        4
      37: aload_2
      38: invokevirtual #93                 // Method kotlin/ranges/IntProgression.getStep:()I
      41: istore        5
      43: iload         5
      45: ifle          54
      48: iload_3
      49: iload         4
      51: if_icmple     65
      54: iload         5
      56: ifge          109
      59: iload         4
      61: iload_3
      62: if_icmpgt     109
      65: iload_1
      66: ifeq          93
      69: aload_0
      70: iload_3
      71: invokevirtual #97                 // Method java/lang/String.charAt:(I)C
      74: aload_0
      75: aload_0
      76: invokevirtual #72                 // Method java/lang/String.length:()I
      79: iconst_1
      80: isub
      81: iload_3
      82: isub
      83: invokevirtual #97                 // Method java/lang/String.charAt:(I)C
      86: if_icmpne     93
      89: iconst_1
      90: goto          94
      93: iconst_0
      94: istore_1
      95: iload_3
      96: iload         4
      98: if_icmpeq     109
     101: iload_3
     102: iload         5
     104: iadd
     105: istore_3
     106: goto          65
     109: iload_1
     110: ireturn
}


import java.io.File
import kotlin.math.abs

data class Program(var weight: Int, var parent: String?, var children: List<String>?)
val programs = HashMap<String, Program>()

fun main(args: Array<String>) {
    // part 1
    val lineRegex = "(\\w+) \\((\\d+)\\)( -> )?(.+)?".toRegex()

    var name: String
    var weight: Int
    var children: List<String> = ArrayList()

    File("input/day7.txt").forEachLine { line -> run {
        name = lineRegex.matchEntire(line)?.groups?.get(1)!!.value
        weight = lineRegex.matchEntire(line)?.groups?.get(2)!!.value.toInt()
        if (lineRegex.matchEntire(line)?.groups?.get(3)?.value != null) {
            children = lineRegex.matchEntire(line)?.groups?.get(4)?.value!!.split(", ")
        }

        children.forEach { child -> run {
            programs.getOrPut(child, { Program(-1, name, null) }).parent = name
        }}

        programs.getOrPut(name, { Program(weight, null, children) }).weight = weight
        programs.get(name)!!.children = children

        children = ArrayList()
    } }

    var parent = Program(0, null, null)
    programs.forEach { program -> run {
        if (program.value.parent == null) {
            println(program.key)
            parent = program.value
        }
    } }

    // part 2
    balanceWeight(parent)
}

fun balanceWeight(program: Program): Int {
    var weight = program.weight
    var childWeight: Int
    val childrenWeight = ArrayList<Int>()
    if (program.children != null) {
        for (child in program.children!!) {
            childWeight = balanceWeight(programs.getOrDefault(child, Program(0, null, null)))
            childrenWeight.add(childWeight)
            weight += childWeight
        }
    }

    if (childrenWeight.size > 0) {
        val testedWeight = childrenWeight.get(0)
        var badWeight = -1
        childrenWeight.forEach { childsWeight -> run {
            if (childsWeight != testedWeight) {
                badWeight = childsWeight
            }
        } }

        if (badWeight != -1 ) {
            println(abs(testedWeight - badWeight))
        }
    }

    return weight
}

Compiled from "Day7.kt"
public final class Day7Kt {
  private static final java.util.HashMap<java.lang.String, Program> programs;

  public static final java.util.HashMap<java.lang.String, Program> getPrograms();
    Code:
       0: getstatic     #12                 // Field programs:Ljava/util/HashMap;
       3: areturn

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #16                 // String args
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #24                 // class kotlin/text/Regex
       9: dup
      10: ldc           #26                 // String (\\w+) \\((\\d+)\\)( -> )?(.+)?
      12: invokespecial #30                 // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      15: astore_1
      16: new           #32                 // class kotlin/jvm/internal/Ref$ObjectRef
      19: dup
      20: invokespecial #35                 // Method kotlin/jvm/internal/Ref$ObjectRef."<init>":()V
      23: astore_2
      24: new           #37                 // class kotlin/jvm/internal/Ref$IntRef
      27: dup
      28: invokespecial #38                 // Method kotlin/jvm/internal/Ref$IntRef."<init>":()V
      31: astore_3
      32: new           #32                 // class kotlin/jvm/internal/Ref$ObjectRef
      35: dup
      36: invokespecial #35                 // Method kotlin/jvm/internal/Ref$ObjectRef."<init>":()V
      39: astore        4
      41: aload         4
      43: new           #40                 // class java/util/ArrayList
      46: dup
      47: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
      50: putfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
      53: new           #47                 // class java/io/File
      56: dup
      57: ldc           #49                 // String input/day7.txt
      59: invokespecial #50                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      62: aconst_null
      63: aload_2
      64: aload_1
      65: aload_3
      66: aload         4
      68: invokedynamic #70,  0             // InvokeDynamic #0:invoke:(Lkotlin/jvm/internal/Ref$ObjectRef;Lkotlin/text/Regex;Lkotlin/jvm/internal/Ref$IntRef;Lkotlin/jvm/internal/Ref$ObjectRef;)Lkotlin/jvm/functions/Function1;
      73: iconst_1
      74: aconst_null
      75: invokestatic  #76                 // Method kotlin/io/FilesKt.forEachLine$default:(Ljava/io/File;Ljava/nio/charset/Charset;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
      78: aconst_null
      79: astore        5
      81: new           #78                 // class Program
      84: dup
      85: iconst_0
      86: aconst_null
      87: aconst_null
      88: invokespecial #81                 // Method Program."<init>":(ILjava/lang/String;Ljava/util/List;)V
      91: astore        5
      93: getstatic     #12                 // Field programs:Ljava/util/HashMap;
      96: checkcast     #83                 // class java/util/Map
      99: astore        6
     101: iconst_0
     102: istore        7
     104: aload         6
     106: invokeinterface #87,  1           // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
     111: invokeinterface #93,  1           // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
     116: astore        8
     118: aload         8
     120: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     125: ifeq          196
     128: aload         8
     130: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     135: checkcast     #105                // class java/util/Map$Entry
     138: astore        9
     140: aload         9
     142: astore        10
     144: iconst_0
     145: istore        11
     147: iconst_0
     148: istore        12
     150: aload         10
     152: invokeinterface #108,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     157: checkcast     #78                 // class Program
     160: invokevirtual #112                // Method Program.getParent:()Ljava/lang/String;
     163: ifnonnull     189
     166: aload         10
     168: invokeinterface #115,  1          // InterfaceMethod java/util/Map$Entry.getKey:()Ljava/lang/Object;
     173: getstatic     #121                // Field java/lang/System.out:Ljava/io/PrintStream;
     176: swap
     177: invokevirtual #127                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     180: aload         10
     182: invokeinterface #108,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     187: astore        5
     189: nop
     190: nop
     191: nop
     192: nop
     193: goto          118
     196: nop
     197: aload         5
     199: checkcast     #78                 // class Program
     202: invokestatic  #131                // Method balanceWeight:(LProgram;)I
     205: pop
     206: return

  public static final int balanceWeight(Program);
    Code:
       0: aload_0
       1: ldc           #151                // String program
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #155                // Method Program.getWeight:()I
      10: istore_1
      11: iconst_0
      12: istore_2
      13: new           #40                 // class java/util/ArrayList
      16: dup
      17: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
      20: astore_3
      21: aload_0
      22: invokevirtual #159                // Method Program.getChildren:()Ljava/util/List;
      25: ifnull        112
      28: aload_0
      29: invokevirtual #159                // Method Program.getChildren:()Ljava/util/List;
      32: dup
      33: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      36: invokeinterface #165,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      41: astore        4
      43: aload         4
      45: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      50: ifeq          112
      53: aload         4
      55: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      60: checkcast     #167                // class java/lang/String
      63: astore        5
      65: getstatic     #12                 // Field programs:Ljava/util/HashMap;
      68: aload         5
      70: new           #78                 // class Program
      73: dup
      74: iconst_0
      75: aconst_null
      76: aconst_null
      77: invokespecial #81                 // Method Program."<init>":(ILjava/lang/String;Ljava/util/List;)V
      80: invokevirtual #173                // Method java/util/HashMap.getOrDefault:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      83: dup
      84: ldc           #175                // String getOrDefault(...)
      86: invokestatic  #178                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      89: checkcast     #78                 // class Program
      92: invokestatic  #131                // Method balanceWeight:(LProgram;)I
      95: istore_2
      96: aload_3
      97: iload_2
      98: invokestatic  #184                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     101: invokevirtual #188                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     104: pop
     105: iload_1
     106: iload_2
     107: iadd
     108: istore_1
     109: goto          43
     112: aload_3
     113: invokevirtual #191                // Method java/util/ArrayList.size:()I
     116: ifle          240
     119: aload_3
     120: iconst_0
     121: invokevirtual #195                // Method java/util/ArrayList.get:(I)Ljava/lang/Object;
     124: dup
     125: ldc           #197                // String get(...)
     127: invokestatic  #178                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     130: checkcast     #199                // class java/lang/Number
     133: invokevirtual #202                // Method java/lang/Number.intValue:()I
     136: istore        4
     138: iconst_0
     139: istore        5
     141: iconst_m1
     142: istore        5
     144: aload_3
     145: checkcast     #204                // class java/lang/Iterable
     148: astore        6
     150: iconst_0
     151: istore        7
     153: aload         6
     155: invokeinterface #205,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     160: astore        8
     162: aload         8
     164: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     169: ifeq          215
     172: aload         8
     174: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     179: astore        9
     181: aload         9
     183: checkcast     #199                // class java/lang/Number
     186: invokevirtual #202                // Method java/lang/Number.intValue:()I
     189: istore        10
     191: iconst_0
     192: istore        11
     194: iconst_0
     195: istore        12
     197: iload         10
     199: iload         4
     201: if_icmpeq     208
     204: iload         10
     206: istore        5
     208: nop
     209: nop
     210: nop
     211: nop
     212: goto          162
     215: nop
     216: iload         5
     218: iconst_m1
     219: if_icmpeq     240
     222: iload         4
     224: iload         5
     226: isub
     227: invokestatic  #211                // Method java/lang/Math.abs:(I)I
     230: istore        6
     232: getstatic     #121                // Field java/lang/System.out:Ljava/io/PrintStream;
     235: iload         6
     237: invokevirtual #214                // Method java/io/PrintStream.println:(I)V
     240: iload_1
     241: ireturn

  private static final kotlin.Unit main$lambda$5(kotlin.jvm.internal.Ref$ObjectRef, kotlin.text.Regex, kotlin.jvm.internal.Ref$IntRef, kotlin.jvm.internal.Ref$ObjectRef, java.lang.String);
    Code:
       0: aload         4
       2: ldc           #228                // String line
       4: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: iconst_0
       8: istore        5
      10: aload_0
      11: aload_1
      12: aload         4
      14: checkcast     #230                // class java/lang/CharSequence
      17: invokevirtual #234                // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
      20: dup
      21: ifnull        42
      24: invokeinterface #240,  1          // InterfaceMethod kotlin/text/MatchResult.getGroups:()Lkotlin/text/MatchGroupCollection;
      29: dup
      30: ifnull        42
      33: iconst_1
      34: invokeinterface #245,  2          // InterfaceMethod kotlin/text/MatchGroupCollection.get:(I)Lkotlin/text/MatchGroup;
      39: goto          44
      42: pop
      43: aconst_null
      44: dup
      45: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      48: invokevirtual #249                // Method kotlin/text/MatchGroup.getValue:()Ljava/lang/String;
      51: putfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
      54: aload_2
      55: aload_1
      56: aload         4
      58: checkcast     #230                // class java/lang/CharSequence
      61: invokevirtual #234                // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
      64: dup
      65: ifnull        86
      68: invokeinterface #240,  1          // InterfaceMethod kotlin/text/MatchResult.getGroups:()Lkotlin/text/MatchGroupCollection;
      73: dup
      74: ifnull        86
      77: iconst_2
      78: invokeinterface #245,  2          // InterfaceMethod kotlin/text/MatchGroupCollection.get:(I)Lkotlin/text/MatchGroup;
      83: goto          88
      86: pop
      87: aconst_null
      88: dup
      89: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      92: invokevirtual #249                // Method kotlin/text/MatchGroup.getValue:()Ljava/lang/String;
      95: invokestatic  #253                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      98: putfield      #255                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     101: aload_1
     102: aload         4
     104: checkcast     #230                // class java/lang/CharSequence
     107: invokevirtual #234                // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
     110: dup
     111: ifnull        139
     114: invokeinterface #240,  1          // InterfaceMethod kotlin/text/MatchResult.getGroups:()Lkotlin/text/MatchGroupCollection;
     119: dup
     120: ifnull        139
     123: iconst_3
     124: invokeinterface #245,  2          // InterfaceMethod kotlin/text/MatchGroupCollection.get:(I)Lkotlin/text/MatchGroup;
     129: dup
     130: ifnull        139
     133: invokevirtual #249                // Method kotlin/text/MatchGroup.getValue:()Ljava/lang/String;
     136: goto          141
     139: pop
     140: aconst_null
     141: ifnull        218
     144: aload_3
     145: aload_1
     146: aload         4
     148: checkcast     #230                // class java/lang/CharSequence
     151: invokevirtual #234                // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
     154: dup
     155: ifnull        183
     158: invokeinterface #240,  1          // InterfaceMethod kotlin/text/MatchResult.getGroups:()Lkotlin/text/MatchGroupCollection;
     163: dup
     164: ifnull        183
     167: iconst_4
     168: invokeinterface #245,  2          // InterfaceMethod kotlin/text/MatchGroupCollection.get:(I)Lkotlin/text/MatchGroup;
     173: dup
     174: ifnull        183
     177: invokevirtual #249                // Method kotlin/text/MatchGroup.getValue:()Ljava/lang/String;
     180: goto          185
     183: pop
     184: aconst_null
     185: dup
     186: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     189: checkcast     #230                // class java/lang/CharSequence
     192: iconst_1
     193: anewarray     #167                // class java/lang/String
     196: astore        6
     198: aload         6
     200: iconst_0
     201: ldc_w         #257                // String ,
     204: aastore
     205: aload         6
     207: iconst_0
     208: iconst_0
     209: bipush        6
     211: aconst_null
     212: invokestatic  #263                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     215: putfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     218: aload_3
     219: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     222: checkcast     #204                // class java/lang/Iterable
     225: astore        6
     227: iconst_0
     228: istore        7
     230: aload         6
     232: invokeinterface #205,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     237: astore        8
     239: aload         8
     241: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     246: ifeq          359
     249: aload         8
     251: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     256: astore        9
     258: aload         9
     260: checkcast     #167                // class java/lang/String
     263: astore        10
     265: iconst_0
     266: istore        11
     268: iconst_0
     269: istore        12
     271: getstatic     #12                 // Field programs:Ljava/util/HashMap;
     274: checkcast     #83                 // class java/util/Map
     277: astore        13
     279: iconst_0
     280: istore        14
     282: aload         13
     284: aload         10
     286: invokeinterface #265,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     291: astore        15
     293: aload         15
     295: ifnonnull     336
     298: iconst_0
     299: istore        16
     301: new           #78                 // class Program
     304: dup
     305: iconst_m1
     306: aload_0
     307: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     310: checkcast     #167                // class java/lang/String
     313: aconst_null
     314: invokespecial #81                 // Method Program."<init>":(ILjava/lang/String;Ljava/util/List;)V
     317: astore        16
     319: aload         13
     321: aload         10
     323: aload         16
     325: invokeinterface #268,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     330: pop
     331: aload         16
     333: goto          338
     336: aload         15
     338: nop
     339: checkcast     #78                 // class Program
     342: aload_0
     343: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     346: checkcast     #167                // class java/lang/String
     349: invokevirtual #271                // Method Program.setParent:(Ljava/lang/String;)V
     352: nop
     353: nop
     354: nop
     355: nop
     356: goto          239
     359: nop
     360: getstatic     #12                 // Field programs:Ljava/util/HashMap;
     363: checkcast     #83                 // class java/util/Map
     366: astore        6
     368: aload_0
     369: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     372: astore        7
     374: iconst_0
     375: istore        8
     377: aload         6
     379: aload         7
     381: invokeinterface #265,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     386: astore        9
     388: aload         9
     390: ifnonnull     434
     393: iconst_0
     394: istore        10
     396: new           #78                 // class Program
     399: dup
     400: aload_2
     401: getfield      #255                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     404: aconst_null
     405: aload_3
     406: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     409: checkcast     #164                // class java/util/List
     412: invokespecial #81                 // Method Program."<init>":(ILjava/lang/String;Ljava/util/List;)V
     415: astore        11
     417: aload         6
     419: aload         7
     421: aload         11
     423: invokeinterface #268,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     428: pop
     429: aload         11
     431: goto          436
     434: aload         9
     436: nop
     437: checkcast     #78                 // class Program
     440: aload_2
     441: getfield      #255                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     444: invokevirtual #274                // Method Program.setWeight:(I)V
     447: getstatic     #12                 // Field programs:Ljava/util/HashMap;
     450: aload_0
     451: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     454: invokevirtual #275                // Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
     457: dup
     458: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     461: checkcast     #78                 // class Program
     464: aload_3
     465: getfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     468: checkcast     #164                // class java/util/List
     471: invokevirtual #279                // Method Program.setChildren:(Ljava/util/List;)V
     474: aload_3
     475: new           #40                 // class java/util/ArrayList
     478: dup
     479: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
     482: putfield      #45                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     485: nop
     486: nop
     487: getstatic     #285                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     490: areturn

  static {};
    Code:
       0: new           #169                // class java/util/HashMap
       3: dup
       4: invokespecial #301                // Method java/util/HashMap."<init>":()V
       7: putstatic     #12                 // Field programs:Ljava/util/HashMap;
      10: return
}


import java.io.File

val letters = "abcdefghijklmnopqrstuvwxyz".toCharArray()

fun main(args: Array<String>) {
    // part 1
    var numberOfCorrectPassphrases = 0
    File("input/day4.txt").forEachLine { line -> run {
        if (passphraseIsValid(line)) numberOfCorrectPassphrases++
    }
    }

    println(numberOfCorrectPassphrases)

    // part 2
    numberOfCorrectPassphrases = 0
    File("input/day4.txt").forEachLine { line -> run {
        val words = line.split(Regex("[ \t]"))
        val o1 = HashMap<Char, Int>()
        val o2 = HashMap<Char, Int>()
        for (letter in letters) {
            o1.put(letter, 0)
            o2.put(letter, 0)
        }

        var isPassphraseCorrect = true
        for (i in 0 until words.size) {
            for (letter in letters) {
                o1.put(letter, 0)
            }
            words[i].toCharArray().forEach { c -> o1.put(c, o1.getValue(c) + 1) }
            for (j in 0 until words.size) {
                for (letter in letters) {
                    o2.put(letter, 0)
                }
                words[j].toCharArray().forEach { c -> o2.put(c, o2.getValue(c) + 1) }
                if (i != j && mapsEqual(o1, o2)) isPassphraseCorrect = false
            }
        }

        if (isPassphraseCorrect) numberOfCorrectPassphrases++
    }
    }

    println(numberOfCorrectPassphrases)

}

fun passphraseIsValid(line : String) : Boolean {
    val words = line.split(Regex("[ \t]"))
    for (i in 0 until words.size) {
        for (j in 0 until words.size) {
            if (i != j && words[i].equals(words[j])) return false
        }
    }

    return true
}

fun mapsEqual(o1: HashMap<Char, Int>, o2: HashMap<Char, Int>): Boolean {
    for (letter in letters) {
        if (o1.get(letter) != o2.get(letter)) return false
    }

    return true
}

Compiled from "Day4.kt"
public final class Day4Kt {
  private static final char[] letters;

  public static final char[] getLetters();
    Code:
       0: getstatic     #11                 // Field letters:[C
       3: areturn

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #15                 // String args
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #23                 // class kotlin/jvm/internal/Ref$IntRef
       9: dup
      10: invokespecial #27                 // Method kotlin/jvm/internal/Ref$IntRef."<init>":()V
      13: astore_1
      14: new           #29                 // class java/io/File
      17: dup
      18: ldc           #31                 // String input/day4.txt
      20: invokespecial #34                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      23: aconst_null
      24: aload_1
      25: invokedynamic #54,  0             // InvokeDynamic #0:invoke:(Lkotlin/jvm/internal/Ref$IntRef;)Lkotlin/jvm/functions/Function1;
      30: iconst_1
      31: aconst_null
      32: invokestatic  #60                 // Method kotlin/io/FilesKt.forEachLine$default:(Ljava/io/File;Ljava/nio/charset/Charset;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
      35: aload_1
      36: getfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      39: istore_2
      40: getstatic     #70                 // Field java/lang/System.out:Ljava/io/PrintStream;
      43: iload_2
      44: invokevirtual #76                 // Method java/io/PrintStream.println:(I)V
      47: aload_1
      48: iconst_0
      49: putfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      52: new           #29                 // class java/io/File
      55: dup
      56: ldc           #31                 // String input/day4.txt
      58: invokespecial #34                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      61: aconst_null
      62: aload_1
      63: invokedynamic #81,  0             // InvokeDynamic #1:invoke:(Lkotlin/jvm/internal/Ref$IntRef;)Lkotlin/jvm/functions/Function1;
      68: iconst_1
      69: aconst_null
      70: invokestatic  #60                 // Method kotlin/io/FilesKt.forEachLine$default:(Ljava/io/File;Ljava/nio/charset/Charset;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
      73: aload_1
      74: getfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      77: istore_2
      78: getstatic     #70                 // Field java/lang/System.out:Ljava/io/PrintStream;
      81: iload_2
      82: invokevirtual #76                 // Method java/io/PrintStream.println:(I)V
      85: return

  public static final boolean passphraseIsValid(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #88                 // String line
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #90                 // class java/lang/CharSequence
      10: astore_2
      11: new           #92                 // class kotlin/text/Regex
      14: dup
      15: ldc           #94                 // String [ \t]
      17: invokespecial #95                 // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      20: astore_3
      21: iconst_0
      22: istore        4
      24: aload_3
      25: aload_2
      26: iload         4
      28: invokevirtual #99                 // Method kotlin/text/Regex.split:(Ljava/lang/CharSequence;I)Ljava/util/List;
      31: astore_1
      32: iconst_0
      33: istore_2
      34: aload_1
      35: invokeinterface #105,  1          // InterfaceMethod java/util/List.size:()I
      40: istore_3
      41: iload_2
      42: iload_3
      43: if_icmpge     108
      46: iconst_0
      47: istore        4
      49: aload_1
      50: invokeinterface #105,  1          // InterfaceMethod java/util/List.size:()I
      55: istore        5
      57: iload         4
      59: iload         5
      61: if_icmpge     102
      64: iload_2
      65: iload         4
      67: if_icmpeq     96
      70: aload_1
      71: iload_2
      72: invokeinterface #109,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      77: checkcast     #111                // class java/lang/String
      80: aload_1
      81: iload         4
      83: invokeinterface #109,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      88: invokevirtual #115                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      91: ifeq          96
      94: iconst_0
      95: ireturn
      96: iinc          4, 1
      99: goto          57
     102: iinc          2, 1
     105: goto          41
     108: iconst_1
     109: ireturn

  public static final boolean mapsEqual(java.util.HashMap<java.lang.Character, java.lang.Integer>, java.util.HashMap<java.lang.Character, java.lang.Integer>);
    Code:
       0: aload_0
       1: ldc           #125                // String o1
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #127                // String o2
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: getstatic     #11                 // Field letters:[C
      15: astore_2
      16: iconst_0
      17: istore_3
      18: aload_2
      19: arraylength
      20: istore        4
      22: iload_3
      23: iload         4
      25: if_icmpge     65
      28: aload_2
      29: iload_3
      30: caload
      31: istore        5
      33: aload_0
      34: iload         5
      36: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      39: invokevirtual #137                // Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
      42: aload_1
      43: iload         5
      45: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      48: invokevirtual #137                // Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
      51: invokestatic  #141                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      54: ifne          59
      57: iconst_0
      58: ireturn
      59: iinc          3, 1
      62: goto          22
      65: iconst_1
      66: ireturn

  private static final kotlin.Unit main$lambda$1(kotlin.jvm.internal.Ref$IntRef, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #88                 // String line
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_2
       8: aload_1
       9: invokestatic  #147                // Method passphraseIsValid:(Ljava/lang/String;)Z
      12: ifeq          27
      15: aload_0
      16: getfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      19: istore_3
      20: aload_0
      21: iload_3
      22: iconst_1
      23: iadd
      24: putfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      27: nop
      28: nop
      29: getstatic     #153                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      32: areturn

  private static final kotlin.Unit main$lambda$5(kotlin.jvm.internal.Ref$IntRef, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #88                 // String line
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_2
       8: aload_1
       9: checkcast     #90                 // class java/lang/CharSequence
      12: astore_3
      13: new           #92                 // class kotlin/text/Regex
      16: dup
      17: ldc           #94                 // String [ \t]
      19: invokespecial #95                 // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      22: astore        4
      24: iconst_0
      25: istore        5
      27: aload         4
      29: aload_3
      30: iload         5
      32: invokevirtual #99                 // Method kotlin/text/Regex.split:(Ljava/lang/CharSequence;I)Ljava/util/List;
      35: astore        6
      37: new           #135                // class java/util/HashMap
      40: dup
      41: invokespecial #156                // Method java/util/HashMap."<init>":()V
      44: astore_3
      45: new           #135                // class java/util/HashMap
      48: dup
      49: invokespecial #156                // Method java/util/HashMap."<init>":()V
      52: astore        4
      54: getstatic     #11                 // Field letters:[C
      57: astore        5
      59: iconst_0
      60: istore        7
      62: aload         5
      64: arraylength
      65: istore        8
      67: iload         7
      69: iload         8
      71: if_icmpge     116
      74: aload         5
      76: iload         7
      78: caload
      79: istore        9
      81: aload_3
      82: iload         9
      84: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      87: iconst_0
      88: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      91: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      94: pop
      95: aload         4
      97: iload         9
      99: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     102: iconst_0
     103: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     106: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     109: pop
     110: iinc          7, 1
     113: goto          67
     116: iconst_1
     117: istore        5
     119: iconst_0
     120: istore        7
     122: aload         6
     124: invokeinterface #105,  1          // InterfaceMethod java/util/List.size:()I
     129: istore        8
     131: iload         7
     133: iload         8
     135: if_icmpge     479
     138: getstatic     #11                 // Field letters:[C
     141: astore        9
     143: iconst_0
     144: istore        10
     146: aload         9
     148: arraylength
     149: istore        11
     151: iload         10
     153: iload         11
     155: if_icmpge     185
     158: aload         9
     160: iload         10
     162: caload
     163: istore        12
     165: aload_3
     166: iload         12
     168: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     171: iconst_0
     172: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     175: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     178: pop
     179: iinc          10, 1
     182: goto          151
     185: aload         6
     187: iload         7
     189: invokeinterface #109,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     194: checkcast     #111                // class java/lang/String
     197: invokevirtual #168                // Method java/lang/String.toCharArray:()[C
     200: dup
     201: ldc           #170                // String toCharArray(...)
     203: invokestatic  #173                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     206: astore        9
     208: nop
     209: iconst_0
     210: istore        10
     212: iconst_0
     213: istore        11
     215: aload         9
     217: arraylength
     218: istore        12
     220: iload         11
     222: iload         12
     224: if_icmpge     281
     227: aload         9
     229: iload         11
     231: caload
     232: istore        13
     234: iload         13
     236: istore        14
     238: iconst_0
     239: istore        15
     241: aload_3
     242: iload         14
     244: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     247: aload_3
     248: checkcast     #175                // class java/util/Map
     251: iload         14
     253: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     256: invokestatic  #181                // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
     259: checkcast     #183                // class java/lang/Number
     262: invokevirtual #186                // Method java/lang/Number.intValue:()I
     265: iconst_1
     266: iadd
     267: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     270: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     273: pop
     274: nop
     275: iinc          11, 1
     278: goto          220
     281: nop
     282: iconst_0
     283: istore        9
     285: aload         6
     287: invokeinterface #105,  1          // InterfaceMethod java/util/List.size:()I
     292: istore        10
     294: iload         9
     296: iload         10
     298: if_icmpge     473
     301: getstatic     #11                 // Field letters:[C
     304: astore        11
     306: iconst_0
     307: istore        12
     309: aload         11
     311: arraylength
     312: istore        13
     314: iload         12
     316: iload         13
     318: if_icmpge     349
     321: aload         11
     323: iload         12
     325: caload
     326: istore        14
     328: aload         4
     330: iload         14
     332: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     335: iconst_0
     336: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     339: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     342: pop
     343: iinc          12, 1
     346: goto          314
     349: aload         6
     351: iload         9
     353: invokeinterface #109,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     358: checkcast     #111                // class java/lang/String
     361: invokevirtual #168                // Method java/lang/String.toCharArray:()[C
     364: dup
     365: ldc           #170                // String toCharArray(...)
     367: invokestatic  #173                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     370: astore        11
     372: nop
     373: iconst_0
     374: istore        12
     376: iconst_0
     377: istore        13
     379: aload         11
     381: arraylength
     382: istore        14
     384: iload         13
     386: iload         14
     388: if_icmpge     447
     391: aload         11
     393: iload         13
     395: caload
     396: istore        15
     398: iload         15
     400: istore        16
     402: iconst_0
     403: istore        17
     405: aload         4
     407: iload         16
     409: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     412: aload         4
     414: checkcast     #175                // class java/util/Map
     417: iload         16
     419: invokestatic  #133                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     422: invokestatic  #181                // Method kotlin/collections/MapsKt.getValue:(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
     425: checkcast     #183                // class java/lang/Number
     428: invokevirtual #186                // Method java/lang/Number.intValue:()I
     431: iconst_1
     432: iadd
     433: invokestatic  #161                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     436: invokevirtual #165                // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     439: pop
     440: nop
     441: iinc          13, 1
     444: goto          384
     447: nop
     448: iload         7
     450: iload         9
     452: if_icmpeq     467
     455: aload_3
     456: aload         4
     458: invokestatic  #188                // Method mapsEqual:(Ljava/util/HashMap;Ljava/util/HashMap;)Z
     461: ifeq          467
     464: iconst_0
     465: istore        5
     467: iinc          9, 1
     470: goto          294
     473: iinc          7, 1
     476: goto          131
     479: iload         5
     481: ifeq          498
     484: aload_0
     485: getfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
     488: istore        7
     490: aload_0
     491: iload         7
     493: iconst_1
     494: iadd
     495: putfield      #64                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
     498: nop
     499: nop
     500: getstatic     #153                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     503: areturn

  static {};
    Code:
       0: ldc           #200                // String abcdefghijklmnopqrstuvwxyz
       2: invokevirtual #168                // Method java/lang/String.toCharArray:()[C
       5: dup
       6: ldc           #170                // String toCharArray(...)
       8: invokestatic  #173                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      11: putstatic     #11                 // Field letters:[C
      14: return
}


import kotlin.math.pow

class Vector(var x: Double, var y: Double)

/**
 * @param poly1, poly2 The two polygons described as arrays of points as Vectors
 *  Note: The points list must go in sequence around the polygon
 * @param maxDist The maximum distance between any two points of any two polygons that can be touching
 *  If this null then the optimization check that uses it will be skipped
 */
fun hasCollided(poly1: Array<Vector>, poly2: Array<Vector>, maxDist: Double?=null): Boolean {
    // Do an optimization check using the maxDist
    if (maxDist != null) {
        if ((poly1[1].x - poly2[0].x).pow(2) + (poly1[1].y - poly2[0].y).pow(2) <= maxDist.pow(2)) {
            // Collision is possible so run SAT on the polys
            return runSAT(poly1, poly2)
        } else {
            return false
        }
    } else {
        // No maxDist so run SAT on the polys
        return runSAT(poly1, poly2)
    }
}

fun runSAT(poly1: Array<Vector>, poly2: Array<Vector>): Boolean {
    // Implements the actual SAT algorithm
    val edges = polyToEdges(poly1) + polyToEdges(poly2)
    val axes = Array(edges.size, { index -> orthogonal(edges[index])})

    for (axis in axes) {
        if (!overlap(project(poly1, axis), project(poly2, axis))) {
            // The polys don't overlap on this axis so they can't be touching
            return false
        }
    }

    // The polys overlap on all axes so they must be touching
    return true
}

/**
 * Returns a vector going from point1 to point2
 */
fun edgeVector(point1: Vector, point2: Vector) = Vector(point2.x - point1.x, point2.y - point1.y)

/**
 * Returns an array of the edges of the poly as vectors
 */
fun polyToEdges(poly: Array<Vector>) = Array(poly.size,
        { index -> edgeVector(poly[index], poly[(index + 1) % poly.size]) })

/**
 * Returns a new vector which is orthogonal to the given vector
 */
fun orthogonal(vector: Vector) = Vector(vector.y, -vector.x)

/**
 * Returns the dot (or scalar) product of the two vectors
 */
fun dotProduct(vector1: Vector, vector2: Vector) = vector1.x * vector2.x + vector1.y * vector2.y

/**
 * Returns a vector showing how much of the poly lies along the axis
 */
fun project(poly: Array<Vector>, axis: Vector): Vector {
    val dots = Array(poly.size, { index -> dotProduct(poly[index], axis) })
    return Vector(dots.min()!!, dots.max()!!)
}

/**
 * Returns a boolean indicating if the two projections overlap
 */
fun overlap(projection1: Vector, projection2: Vector) = projection1.x <= projection2.y &&
        projection2.x <= projection1.y

Compiled from "sat.kt"
public final class SatKt {
  public static final boolean hasCollided(Vector[], Vector[], java.lang.Double);
    Code:
       0: aload_0
       1: ldc           #10                 // String poly1
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #18                 // String poly2
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_2
      13: ifnull        74
      16: aload_0
      17: iconst_1
      18: aaload
      19: invokevirtual #24                 // Method Vector.getX:()D
      22: aload_1
      23: iconst_0
      24: aaload
      25: invokevirtual #24                 // Method Vector.getX:()D
      28: dsub
      29: iconst_2
      30: i2d
      31: invokestatic  #30                 // Method java/lang/Math.pow:(DD)D
      34: aload_0
      35: iconst_1
      36: aaload
      37: invokevirtual #33                 // Method Vector.getY:()D
      40: aload_1
      41: iconst_0
      42: aaload
      43: invokevirtual #33                 // Method Vector.getY:()D
      46: dsub
      47: iconst_2
      48: i2d
      49: invokestatic  #30                 // Method java/lang/Math.pow:(DD)D
      52: dadd
      53: aload_2
      54: invokevirtual #38                 // Method java/lang/Double.doubleValue:()D
      57: iconst_2
      58: i2d
      59: invokestatic  #30                 // Method java/lang/Math.pow:(DD)D
      62: dcmpg
      63: ifgt          72
      66: aload_0
      67: aload_1
      68: invokestatic  #42                 // Method runSAT:([LVector;[LVector;)Z
      71: ireturn
      72: iconst_0
      73: ireturn
      74: aload_0
      75: aload_1
      76: invokestatic  #42                 // Method runSAT:([LVector;[LVector;)Z
      79: ireturn

  public static boolean hasCollided$default(Vector[], Vector[], java.lang.Double, int, java.lang.Object);
    Code:
       0: iload_3
       1: iconst_4
       2: iand
       3: ifeq          8
       6: aconst_null
       7: astore_2
       8: aload_0
       9: aload_1
      10: aload_2
      11: invokestatic  #49                 // Method hasCollided:([LVector;[LVector;Ljava/lang/Double;)Z
      14: ireturn

  public static final boolean runSAT(Vector[], Vector[]);
    Code:
       0: aload_0
       1: ldc           #10                 // String poly1
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #18                 // String poly2
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: invokestatic  #53                 // Method polyToEdges:([LVector;)[LVector;
      16: aload_1
      17: invokestatic  #53                 // Method polyToEdges:([LVector;)[LVector;
      20: invokestatic  #59                 // Method kotlin/collections/ArraysKt.plus:([Ljava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;
      23: checkcast     #60                 // class "[LVector;"
      26: astore_2
      27: iconst_0
      28: istore        4
      30: aload_2
      31: arraylength
      32: istore        5
      34: iload         5
      36: anewarray     #20                 // class Vector
      39: astore        6
      41: iload         4
      43: iload         5
      45: if_icmpge     70
      48: iload         4
      50: istore        7
      52: aload         6
      54: iload         7
      56: aload_2
      57: iload         7
      59: aaload
      60: invokestatic  #64                 // Method orthogonal:(LVector;)LVector;
      63: aastore
      64: iinc          4, 1
      67: goto          41
      70: aload         6
      72: astore_3
      73: iconst_0
      74: istore        4
      76: aload_3
      77: arraylength
      78: istore        5
      80: iload         4
      82: iload         5
      84: if_icmpge     119
      87: aload_3
      88: iload         4
      90: aaload
      91: astore        6
      93: aload_0
      94: aload         6
      96: invokestatic  #68                 // Method project:([LVector;LVector;)LVector;
      99: aload_1
     100: aload         6
     102: invokestatic  #68                 // Method project:([LVector;LVector;)LVector;
     105: invokestatic  #72                 // Method overlap:(LVector;LVector;)Z
     108: ifne          113
     111: iconst_0
     112: ireturn
     113: iinc          4, 1
     116: goto          80
     119: iconst_1
     120: ireturn

  public static final Vector edgeVector(Vector, Vector);
    Code:
       0: aload_0
       1: ldc           #80                 // String point1
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #82                 // String point2
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: new           #20                 // class Vector
      15: dup
      16: aload_1
      17: invokevirtual #24                 // Method Vector.getX:()D
      20: aload_0
      21: invokevirtual #24                 // Method Vector.getX:()D
      24: dsub
      25: aload_1
      26: invokevirtual #33                 // Method Vector.getY:()D
      29: aload_0
      30: invokevirtual #33                 // Method Vector.getY:()D
      33: dsub
      34: invokespecial #86                 // Method Vector."<init>":(DD)V
      37: areturn

  public static final Vector[] polyToEdges(Vector[]);
    Code:
       0: aload_0
       1: ldc           #88                 // String poly
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_1
       8: aload_0
       9: arraylength
      10: istore_2
      11: iload_2
      12: anewarray     #20                 // class Vector
      15: astore_3
      16: iload_1
      17: iload_2
      18: if_icmpge     50
      21: iload_1
      22: istore        4
      24: aload_3
      25: iload         4
      27: aload_0
      28: iload         4
      30: aaload
      31: aload_0
      32: iload         4
      34: iconst_1
      35: iadd
      36: aload_0
      37: arraylength
      38: irem
      39: aaload
      40: invokestatic  #90                 // Method edgeVector:(LVector;LVector;)LVector;
      43: aastore
      44: iinc          1, 1
      47: goto          16
      50: aload_3
      51: areturn

  public static final Vector orthogonal(Vector);
    Code:
       0: aload_0
       1: ldc           #92                 // String vector
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #20                 // class Vector
       9: dup
      10: aload_0
      11: invokevirtual #33                 // Method Vector.getY:()D
      14: aload_0
      15: invokevirtual #24                 // Method Vector.getX:()D
      18: dneg
      19: invokespecial #86                 // Method Vector."<init>":(DD)V
      22: areturn

  public static final double dotProduct(Vector, Vector);
    Code:
       0: aload_0
       1: ldc           #96                 // String vector1
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #98                 // String vector2
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: invokevirtual #24                 // Method Vector.getX:()D
      16: aload_1
      17: invokevirtual #24                 // Method Vector.getX:()D
      20: dmul
      21: aload_0
      22: invokevirtual #33                 // Method Vector.getY:()D
      25: aload_1
      26: invokevirtual #33                 // Method Vector.getY:()D
      29: dmul
      30: dadd
      31: dreturn

  public static final Vector project(Vector[], Vector);
    Code:
       0: aload_0
       1: ldc           #88                 // String poly
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #99                 // String axis
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iconst_0
      13: istore_3
      14: aload_0
      15: arraylength
      16: istore        4
      18: iload         4
      20: anewarray     #35                 // class java/lang/Double
      23: astore        5
      25: iload_3
      26: iload         4
      28: if_icmpge     56
      31: iload_3
      32: istore        6
      34: aload         5
      36: iload         6
      38: aload_0
      39: iload         6
      41: aaload
      42: aload_1
      43: invokestatic  #101                // Method dotProduct:(LVector;LVector;)D
      46: invokestatic  #105                // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      49: aastore
      50: iinc          3, 1
      53: goto          25
      56: aload         5
      58: astore_2
      59: new           #20                 // class Vector
      62: dup
      63: aload_2
      64: invokestatic  #109                // Method kotlin/collections/ArraysKt.minOrThrow:([Ljava/lang/Double;)D
      67: aload_2
      68: invokestatic  #112                // Method kotlin/collections/ArraysKt.maxOrThrow:([Ljava/lang/Double;)D
      71: invokespecial #86                 // Method Vector."<init>":(DD)V
      74: areturn

  public static final boolean overlap(Vector, Vector);
    Code:
       0: aload_0
       1: ldc           #117                // String projection1
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #119                // String projection2
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: invokevirtual #24                 // Method Vector.getX:()D
      16: aload_1
      17: invokevirtual #33                 // Method Vector.getY:()D
      20: dcmpg
      21: ifgt          40
      24: aload_1
      25: invokevirtual #24                 // Method Vector.getX:()D
      28: aload_0
      29: invokevirtual #33                 // Method Vector.getY:()D
      32: dcmpg
      33: ifgt          40
      36: iconst_1
      37: goto          41
      40: iconst_0
      41: ireturn
}