package com.lonbon.kotlin.collection

/**
 * 排序 Comparable.
 * 1. 存在自然排序。针对一个类需要自然排序的话，那么需要实现的Comparable接口。并且实现Comparable接口。
 * 2.
 */
class CollectionComparable {
}

fun main() {
/*    val v1 = Version(1, 2)
    val v2 = Version(2, 1)
    println(v1 > v2)*/
    collectionPolymerization()
}

/**
 * 定义自然排序的话 -> 正值表示大
 * 负值表示小
 * 0 代表两个对象相等
 */
data class Version(
    val majorVersion: Int,
    val subVersion: Int
) : Comparable<Version> {
    /**
     * 实现Comparable来定义自然顺序。
     */
    override fun compareTo(other: Version): Int {
        if (this.majorVersion != other.majorVersion) {
            return this.majorVersion - this.majorVersion
        } else if (this.subVersion != other.subVersion) {
            return this.subVersion - other.subVersion
        } else {
            return 0
        }
    }
}

/*
*   定义非自然顺序。
*   当不可以为类来定义自然顺序的时候，此时需要定义一个非自然的顺序。
* */
fun notNatureComparable() {

    /**
     * 定义一个比较器。Comparator()并且实现compareTo()方法。
     */
    val comparator = Comparator<String> { t, t2 ->
        t.length - t2.length
    }

    val list = listOf("aaa", "bb", "c")

    //可以调用kotlin的sortedWith方法。传入了一个Comparator即可。
    println(list.sortedWith(comparator).joinToString())

    //如果想快速定义一个的Comparator对象的话，可以使用 compareBy方法。该方法可以快速的定义出一个Comparator对象。
    //定义comparator对象时，需要标注其类型。
    val comparator2 = compareBy<String> {
        it.length
    }
}

fun collectionSort() {
    val list = listOf(1, 2, 3, 4, 5)
    val listVersion = listOf(
        Version(1, 1),
        Version(1, 2),
        Version(2, 3),
        Version(2, 1)
    )
    println(list.sorted())
    println(list.sortedDescending())
    println(listVersion.sortedDescending())
    println(listVersion.sortedDescending())
    /**
     * sorted()和sortedDescending() 两个函数。可以针对存在自然排序的集合进行排序。
     * sorted() 是自然排序的正序。sortedDescending()是自然排序的倒序。
     */

    /**
     * 自定义排序规则。通常存在两个函数sortedBy()
     */
    val listNumber = listOf("one", "two", "three", "four", "five")
    //sortedBy的底层还是调用sortedWith(comparableBy{})
    println(listNumber.sortedBy {
        it.length
    }.joinToString())

    println(listNumber.sortedByDescending {
        it.length
    }.joinToString())

    //sortWith可以使用自己的提供的Comparator
}

/**
 * 集合的倒序。kotlin
 *  1. reversed() 创建一个集合的副本，其中的元素的是接受者排序的逆序。
 *  2. asReversed()
 *  3. reverse() 将集合逆转。
 */
fun collectionReversed() {
    val list = mutableListOf(1, 2, 3, 4, 5, 6)
    val reverse = list.reversed()
    val reverse2 = list.asReversed()
    list.add(7)
    println(reverse) //由于是创建的副本的，所以那么原Collection的更改不会影响到新的倒序的Collection
    println(reverse2) //asRevered和reversed不相同。这个函数是针对引用来。原Collection的变化可以导致新的Collection变化。
    println(list.joinToString())
}

/**
 * shuffled洗牌算法。
 */
fun collectionShuffled() {
    val list = listOf(1, 2, 3, 4, 5)
    //list.shuffled()同样是创建集合的副本然后执行洗牌
    println(list.shuffled())
}

/*
*   集合的聚合操作： 按照某一种规则将集合聚合成一个值。
* */
fun collectionPolymerization() {
    val list = listOf(1, 543, 6, 89)
    val min = list.min() //最小值
    val max = list.max()
    val average = list.average()
    val sum = list.sum()
    println(min)
    println(max)
    println(average)
    println(sum)
    //更高级的sum求和函数sumBy() .在集合的基础上调用上it函数
    println(list.sumBy {
        it * 2
    })

    println(list.sumByDouble {
        it.toDouble() / 2
    })

    val numbers = listOf<Int>(1, 2, 3, 4)
    val sum2 =
        numbers.reduce { sum, element -> sum + element } // s = 5 T = 2、10、4 -> 5 + 2 -> 7 + 10 -> 17 + 4 = 21

    val sum3 = numbers.fold(0) { sum, ele ->
        sum + ele * 2 // 0 + 5 + 2 + 10 + 4 ->
    }

    /**
     * reduce的初始值是第一个元素。在第一个元素的基础上，一直向后进行迭代调用值来调用相对应的方法。
     * 在对元素进行reduce的时候，此时如果集合为空的集合，那么此时会产生异常。
     * 而 fold的初始化的不是第一个元素，而是另外提供的一个初始化值。包括第一个值内一次和初始化做一定的操作。
     * 当list为空的时候，此时不会产生异常，会返回初始值。
     */
    println(sum2)
    println(sum3)

    //fold 和 reduce 默认都是从集合的 left -> right。如何需要从集合的右侧开始进行规约。 foldRight() 或者 reduceRight()
    //通过查看源码发现。参数的顺序产生变化。第二个参数变成累加值。
    val sum4 = numbers.foldRight(0) { sum, ele ->
        ele + sum * 2 // 0 + 5 + 2 + 10 + 4 ->
    }

    //如果需要加上针对Index的判断的话，那么也存在函数
    val sum5 = numbers.foldIndexed(0) { index, sum, ele ->
        if (index % 2 == 0)
            sum + ele
        else
            sum + ele * 2
        //0 + 1 + 4 + 3 + 8
    }

    println(sum4)

    println(sum5)

}

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

Compiled from "Comparisons.kt"
public final class com.lonbon.kotlin.collection.CollectionComparableKt$collectionSort$$inlined$sortedBy$1<T> implements java.util.Comparator {
  public com.lonbon.kotlin.collection.CollectionComparableKt$collectionSort$$inlined$sortedBy$1();
    Code:
       0: aload_0
       1: invokespecial #16                 // Method java/lang/Object."<init>":()V
       4: return

  public final int compare(T, T);
    Code:
       0: aload_1
       1: checkcast     #23                 // class java/lang/String
       4: astore_3
       5: iconst_0
       6: istore        4
       8: aload_3
       9: invokevirtual #27                 // Method java/lang/String.length:()I
      12: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: checkcast     #35                 // class java/lang/Comparable
      18: aload_2
      19: checkcast     #23                 // class java/lang/String
      22: astore_3
      23: astore        5
      25: iconst_0
      26: istore        4
      28: aload_3
      29: invokevirtual #27                 // Method java/lang/String.length:()I
      32: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: aload         5
      37: swap
      38: checkcast     #35                 // class java/lang/Comparable
      41: invokestatic  #41                 // Method kotlin/comparisons/ComparisonsKt.compareValues:(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
      44: ireturn
}

Compiled from "CollectionComparable.kt"
public final class com.lonbon.kotlin.collection.CollectionComparableKt {
  public static final void main();
    Code:
       0: invokestatic  #9                  // Method collectionPolymerization:()V
       3: return

  public static final void notNatureComparable();
    Code:
       0: invokedynamic #29,  0             // InvokeDynamic #0:compare:()Ljava/util/Comparator;
       5: astore_0
       6: iconst_3
       7: anewarray     #31                 // class java/lang/String
      10: astore_2
      11: aload_2
      12: iconst_0
      13: ldc           #33                 // String aaa
      15: aastore
      16: aload_2
      17: iconst_1
      18: ldc           #35                 // String bb
      20: aastore
      21: aload_2
      22: iconst_2
      23: ldc           #37                 // String c
      25: aastore
      26: aload_2
      27: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
      30: astore_1
      31: aload_1
      32: checkcast     #45                 // class java/lang/Iterable
      35: aload_0
      36: invokestatic  #49                 // Method kotlin/collections/CollectionsKt.sortedWith:(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
      39: checkcast     #45                 // class java/lang/Iterable
      42: aconst_null
      43: aconst_null
      44: aconst_null
      45: iconst_0
      46: aconst_null
      47: aconst_null
      48: bipush        63
      50: aconst_null
      51: invokestatic  #53                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
      54: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      57: swap
      58: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      61: new           #67                 // class com/lonbon/kotlin/collection/CollectionComparableKt$notNatureComparable$$inlined$compareBy$1
      64: dup
      65: invokespecial #70                 // Method com/lonbon/kotlin/collection/CollectionComparableKt$notNatureComparable$$inlined$compareBy$1."<init>":()V
      68: checkcast     #72                 // class java/util/Comparator
      71: astore_2
      72: return

  public static final void collectionSort();
    Code:
       0: iconst_5
       1: anewarray     #80                 // class java/lang/Integer
       4: astore_1
       5: aload_1
       6: iconst_0
       7: iconst_1
       8: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: aastore
      12: aload_1
      13: iconst_1
      14: iconst_2
      15: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      18: aastore
      19: aload_1
      20: iconst_2
      21: iconst_3
      22: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: aload_1
      27: iconst_3
      28: iconst_4
      29: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      32: aastore
      33: aload_1
      34: iconst_4
      35: iconst_5
      36: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      39: aastore
      40: aload_1
      41: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
      44: astore_0
      45: iconst_4
      46: anewarray     #86                 // class com/lonbon/kotlin/collection/Version
      49: astore_2
      50: aload_2
      51: iconst_0
      52: new           #86                 // class com/lonbon/kotlin/collection/Version
      55: dup
      56: iconst_1
      57: iconst_1
      58: invokespecial #89                 // Method com/lonbon/kotlin/collection/Version."<init>":(II)V
      61: aastore
      62: aload_2
      63: iconst_1
      64: new           #86                 // class com/lonbon/kotlin/collection/Version
      67: dup
      68: iconst_1
      69: iconst_2
      70: invokespecial #89                 // Method com/lonbon/kotlin/collection/Version."<init>":(II)V
      73: aastore
      74: aload_2
      75: iconst_2
      76: new           #86                 // class com/lonbon/kotlin/collection/Version
      79: dup
      80: iconst_2
      81: iconst_3
      82: invokespecial #89                 // Method com/lonbon/kotlin/collection/Version."<init>":(II)V
      85: aastore
      86: aload_2
      87: iconst_3
      88: new           #86                 // class com/lonbon/kotlin/collection/Version
      91: dup
      92: iconst_2
      93: iconst_1
      94: invokespecial #89                 // Method com/lonbon/kotlin/collection/Version."<init>":(II)V
      97: aastore
      98: aload_2
      99: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     102: astore_1
     103: aload_0
     104: checkcast     #45                 // class java/lang/Iterable
     107: invokestatic  #93                 // Method kotlin/collections/CollectionsKt.sorted:(Ljava/lang/Iterable;)Ljava/util/List;
     110: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     113: swap
     114: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     117: aload_0
     118: checkcast     #45                 // class java/lang/Iterable
     121: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.sortedDescending:(Ljava/lang/Iterable;)Ljava/util/List;
     124: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     127: swap
     128: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     131: aload_1
     132: checkcast     #45                 // class java/lang/Iterable
     135: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.sortedDescending:(Ljava/lang/Iterable;)Ljava/util/List;
     138: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     141: swap
     142: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     145: aload_1
     146: checkcast     #45                 // class java/lang/Iterable
     149: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.sortedDescending:(Ljava/lang/Iterable;)Ljava/util/List;
     152: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     155: swap
     156: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     159: iconst_5
     160: anewarray     #31                 // class java/lang/String
     163: astore_3
     164: aload_3
     165: iconst_0
     166: ldc           #98                 // String one
     168: aastore
     169: aload_3
     170: iconst_1
     171: ldc           #100                // String two
     173: aastore
     174: aload_3
     175: iconst_2
     176: ldc           #102                // String three
     178: aastore
     179: aload_3
     180: iconst_3
     181: ldc           #104                // String four
     183: aastore
     184: aload_3
     185: iconst_4
     186: ldc           #106                // String five
     188: aastore
     189: aload_3
     190: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     193: astore_2
     194: aload_2
     195: checkcast     #45                 // class java/lang/Iterable
     198: astore_3
     199: iconst_0
     200: istore        4
     202: aload_3
     203: new           #108                // class com/lonbon/kotlin/collection/CollectionComparableKt$collectionSort$$inlined$sortedBy$1
     206: dup
     207: invokespecial #109                // Method com/lonbon/kotlin/collection/CollectionComparableKt$collectionSort$$inlined$sortedBy$1."<init>":()V
     210: checkcast     #72                 // class java/util/Comparator
     213: invokestatic  #49                 // Method kotlin/collections/CollectionsKt.sortedWith:(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
     216: checkcast     #45                 // class java/lang/Iterable
     219: aconst_null
     220: aconst_null
     221: aconst_null
     222: iconst_0
     223: aconst_null
     224: aconst_null
     225: bipush        63
     227: aconst_null
     228: invokestatic  #53                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     231: astore_3
     232: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     235: aload_3
     236: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     239: aload_2
     240: checkcast     #45                 // class java/lang/Iterable
     243: astore_3
     244: iconst_0
     245: istore        4
     247: aload_3
     248: new           #111                // class com/lonbon/kotlin/collection/CollectionComparableKt$collectionSort$$inlined$sortedByDescending$1
     251: dup
     252: invokespecial #112                // Method com/lonbon/kotlin/collection/CollectionComparableKt$collectionSort$$inlined$sortedByDescending$1."<init>":()V
     255: checkcast     #72                 // class java/util/Comparator
     258: invokestatic  #49                 // Method kotlin/collections/CollectionsKt.sortedWith:(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
     261: checkcast     #45                 // class java/lang/Iterable
     264: aconst_null
     265: aconst_null
     266: aconst_null
     267: iconst_0
     268: aconst_null
     269: aconst_null
     270: bipush        63
     272: aconst_null
     273: invokestatic  #53                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     276: astore_3
     277: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     280: aload_3
     281: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     284: return

  public static final void collectionReversed();
    Code:
       0: bipush        6
       2: anewarray     #80                 // class java/lang/Integer
       5: astore_1
       6: aload_1
       7: iconst_0
       8: iconst_1
       9: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      12: aastore
      13: aload_1
      14: iconst_1
      15: iconst_2
      16: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      19: aastore
      20: aload_1
      21: iconst_2
      22: iconst_3
      23: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      26: aastore
      27: aload_1
      28: iconst_3
      29: iconst_4
      30: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      33: aastore
      34: aload_1
      35: iconst_4
      36: iconst_5
      37: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      40: aastore
      41: aload_1
      42: iconst_5
      43: bipush        6
      45: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      48: aastore
      49: aload_1
      50: invokestatic  #124                // Method kotlin/collections/CollectionsKt.mutableListOf:([Ljava/lang/Object;)Ljava/util/List;
      53: astore_0
      54: aload_0
      55: checkcast     #45                 // class java/lang/Iterable
      58: invokestatic  #127                // Method kotlin/collections/CollectionsKt.reversed:(Ljava/lang/Iterable;)Ljava/util/List;
      61: astore_1
      62: aload_0
      63: invokestatic  #131                // Method kotlin/collections/CollectionsKt.asReversedMutable:(Ljava/util/List;)Ljava/util/List;
      66: astore_2
      67: aload_0
      68: bipush        7
      70: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      73: invokeinterface #137,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      78: pop
      79: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      82: aload_1
      83: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      86: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      89: aload_2
      90: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      93: aload_0
      94: checkcast     #45                 // class java/lang/Iterable
      97: aconst_null
      98: aconst_null
      99: aconst_null
     100: iconst_0
     101: aconst_null
     102: aconst_null
     103: bipush        63
     105: aconst_null
     106: invokestatic  #53                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     109: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     112: swap
     113: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     116: return

  public static final void collectionShuffled();
    Code:
       0: iconst_5
       1: anewarray     #80                 // class java/lang/Integer
       4: astore_1
       5: aload_1
       6: iconst_0
       7: iconst_1
       8: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: aastore
      12: aload_1
      13: iconst_1
      14: iconst_2
      15: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      18: aastore
      19: aload_1
      20: iconst_2
      21: iconst_3
      22: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: aload_1
      27: iconst_3
      28: iconst_4
      29: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      32: aastore
      33: aload_1
      34: iconst_4
      35: iconst_5
      36: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      39: aastore
      40: aload_1
      41: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
      44: astore_0
      45: aload_0
      46: checkcast     #45                 // class java/lang/Iterable
      49: invokestatic  #143                // Method kotlin/collections/CollectionsKt.shuffled:(Ljava/lang/Iterable;)Ljava/util/List;
      52: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      55: swap
      56: invokevirtual #65                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      59: return

  public static final void collectionPolymerization();
    Code:
       0: iconst_4
       1: anewarray     #80                 // class java/lang/Integer
       4: astore_1
       5: aload_1
       6: iconst_0
       7: iconst_1
       8: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: aastore
      12: aload_1
      13: iconst_1
      14: sipush        543
      17: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      20: aastore
      21: aload_1
      22: iconst_2
      23: bipush        6
      25: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      28: aastore
      29: aload_1
      30: iconst_3
      31: bipush        89
      33: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      36: aastore
      37: aload_1
      38: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
      41: astore_0
      42: aload_0
      43: checkcast     #45                 // class java/lang/Iterable
      46: invokestatic  #147                // Method kotlin/collections/CollectionsKt.minOrThrow:(Ljava/lang/Iterable;)Ljava/lang/Comparable;
      49: checkcast     #149                // class java/lang/Number
      52: invokevirtual #153                // Method java/lang/Number.intValue:()I
      55: istore_1
      56: aload_0
      57: checkcast     #45                 // class java/lang/Iterable
      60: invokestatic  #156                // Method kotlin/collections/CollectionsKt.maxOrThrow:(Ljava/lang/Iterable;)Ljava/lang/Comparable;
      63: checkcast     #149                // class java/lang/Number
      66: invokevirtual #153                // Method java/lang/Number.intValue:()I
      69: istore_2
      70: aload_0
      71: checkcast     #45                 // class java/lang/Iterable
      74: invokestatic  #160                // Method kotlin/collections/CollectionsKt.averageOfInt:(Ljava/lang/Iterable;)D
      77: dstore_3
      78: aload_0
      79: checkcast     #45                 // class java/lang/Iterable
      82: invokestatic  #164                // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
      85: istore        5
      87: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      90: iload_1
      91: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
      94: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
      97: iload_2
      98: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     101: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     104: dload_3
     105: invokevirtual #170                // Method java/io/PrintStream.println:(D)V
     108: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     111: iload         5
     113: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     116: aload_0
     117: checkcast     #45                 // class java/lang/Iterable
     120: astore        6
     122: iconst_0
     123: istore        7
     125: iconst_0
     126: istore        8
     128: aload         6
     130: invokeinterface #174,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     135: astore        9
     137: aload         9
     139: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     144: ifeq          189
     147: aload         9
     149: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     154: astore        10
     156: iload         8
     158: aload         10
     160: checkcast     #149                // class java/lang/Number
     163: invokevirtual #153                // Method java/lang/Number.intValue:()I
     166: istore        11
     168: istore        23
     170: iconst_0
     171: istore        12
     173: iload         11
     175: iconst_2
     176: imul
     177: istore        24
     179: iload         23
     181: iload         24
     183: iadd
     184: istore        8
     186: goto          137
     189: iload         8
     191: istore        6
     193: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     196: iload         6
     198: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     201: aload_0
     202: checkcast     #45                 // class java/lang/Iterable
     205: astore        6
     207: iconst_0
     208: istore        7
     210: dconst_0
     211: dstore        8
     213: aload         6
     215: invokeinterface #174,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     220: astore        10
     222: aload         10
     224: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     229: ifeq          276
     232: aload         10
     234: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     239: astore        11
     241: dload         8
     243: aload         11
     245: checkcast     #149                // class java/lang/Number
     248: invokevirtual #153                // Method java/lang/Number.intValue:()I
     251: istore        12
     253: dstore        23
     255: iconst_0
     256: istore        13
     258: iload         12
     260: i2d
     261: iconst_2
     262: i2d
     263: ddiv
     264: dstore        25
     266: dload         23
     268: dload         25
     270: dadd
     271: dstore        8
     273: goto          222
     276: dload         8
     278: dstore        6
     280: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     283: dload         6
     285: invokevirtual #170                // Method java/io/PrintStream.println:(D)V
     288: iconst_4
     289: anewarray     #80                 // class java/lang/Integer
     292: astore        7
     294: aload         7
     296: iconst_0
     297: iconst_1
     298: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     301: aastore
     302: aload         7
     304: iconst_1
     305: iconst_2
     306: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     309: aastore
     310: aload         7
     312: iconst_2
     313: iconst_3
     314: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     317: aastore
     318: aload         7
     320: iconst_3
     321: iconst_4
     322: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     325: aastore
     326: aload         7
     328: invokestatic  #43                 // Method kotlin/collections/CollectionsKt.listOf:([Ljava/lang/Object;)Ljava/util/List;
     331: astore        6
     333: aload         6
     335: checkcast     #45                 // class java/lang/Iterable
     338: astore        8
     340: iconst_0
     341: istore        9
     343: aload         8
     345: invokeinterface #174,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     350: astore        10
     352: aload         10
     354: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     359: ifne          372
     362: new           #186                // class java/lang/UnsupportedOperationException
     365: dup
     366: ldc           #188                // String Empty collection can\'t be reduced.
     368: invokespecial #191                // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V
     371: athrow
     372: aload         10
     374: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     379: astore        11
     381: aload         10
     383: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     388: ifeq          432
     391: aload         11
     393: aload         10
     395: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     400: checkcast     #149                // class java/lang/Number
     403: invokevirtual #153                // Method java/lang/Number.intValue:()I
     406: istore        12
     408: checkcast     #149                // class java/lang/Number
     411: invokevirtual #153                // Method java/lang/Number.intValue:()I
     414: istore        13
     416: iconst_0
     417: istore        14
     419: iload         13
     421: iload         12
     423: iadd
     424: invokestatic  #84                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     427: astore        11
     429: goto          381
     432: aload         11
     434: checkcast     #149                // class java/lang/Number
     437: invokevirtual #153                // Method java/lang/Number.intValue:()I
     440: istore        7
     442: aload         6
     444: checkcast     #45                 // class java/lang/Iterable
     447: astore        9
     449: iconst_0
     450: istore        10
     452: iconst_0
     453: istore        11
     455: iload         10
     457: istore        12
     459: aload         9
     461: invokeinterface #174,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     466: astore        13
     468: aload         13
     470: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     475: ifeq          516
     478: aload         13
     480: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     485: astore        14
     487: iload         12
     489: aload         14
     491: checkcast     #149                // class java/lang/Number
     494: invokevirtual #153                // Method java/lang/Number.intValue:()I
     497: istore        15
     499: istore        16
     501: iconst_0
     502: istore        17
     504: iload         16
     506: iload         15
     508: iconst_2
     509: imul
     510: iadd
     511: istore        12
     513: goto          468
     516: iload         12
     518: istore        8
     520: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     523: iload         7
     525: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     528: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     531: iload         8
     533: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     536: aload         6
     538: astore        10
     540: iconst_0
     541: istore        11
     543: iconst_0
     544: istore        12
     546: iload         11
     548: istore        13
     550: aload         10
     552: invokeinterface #194,  1          // InterfaceMethod java/util/List.isEmpty:()Z
     557: ifne          620
     560: aload         10
     562: aload         10
     564: invokeinterface #197,  1          // InterfaceMethod java/util/List.size:()I
     569: invokeinterface #201,  2          // InterfaceMethod java/util/List.listIterator:(I)Ljava/util/ListIterator;
     574: astore        14
     576: aload         14
     578: invokeinterface #206,  1          // InterfaceMethod java/util/ListIterator.hasPrevious:()Z
     583: ifeq          620
     586: aload         14
     588: invokeinterface #209,  1          // InterfaceMethod java/util/ListIterator.previous:()Ljava/lang/Object;
     593: iload         13
     595: istore        15
     597: checkcast     #149                // class java/lang/Number
     600: invokevirtual #153                // Method java/lang/Number.intValue:()I
     603: istore        16
     605: iconst_0
     606: istore        17
     608: iload         15
     610: iload         16
     612: iconst_2
     613: imul
     614: iadd
     615: istore        13
     617: goto          576
     620: iload         13
     622: istore        9
     624: aload         6
     626: checkcast     #45                 // class java/lang/Iterable
     629: astore        11
     631: iconst_0
     632: istore        12
     634: iconst_0
     635: istore        13
     637: iconst_0
     638: istore        14
     640: iload         12
     642: istore        15
     644: aload         11
     646: invokeinterface #174,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     651: astore        16
     653: aload         16
     655: invokeinterface #180,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     660: ifeq          735
     663: aload         16
     665: invokeinterface #184,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     670: astore        17
     672: iload         14
     674: iinc          14, 1
     677: istore        18
     679: iload         18
     681: ifge          687
     684: invokestatic  #212                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
     687: iload         18
     689: iload         15
     691: aload         17
     693: checkcast     #149                // class java/lang/Number
     696: invokevirtual #153                // Method java/lang/Number.intValue:()I
     699: istore        19
     701: istore        20
     703: istore        21
     705: iconst_0
     706: istore        22
     708: iload         21
     710: iconst_2
     711: irem
     712: ifne          723
     715: iload         20
     717: iload         19
     719: iadd
     720: goto          730
     723: iload         20
     725: iload         19
     727: iconst_2
     728: imul
     729: iadd
     730: istore        15
     732: goto          653
     735: iload         15
     737: istore        10
     739: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     742: iload         9
     744: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     747: getstatic     #59                 // Field java/lang/System.out:Ljava/io/PrintStream;
     750: iload         10
     752: invokevirtual #167                // Method java/io/PrintStream.println:(I)V
     755: return

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

  private static final int notNatureComparable$lambda$0(java.lang.String, java.lang.String);
    Code:
       0: aload_0
       1: invokevirtual #263                // Method java/lang/String.length:()I
       4: aload_1
       5: invokevirtual #263                // Method java/lang/String.length:()I
       8: isub
       9: ireturn
}

Compiled from "Comparisons.kt"
public final class com.lonbon.kotlin.collection.CollectionComparableKt$notNatureComparable$$inlined$compareBy$1<T> implements java.util.Comparator {
  public com.lonbon.kotlin.collection.CollectionComparableKt$notNatureComparable$$inlined$compareBy$1();
    Code:
       0: aload_0
       1: invokespecial #16                 // Method java/lang/Object."<init>":()V
       4: return

  public final int compare(T, T);
    Code:
       0: aload_1
       1: checkcast     #23                 // class java/lang/String
       4: astore_3
       5: iconst_0
       6: istore        4
       8: aload_3
       9: invokevirtual #27                 // Method java/lang/String.length:()I
      12: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: checkcast     #35                 // class java/lang/Comparable
      18: aload_2
      19: checkcast     #23                 // class java/lang/String
      22: astore_3
      23: astore        5
      25: iconst_0
      26: istore        4
      28: aload_3
      29: invokevirtual #27                 // Method java/lang/String.length:()I
      32: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: checkcast     #35                 // class java/lang/Comparable
      38: aload         5
      40: swap
      41: invokestatic  #41                 // Method kotlin/comparisons/ComparisonsKt.compareValues:(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
      44: ireturn
}

Compiled from "Comparisons.kt"
public final class com.lonbon.kotlin.collection.CollectionComparableKt$collectionSort$$inlined$sortedByDescending$1<T> implements java.util.Comparator {
  public com.lonbon.kotlin.collection.CollectionComparableKt$collectionSort$$inlined$sortedByDescending$1();
    Code:
       0: aload_0
       1: invokespecial #16                 // Method java/lang/Object."<init>":()V
       4: return

  public final int compare(T, T);
    Code:
       0: aload_2
       1: checkcast     #23                 // class java/lang/String
       4: astore_3
       5: iconst_0
       6: istore        4
       8: aload_3
       9: invokevirtual #27                 // Method java/lang/String.length:()I
      12: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: checkcast     #35                 // class java/lang/Comparable
      18: aload_1
      19: checkcast     #23                 // class java/lang/String
      22: astore_3
      23: astore        5
      25: iconst_0
      26: istore        4
      28: aload_3
      29: invokevirtual #27                 // Method java/lang/String.length:()I
      32: invokestatic  #33                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: aload         5
      37: swap
      38: checkcast     #35                 // class java/lang/Comparable
      41: invokestatic  #41                 // Method kotlin/comparisons/ComparisonsKt.compareValues:(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
      44: ireturn
}


package aoc.day2

sealed class Instruction {
    data class FORWARD(val value: Int) : Instruction()
    data class DOWN(val value: Int) : Instruction()
    data class UP(val value: Int) : Instruction()
}

fun parseInstructions(input: List<String>): List<Instruction> =
    input.map { it.split(" ") }.map { (instruction, value) ->
        when (instruction) {
            "forward" -> Instruction.FORWARD(value.toInt())
            "down" -> Instruction.DOWN(value.toInt())
            "up" -> Instruction.UP(value.toInt())
            else -> throw Exception("This when is exhaustive")
        }
    }

fun part1(input: List<Instruction>): Int {
    val (pos, depth) = input.fold(Pair(0, 0)) { sum, add ->
        when (add) {
            is Instruction.FORWARD -> sum.copy(first = sum.first + add.value)
            is Instruction.DOWN -> sum.copy(second = sum.second + add.value)
            is Instruction.UP -> sum.copy(second = sum.second - add.value)
        }
    }

    return pos * depth
}

fun part2(input: List<Instruction>): Int {
    val (pos, depth, aim) = input.fold(Triple(0, 0, 0)) { sum, add ->
        when (add) {
            is Instruction.FORWARD -> sum.copy(
                first = sum.first + add.value,
                second = sum.second + sum.third * add.value
            )
            is Instruction.DOWN -> sum.copy(third = sum.third + add.value)
            is Instruction.UP -> sum.copy(third = sum.third - add.value)
        }
    }

    return pos * depth
}

Compiled from "day2.kt"
public final class aoc.day2.Day2Kt {
  public static final java.util.List<aoc.day2.Instruction> parseInstructions(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/Iterable
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: astore_3
      15: new           #20                 // class java/util/ArrayList
      18: dup
      19: aload_1
      20: bipush        10
      22: invokestatic  #26                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      25: invokespecial #30                 // Method java/util/ArrayList."<init>":(I)V
      28: checkcast     #32                 // class java/util/Collection
      31: astore        4
      33: iconst_0
      34: istore        5
      36: aload_3
      37: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      42: astore        6
      44: aload         6
      46: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      51: ifeq          116
      54: aload         6
      56: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      61: astore        7
      63: aload         4
      65: aload         7
      67: checkcast     #48                 // class java/lang/String
      70: astore        8
      72: astore        13
      74: iconst_0
      75: istore        9
      77: aload         8
      79: checkcast     #50                 // class java/lang/CharSequence
      82: iconst_1
      83: anewarray     #48                 // class java/lang/String
      86: astore        10
      88: aload         10
      90: iconst_0
      91: ldc           #52                 // String
      93: aastore
      94: aload         10
      96: iconst_0
      97: iconst_0
      98: bipush        6
     100: aconst_null
     101: invokestatic  #58                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     104: aload         13
     106: swap
     107: invokeinterface #62,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     112: pop
     113: goto          44
     116: aload         4
     118: checkcast     #64                 // class java/util/List
     121: nop
     122: checkcast     #18                 // class java/lang/Iterable
     125: astore_1
     126: nop
     127: iconst_0
     128: istore_2
     129: aload_1
     130: astore_3
     131: new           #20                 // class java/util/ArrayList
     134: dup
     135: aload_1
     136: bipush        10
     138: invokestatic  #26                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     141: invokespecial #30                 // Method java/util/ArrayList."<init>":(I)V
     144: checkcast     #32                 // class java/util/Collection
     147: astore        4
     149: iconst_0
     150: istore        5
     152: aload_3
     153: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     158: astore        6
     160: aload         6
     162: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     167: ifeq          380
     170: aload         6
     172: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     177: astore        7
     179: aload         4
     181: aload         7
     183: checkcast     #64                 // class java/util/List
     186: astore        8
     188: astore        13
     190: iconst_0
     191: istore        9
     193: aload         8
     195: iconst_0
     196: invokeinterface #68,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     201: checkcast     #48                 // class java/lang/String
     204: astore        10
     206: aload         8
     208: iconst_1
     209: invokeinterface #68,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     214: checkcast     #48                 // class java/lang/String
     217: astore        11
     219: aload         10
     221: astore        12
     223: aload         12
     225: invokevirtual #72                 // Method java/lang/String.hashCode:()I
     228: lookupswitch  { // 3
            -677145915: 264
                  3739: 277
               3089570: 290
               default: 357
          }
     264: aload         12
     266: ldc           #74                 // String forward
     268: invokevirtual #77                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     271: ifne          303
     274: goto          357
     277: aload         12
     279: ldc           #79                 // String up
     281: invokevirtual #77                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     284: ifne          339
     287: goto          357
     290: aload         12
     292: ldc           #81                 // String down
     294: invokevirtual #77                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     297: ifne          321
     300: goto          357
     303: new           #83                 // class aoc/day2/Instruction$FORWARD
     306: dup
     307: aload         11
     309: invokestatic  #89                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     312: invokespecial #90                 // Method aoc/day2/Instruction$FORWARD."<init>":(I)V
     315: checkcast     #92                 // class aoc/day2/Instruction
     318: goto          367
     321: new           #94                 // class aoc/day2/Instruction$DOWN
     324: dup
     325: aload         11
     327: invokestatic  #89                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     330: invokespecial #95                 // Method aoc/day2/Instruction$DOWN."<init>":(I)V
     333: checkcast     #92                 // class aoc/day2/Instruction
     336: goto          367
     339: new           #97                 // class aoc/day2/Instruction$UP
     342: dup
     343: aload         11
     345: invokestatic  #89                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     348: invokespecial #98                 // Method aoc/day2/Instruction$UP."<init>":(I)V
     351: checkcast     #92                 // class aoc/day2/Instruction
     354: goto          367
     357: new           #100                // class java/lang/Exception
     360: dup
     361: ldc           #102                // String This when is exhaustive
     363: invokespecial #105                // Method java/lang/Exception."<init>":(Ljava/lang/String;)V
     366: athrow
     367: nop
     368: aload         13
     370: swap
     371: invokeinterface #62,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     376: pop
     377: goto          160
     380: aload         4
     382: checkcast     #64                 // class java/util/List
     385: nop
     386: areturn

  public static final int part1(java.util.List<? extends aoc.day2.Instruction>);
    Code:
       0: aload_0
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/Iterable
      10: astore_2
      11: new           #127                // class kotlin/Pair
      14: dup
      15: iconst_0
      16: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      19: iconst_0
      20: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      23: invokespecial #134                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      26: astore_3
      27: iconst_0
      28: istore        4
      30: aload_3
      31: astore        5
      33: aload_2
      34: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      39: astore        6
      41: aload         6
      43: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      48: ifeq          218
      51: aload         6
      53: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      58: astore        7
      60: aload         5
      62: aload         7
      64: checkcast     #92                 // class aoc/day2/Instruction
      67: astore        8
      69: astore        9
      71: iconst_0
      72: istore        10
      74: aload         8
      76: astore        11
      78: aload         11
      80: instanceof    #83                 // class aoc/day2/Instruction$FORWARD
      83: ifeq          120
      86: aload         9
      88: aload         9
      90: invokevirtual #137                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      93: checkcast     #139                // class java/lang/Number
      96: invokevirtual #142                // Method java/lang/Number.intValue:()I
      99: aload         8
     101: checkcast     #83                 // class aoc/day2/Instruction$FORWARD
     104: invokevirtual #145                // Method aoc/day2/Instruction$FORWARD.getValue:()I
     107: iadd
     108: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     111: aconst_null
     112: iconst_2
     113: aconst_null
     114: invokestatic  #149                // Method kotlin/Pair.copy$default:(Lkotlin/Pair;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Pair;
     117: goto          212
     120: aload         11
     122: instanceof    #94                 // class aoc/day2/Instruction$DOWN
     125: ifeq          162
     128: aload         9
     130: aconst_null
     131: aload         9
     133: invokevirtual #152                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     136: checkcast     #139                // class java/lang/Number
     139: invokevirtual #142                // Method java/lang/Number.intValue:()I
     142: aload         8
     144: checkcast     #94                 // class aoc/day2/Instruction$DOWN
     147: invokevirtual #153                // Method aoc/day2/Instruction$DOWN.getValue:()I
     150: iadd
     151: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     154: iconst_1
     155: aconst_null
     156: invokestatic  #149                // Method kotlin/Pair.copy$default:(Lkotlin/Pair;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Pair;
     159: goto          212
     162: aload         11
     164: instanceof    #97                 // class aoc/day2/Instruction$UP
     167: ifeq          204
     170: aload         9
     172: aconst_null
     173: aload         9
     175: invokevirtual #152                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     178: checkcast     #139                // class java/lang/Number
     181: invokevirtual #142                // Method java/lang/Number.intValue:()I
     184: aload         8
     186: checkcast     #97                 // class aoc/day2/Instruction$UP
     189: invokevirtual #154                // Method aoc/day2/Instruction$UP.getValue:()I
     192: isub
     193: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     196: iconst_1
     197: aconst_null
     198: invokestatic  #149                // Method kotlin/Pair.copy$default:(Lkotlin/Pair;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Pair;
     201: goto          212
     204: new           #156                // class kotlin/NoWhenBranchMatchedException
     207: dup
     208: invokespecial #159                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     211: athrow
     212: nop
     213: astore        5
     215: goto          41
     218: aload         5
     220: astore_1
     221: aload_1
     222: invokevirtual #162                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     225: checkcast     #139                // class java/lang/Number
     228: invokevirtual #142                // Method java/lang/Number.intValue:()I
     231: istore_2
     232: aload_1
     233: invokevirtual #165                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     236: checkcast     #139                // class java/lang/Number
     239: invokevirtual #142                // Method java/lang/Number.intValue:()I
     242: istore_3
     243: iload_2
     244: iload_3
     245: imul
     246: ireturn

  public static final int part2(java.util.List<? extends aoc.day2.Instruction>);
    Code:
       0: aload_0
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/Iterable
      10: astore_2
      11: new           #179                // class kotlin/Triple
      14: dup
      15: iconst_0
      16: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      19: iconst_0
      20: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      23: iconst_0
      24: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      27: invokespecial #182                // Method kotlin/Triple."<init>":(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
      30: astore_3
      31: iconst_0
      32: istore        4
      34: aload_3
      35: astore        5
      37: aload_2
      38: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          259
      55: aload         6
      57: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: astore        7
      64: aload         5
      66: aload         7
      68: checkcast     #92                 // class aoc/day2/Instruction
      71: astore        8
      73: astore        9
      75: iconst_0
      76: istore        10
      78: aload         8
      80: astore        11
      82: aload         11
      84: instanceof    #83                 // class aoc/day2/Instruction$FORWARD
      87: ifeq          159
      90: aload         9
      92: aload         9
      94: invokevirtual #183                // Method kotlin/Triple.getFirst:()Ljava/lang/Object;
      97: checkcast     #139                // class java/lang/Number
     100: invokevirtual #142                // Method java/lang/Number.intValue:()I
     103: aload         8
     105: checkcast     #83                 // class aoc/day2/Instruction$FORWARD
     108: invokevirtual #145                // Method aoc/day2/Instruction$FORWARD.getValue:()I
     111: iadd
     112: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     115: aload         9
     117: invokevirtual #184                // Method kotlin/Triple.getSecond:()Ljava/lang/Object;
     120: checkcast     #139                // class java/lang/Number
     123: invokevirtual #142                // Method java/lang/Number.intValue:()I
     126: aload         9
     128: invokevirtual #187                // Method kotlin/Triple.getThird:()Ljava/lang/Object;
     131: checkcast     #139                // class java/lang/Number
     134: invokevirtual #142                // Method java/lang/Number.intValue:()I
     137: aload         8
     139: checkcast     #83                 // class aoc/day2/Instruction$FORWARD
     142: invokevirtual #145                // Method aoc/day2/Instruction$FORWARD.getValue:()I
     145: imul
     146: iadd
     147: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     150: aconst_null
     151: iconst_4
     152: aconst_null
     153: invokestatic  #190                // Method kotlin/Triple.copy$default:(Lkotlin/Triple;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Triple;
     156: goto          253
     159: aload         11
     161: instanceof    #94                 // class aoc/day2/Instruction$DOWN
     164: ifeq          202
     167: aload         9
     169: aconst_null
     170: aconst_null
     171: aload         9
     173: invokevirtual #187                // Method kotlin/Triple.getThird:()Ljava/lang/Object;
     176: checkcast     #139                // class java/lang/Number
     179: invokevirtual #142                // Method java/lang/Number.intValue:()I
     182: aload         8
     184: checkcast     #94                 // class aoc/day2/Instruction$DOWN
     187: invokevirtual #153                // Method aoc/day2/Instruction$DOWN.getValue:()I
     190: iadd
     191: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     194: iconst_3
     195: aconst_null
     196: invokestatic  #190                // Method kotlin/Triple.copy$default:(Lkotlin/Triple;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Triple;
     199: goto          253
     202: aload         11
     204: instanceof    #97                 // class aoc/day2/Instruction$UP
     207: ifeq          245
     210: aload         9
     212: aconst_null
     213: aconst_null
     214: aload         9
     216: invokevirtual #187                // Method kotlin/Triple.getThird:()Ljava/lang/Object;
     219: checkcast     #139                // class java/lang/Number
     222: invokevirtual #142                // Method java/lang/Number.intValue:()I
     225: aload         8
     227: checkcast     #97                 // class aoc/day2/Instruction$UP
     230: invokevirtual #154                // Method aoc/day2/Instruction$UP.getValue:()I
     233: isub
     234: invokestatic  #131                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     237: iconst_3
     238: aconst_null
     239: invokestatic  #190                // Method kotlin/Triple.copy$default:(Lkotlin/Triple;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Triple;
     242: goto          253
     245: new           #156                // class kotlin/NoWhenBranchMatchedException
     248: dup
     249: invokespecial #159                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     252: athrow
     253: nop
     254: astore        5
     256: goto          45
     259: aload         5
     261: astore_1
     262: aload_1
     263: invokevirtual #191                // Method kotlin/Triple.component1:()Ljava/lang/Object;
     266: checkcast     #139                // class java/lang/Number
     269: invokevirtual #142                // Method java/lang/Number.intValue:()I
     272: istore_2
     273: aload_1
     274: invokevirtual #192                // Method kotlin/Triple.component2:()Ljava/lang/Object;
     277: checkcast     #139                // class java/lang/Number
     280: invokevirtual #142                // Method java/lang/Number.intValue:()I
     283: istore_3
     284: aload_1
     285: invokevirtual #195                // Method kotlin/Triple.component3:()Ljava/lang/Object;
     288: checkcast     #139                // class java/lang/Number
     291: invokevirtual #142                // Method java/lang/Number.intValue:()I
     294: istore        4
     296: iload_2
     297: iload_3
     298: imul
     299: ireturn
}


package algo.expert.solutions.medium

import java.lang.Integer.min

// Solution: Dynamic programming
fun minNumberOfCoinsForChange(n: Int, denoms: List<Int>): Int {
    val coins = IntArray(n + 1) { -1 }
    coins[0] = 0
    for (d in denoms.sorted()) {
        for (i in 1 until coins.size) {
            if (d <= i) {
                val remaining = i - d
                val remainingCoins = coins[remaining]
                if (remainingCoins != -1) {
                    if (coins[i] == -1) {
                        coins[i] = 1 + remainingCoins
                    } else {
                        coins[i] = min(coins[i], 1 + remainingCoins)
                    }
                }
            }
        }
    }
    return coins[n]
}

// Solution: Build a tree of all possible combinations -- very inefficient
class TreeNode(var value: Int) {
    var children: MutableList<TreeNode> = mutableListOf()
}

fun minNumberOfCoinsForChangeTreeNaive(n: Int, denoms: List<Int>): Int {
    val root = buildTree(TreeNode(n), denoms)
    val shortest = findShortestBranchEqualToZero(root, 0)
    return shortest
}

fun buildTree(node: TreeNode, denoms: List<Int>): TreeNode {
    for (d in denoms) {
        if (node.value - d >= 0) {
            node.children.add(TreeNode(node.value - d))
        }
    }

    for (c in node.children) {
        buildTree(c, denoms)
    }

    return node
}

fun findShortestBranchEqualToZero(node: TreeNode, depth: Int): Int {
    if (node.value == 0) {
        return depth
    }

    if (node.children.isEmpty()) {
        return Integer.MAX_VALUE
    }

    val lengths = mutableListOf<Int>()
    for (c in node.children) {
        lengths.add(findShortestBranchEqualToZero(c, depth + 1))
    }

    return lengths.min()!!
}

// Solution: Build optimized tree (without using actual tree data structure)
// - Build out the tree breadth-first
// - Stop on the first branch to equal 0 instead of building out the entire tree
// - Stop building branches < 0

fun minNumberOfCoinsForChangeTreeOptimized(n: Int, denoms: List<Int>): Int {
    return treeOptimizedHelper(listOf(n), denoms, 1)
}

fun treeOptimizedHelper(row: List<Int>, denoms: List<Int>, depth: Int): Int {

    if (row.isEmpty()) {
        return Integer.MAX_VALUE
    }

    val nextRow = mutableListOf<Int>()
    for (node in row) {
        for (d in denoms) {
            if (node - d == 0) {
                return depth
            }
            if (node - d > 0) {
                nextRow.add(node - d)
            }
        }
    }

    return treeOptimizedHelper(nextRow, denoms, depth + 1)
}

Compiled from "MinCoinsForChange.kt"
public final class algo.expert.solutions.medium.MinCoinsForChangeKt {
  public static final int minNumberOfCoinsForChange(int, java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: ldc           #10                 // String denoms
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_3
       8: iload_0
       9: iconst_1
      10: iadd
      11: istore        4
      13: iload         4
      15: newarray       int
      17: astore        5
      19: iload_3
      20: iload         4
      22: if_icmpge     40
      25: iload_3
      26: istore        6
      28: aload         5
      30: iload         6
      32: iconst_m1
      33: iastore
      34: iinc          3, 1
      37: goto          19
      40: aload         5
      42: astore_2
      43: aload_2
      44: iconst_0
      45: iconst_0
      46: iastore
      47: aload_1
      48: checkcast     #18                 // class java/lang/Iterable
      51: invokestatic  #24                 // Method kotlin/collections/CollectionsKt.sorted:(Ljava/lang/Iterable;)Ljava/util/List;
      54: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      59: astore_3
      60: aload_3
      61: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      66: ifeq          163
      69: aload_3
      70: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      75: checkcast     #42                 // class java/lang/Number
      78: invokevirtual #46                 // Method java/lang/Number.intValue:()I
      81: istore        4
      83: iconst_1
      84: istore        5
      86: aload_2
      87: arraylength
      88: istore        6
      90: iload         5
      92: iload         6
      94: if_icmpge     60
      97: iload         4
      99: iload         5
     101: if_icmpgt     157
     104: iload         5
     106: iload         4
     108: isub
     109: istore        7
     111: aload_2
     112: iload         7
     114: iaload
     115: istore        8
     117: iload         8
     119: iconst_m1
     120: if_icmpeq     157
     123: aload_2
     124: iload         5
     126: iaload
     127: iconst_m1
     128: if_icmpne     142
     131: aload_2
     132: iload         5
     134: iconst_1
     135: iload         8
     137: iadd
     138: iastore
     139: goto          157
     142: aload_2
     143: iload         5
     145: aload_2
     146: iload         5
     148: iaload
     149: iconst_1
     150: iload         8
     152: iadd
     153: invokestatic  #52                 // Method java/lang/Integer.min:(II)I
     156: iastore
     157: iinc          5, 1
     160: goto          90
     163: aload_2
     164: iload_0
     165: iaload
     166: ireturn

  public static final int minNumberOfCoinsForChangeTreeNaive(int, java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: ldc           #10                 // String denoms
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #65                 // class algo/expert/solutions/medium/TreeNode
       9: dup
      10: iload_0
      11: invokespecial #69                 // Method algo/expert/solutions/medium/TreeNode."<init>":(I)V
      14: aload_1
      15: invokestatic  #73                 // Method buildTree:(Lalgo/expert/solutions/medium/TreeNode;Ljava/util/List;)Lalgo/expert/solutions/medium/TreeNode;
      18: astore_2
      19: aload_2
      20: iconst_0
      21: invokestatic  #77                 // Method findShortestBranchEqualToZero:(Lalgo/expert/solutions/medium/TreeNode;I)I
      24: istore_3
      25: iload_3
      26: ireturn

  public static final algo.expert.solutions.medium.TreeNode buildTree(algo.expert.solutions.medium.TreeNode, java.util.List<java.lang.Integer>);
    Code:
       0: aload_0
       1: ldc           #83                 // String node
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #10                 // String denoms
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      18: astore_2
      19: aload_2
      20: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      25: ifeq          76
      28: aload_2
      29: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      34: checkcast     #42                 // class java/lang/Number
      37: invokevirtual #46                 // Method java/lang/Number.intValue:()I
      40: istore_3
      41: aload_0
      42: invokevirtual #86                 // Method algo/expert/solutions/medium/TreeNode.getValue:()I
      45: iload_3
      46: isub
      47: iflt          19
      50: aload_0
      51: invokevirtual #90                 // Method algo/expert/solutions/medium/TreeNode.getChildren:()Ljava/util/List;
      54: new           #65                 // class algo/expert/solutions/medium/TreeNode
      57: dup
      58: aload_0
      59: invokevirtual #86                 // Method algo/expert/solutions/medium/TreeNode.getValue:()I
      62: iload_3
      63: isub
      64: invokespecial #69                 // Method algo/expert/solutions/medium/TreeNode."<init>":(I)V
      67: invokeinterface #94,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      72: pop
      73: goto          19
      76: aload_0
      77: invokevirtual #90                 // Method algo/expert/solutions/medium/TreeNode.getChildren:()Ljava/util/List;
      80: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      85: astore_2
      86: aload_2
      87: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      92: ifeq          114
      95: aload_2
      96: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     101: checkcast     #65                 // class algo/expert/solutions/medium/TreeNode
     104: astore_3
     105: aload_3
     106: aload_1
     107: invokestatic  #73                 // Method buildTree:(Lalgo/expert/solutions/medium/TreeNode;Ljava/util/List;)Lalgo/expert/solutions/medium/TreeNode;
     110: pop
     111: goto          86
     114: aload_0
     115: areturn

  public static final int findShortestBranchEqualToZero(algo.expert.solutions.medium.TreeNode, int);
    Code:
       0: aload_0
       1: ldc           #83                 // String node
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #86                 // Method algo/expert/solutions/medium/TreeNode.getValue:()I
      10: ifne          15
      13: iload_1
      14: ireturn
      15: aload_0
      16: invokevirtual #90                 // Method algo/expert/solutions/medium/TreeNode.getChildren:()Ljava/util/List;
      19: invokeinterface #98,  1           // InterfaceMethod java/util/List.isEmpty:()Z
      24: ifeq          30
      27: ldc           #99                 // int 2147483647
      29: ireturn
      30: new           #101                // class java/util/ArrayList
      33: dup
      34: invokespecial #104                // Method java/util/ArrayList."<init>":()V
      37: checkcast     #26                 // class java/util/List
      40: astore_2
      41: aload_0
      42: invokevirtual #90                 // Method algo/expert/solutions/medium/TreeNode.getChildren:()Ljava/util/List;
      45: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      50: astore_3
      51: aload_3
      52: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      57: ifeq          92
      60: aload_3
      61: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      66: checkcast     #65                 // class algo/expert/solutions/medium/TreeNode
      69: astore        4
      71: aload_2
      72: aload         4
      74: iload_1
      75: iconst_1
      76: iadd
      77: invokestatic  #77                 // Method findShortestBranchEqualToZero:(Lalgo/expert/solutions/medium/TreeNode;I)I
      80: invokestatic  #108                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      83: invokeinterface #94,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      88: pop
      89: goto          51
      92: aload_2
      93: checkcast     #18                 // class java/lang/Iterable
      96: invokestatic  #112                // Method kotlin/collections/CollectionsKt.minOrThrow:(Ljava/lang/Iterable;)Ljava/lang/Comparable;
      99: dup
     100: invokestatic  #116                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     103: checkcast     #42                 // class java/lang/Number
     106: invokevirtual #46                 // Method java/lang/Number.intValue:()I
     109: ireturn

  public static final int minNumberOfCoinsForChangeTreeOptimized(int, java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: ldc           #10                 // String denoms
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iload_0
       7: invokestatic  #108                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      10: invokestatic  #123                // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      13: aload_1
      14: iconst_1
      15: invokestatic  #127                // Method treeOptimizedHelper:(Ljava/util/List;Ljava/util/List;I)I
      18: ireturn

  public static final int treeOptimizedHelper(java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, int);
    Code:
       0: aload_0
       1: ldc           #130                // String row
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #10                 // String denoms
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: invokeinterface #98,  1           // InterfaceMethod java/util/List.isEmpty:()Z
      18: ifeq          24
      21: ldc           #99                 // int 2147483647
      23: ireturn
      24: new           #101                // class java/util/ArrayList
      27: dup
      28: invokespecial #104                // Method java/util/ArrayList."<init>":()V
      31: checkcast     #26                 // class java/util/List
      34: astore_3
      35: aload_0
      36: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      41: astore        4
      43: aload         4
      45: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      50: ifeq          137
      53: aload         4
      55: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      60: checkcast     #42                 // class java/lang/Number
      63: invokevirtual #46                 // Method java/lang/Number.intValue:()I
      66: istore        5
      68: aload_1
      69: invokeinterface #30,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      74: astore        6
      76: aload         6
      78: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      83: ifeq          43
      86: aload         6
      88: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      93: checkcast     #42                 // class java/lang/Number
      96: invokevirtual #46                 // Method java/lang/Number.intValue:()I
      99: istore        7
     101: iload         5
     103: iload         7
     105: isub
     106: ifne          111
     109: iload_2
     110: ireturn
     111: iload         5
     113: iload         7
     115: isub
     116: ifle          76
     119: aload_3
     120: iload         5
     122: iload         7
     124: isub
     125: invokestatic  #108                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     128: invokeinterface #94,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     133: pop
     134: goto          76
     137: aload_3
     138: aload_1
     139: iload_2
     140: iconst_1
     141: iadd
     142: invokestatic  #127                // Method treeOptimizedHelper:(Ljava/util/List;Ljava/util/List;I)I
     145: ireturn
}


package io.github.ajoz.sequences

/**
 * Returns a sequence containing the results of applying the given [transform] function to each element in the original
 * sequence and the result of previous application. For the case of first element in the sequence the [initial] value
 * will be used as the "previous result" and passed to [transform] function.
 * @param initial Initial element from which the scan should take place.
 * @param transform Two argument function used to perform scan operation.
 */
fun <T, R> Sequence<T>.scan(initial: R, transform: (R, T) -> R): Sequence<R> {
    return TransformingScanSequence(this, initial, transform)
}

/**
 * A sequence which returns the results of applying the given [transformer] function to the values in the underlying
 * [sequence]. Each [transformer] is given a previously calculated value and a new value. In case of the first element
 * of the given [sequence] the [transformer] function will use [initial] as the "previously calculated value".
 */
internal class TransformingScanSequence<T, R>
constructor(private val sequence: Sequence<T>,
            private val initial: R,
            private val transformer: (R, T) -> R) : Sequence<R> {
    override fun iterator(): Iterator<R> = object : Iterator<R> {
        val iterator = sequence.iterator()
        var previous = initial
        override fun next(): R {
            val mapped = transformer(previous, iterator.next())
            previous = mapped
            return mapped
        }

        override fun hasNext(): Boolean {
            return iterator.hasNext()
        }
    }
}

/**
 * Returns first repeated element in the [Sequence]. Can throw a [NoSuchElementException] if the [Sequence] doesn't have
 * elements or there are no repeating elements
 */
fun <T> Sequence<T>.firstRepeated(): T {
    val set = HashSet<T>()
    for (element in this) {
        if (set.contains(element)) return element
        else set.add(element)
    }

    throw NoSuchElementException("Sequence contains no repeating elements")
}

Compiled from "Sequences.kt"
public final class io.github.ajoz.sequences.SequencesKt {
  public static final <T, R> kotlin.sequences.Sequence<R> scan(kotlin.sequences.Sequence<? extends T>, R, kotlin.jvm.functions.Function2<? super R, ? super T, ? extends R>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #18                 // String transform
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: new           #20                 // class io/github/ajoz/sequences/TransformingScanSequence
      15: dup
      16: aload_0
      17: aload_1
      18: aload_2
      19: invokespecial #24                 // Method io/github/ajoz/sequences/TransformingScanSequence."<init>":(Lkotlin/sequences/Sequence;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
      22: checkcast     #26                 // class kotlin/sequences/Sequence
      25: areturn

  public static final <T> T firstRepeated(kotlin.sequences.Sequence<? extends T>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #36                 // class java/util/HashSet
       9: dup
      10: invokespecial #39                 // Method java/util/HashSet."<init>":()V
      13: astore_1
      14: aload_0
      15: invokeinterface #43,  1           // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      20: astore_2
      21: aload_2
      22: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      27: ifeq          56
      30: aload_2
      31: invokeinterface #53,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      36: astore_3
      37: aload_1
      38: aload_3
      39: invokevirtual #57                 // Method java/util/HashSet.contains:(Ljava/lang/Object;)Z
      42: ifeq          47
      45: aload_3
      46: areturn
      47: aload_1
      48: aload_3
      49: invokevirtual #60                 // Method java/util/HashSet.add:(Ljava/lang/Object;)Z
      52: pop
      53: goto          21
      56: new           #62                 // class java/util/NoSuchElementException
      59: dup
      60: ldc           #64                 // String Sequence contains no repeating elements
      62: invokespecial #67                 // Method java/util/NoSuchElementException."<init>":(Ljava/lang/String;)V
      65: athrow
}