package day05

import java.io.File

class Stack<T> {
    private val mutableList = mutableListOf<T>()

    fun push(vararg element: T) {
        mutableList.addAll(element)
    }

    fun pop(): T? {
        return if (mutableList.isNotEmpty()) {
            mutableList.removeLast()
        } else {
            null
        }
    }

    fun pop(n: Int): List<T> {
        val result = mutableListOf<T>()
        result.addAll(mutableList.takeLast(n))
        repeat(n) {
            mutableList.removeLast()
        }
        return result
    }

    override fun toString(): String {
        return mutableList.toString()
    }
}

fun main() {

    fun <A, B, R, T> Pair<A, B>.map(transformA: (A) -> R, transformB: (B) -> T): Pair<R, T> {
        return Pair(
            transformA(first),
            transformB(second)
        )
    }

    fun parseMovements(s: String) = s
        .lines()
        .map { row ->
            row.split(" ")
                .filter { it.toIntOrNull() != null }
                .map { it.toInt() }
        }

    fun parseStore(s: String) = s.lines().reversed()
        .foldIndexed(mutableMapOf()) { index, acc: MutableMap<Int, Stack<Char>>, str ->
            str.forEachIndexed { idx, char ->
                if (index == 0 && char.isDigit()) {
                    val i = char.digitToInt()
                    acc[i] = Stack<Char>()
                }

                if (char.isLetter()) {
                    val i = idx / 4 + 1
                    val stack = acc[i]
                    stack?.let { st ->
                        st.push(char)
                        acc[i] = st
                    }
                }
            }
            acc
        }

    fun parseInput(input: String) = input.split("\n\n")
        .foldIndexed("" to "") { index: Int, acc: Pair<String, String>, s: String ->
            if (index % 2 != 0) acc.copy(second = s) else acc.copy(first = s)
        }.map(
            transformA = ::parseStore,
            transformB = ::parseMovements
        )

    fun part1(input: String): String {
        val (storeData, movedData) = parseInput(input)
        movedData.forEach { (move, from, to) ->
            (1..move).forEach { _ ->
                val el = storeData[from]?.pop()
                el?.let {
                    storeData[to]?.push(it)
                }
            }
        }
        return storeData.values.map { it.pop() }.joinToString("")
    }

    fun part2(input: String): String {
        val (storeData, movedData) = parseInput(input)
        movedData.forEach { (move, from, to) ->
            val el = storeData[from]?.pop(move)
            el?.let {
                storeData[to]?.push(*it.toTypedArray())
            }

        }
        return storeData.values.map { it.pop() }.joinToString("")
    }

    val testInput = File("src/day05/Day05_test.txt").readText()

    println(part1(testInput))
    println(part2(testInput))
//
    val input = File("src/day05/Day05.txt").readText()

    println(part1(input))
    println(part2(input))
}

Compiled from "Day05.kt"
public final class day05.Day05Kt {
  public static final void main();
    Code:
       0: new           #8                  // class java/io/File
       3: dup
       4: ldc           #10                 // String src/day05/Day05_test.txt
       6: invokespecial #14                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #20                 // Method kotlin/io/FilesKt.readText$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String;
      15: astore_0
      16: aload_0
      17: invokestatic  #24                 // Method main$part1:(Ljava/lang/String;)Ljava/lang/String;
      20: getstatic     #30                 // Field java/lang/System.out:Ljava/io/PrintStream;
      23: swap
      24: invokevirtual #36                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      27: aload_0
      28: invokestatic  #39                 // Method main$part2:(Ljava/lang/String;)Ljava/lang/String;
      31: getstatic     #30                 // Field java/lang/System.out:Ljava/io/PrintStream;
      34: swap
      35: invokevirtual #36                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      38: new           #8                  // class java/io/File
      41: dup
      42: ldc           #41                 // String src/day05/Day05.txt
      44: invokespecial #14                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      47: aconst_null
      48: iconst_1
      49: aconst_null
      50: invokestatic  #20                 // Method kotlin/io/FilesKt.readText$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String;
      53: astore_1
      54: aload_1
      55: invokestatic  #24                 // Method main$part1:(Ljava/lang/String;)Ljava/lang/String;
      58: getstatic     #30                 // Field java/lang/System.out:Ljava/io/PrintStream;
      61: swap
      62: invokevirtual #36                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      65: aload_1
      66: invokestatic  #39                 // Method main$part2:(Ljava/lang/String;)Ljava/lang/String;
      69: getstatic     #30                 // Field java/lang/System.out:Ljava/io/PrintStream;
      72: swap
      73: invokevirtual #36                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      76: return

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

  private static final <A, B, R, T> kotlin.Pair<R, T> main$map(kotlin.Pair<? extends A, ? extends B>, kotlin.jvm.functions.Function1<? super A, ? extends R>, kotlin.jvm.functions.Function1<? super B, ? extends T>);
    Code:
       0: new           #54                 // class kotlin/Pair
       3: dup
       4: aload_1
       5: aload_0
       6: invokevirtual #58                 // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
       9: invokeinterface #64,  2           // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      14: aload_2
      15: aload_0
      16: invokevirtual #67                 // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      19: invokeinterface #64,  2           // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      24: invokespecial #70                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      27: areturn

  private static final java.util.List<java.util.List<java.lang.Integer>> main$parseMovements(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #80                 // class java/lang/CharSequence
       4: invokestatic  #86                 // Method kotlin/text/StringsKt.lines:(Ljava/lang/CharSequence;)Ljava/util/List;
       7: checkcast     #88                 // class java/lang/Iterable
      10: astore_1
      11: nop
      12: iconst_0
      13: istore_2
      14: aload_1
      15: astore_3
      16: new           #90                 // class java/util/ArrayList
      19: dup
      20: aload_1
      21: bipush        10
      23: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      26: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
      29: checkcast     #101                // class java/util/Collection
      32: astore        4
      34: iconst_0
      35: istore        5
      37: aload_3
      38: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          323
      55: aload         6
      57: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: astore        7
      64: aload         4
      66: aload         7
      68: checkcast     #116                // class java/lang/String
      71: astore        8
      73: astore        20
      75: iconst_0
      76: istore        9
      78: aload         8
      80: checkcast     #80                 // class java/lang/CharSequence
      83: iconst_1
      84: anewarray     #116                // class java/lang/String
      87: astore        10
      89: aload         10
      91: iconst_0
      92: ldc           #118                // String
      94: aastore
      95: aload         10
      97: iconst_0
      98: iconst_0
      99: bipush        6
     101: aconst_null
     102: invokestatic  #122                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     105: checkcast     #88                 // class java/lang/Iterable
     108: astore        10
     110: nop
     111: iconst_0
     112: istore        11
     114: aload         10
     116: astore        12
     118: new           #90                 // class java/util/ArrayList
     121: dup
     122: invokespecial #124                // Method java/util/ArrayList."<init>":()V
     125: checkcast     #101                // class java/util/Collection
     128: astore        13
     130: iconst_0
     131: istore        14
     133: aload         12
     135: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     140: astore        15
     142: aload         15
     144: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     149: ifeq          200
     152: aload         15
     154: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     159: astore        16
     161: aload         16
     163: checkcast     #116                // class java/lang/String
     166: astore        17
     168: iconst_0
     169: istore        18
     171: aload         17
     173: invokestatic  #128                // Method kotlin/text/StringsKt.toIntOrNull:(Ljava/lang/String;)Ljava/lang/Integer;
     176: ifnull        183
     179: iconst_1
     180: goto          184
     183: iconst_0
     184: ifeq          142
     187: aload         13
     189: aload         16
     191: invokeinterface #132,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     196: pop
     197: goto          142
     200: aload         13
     202: checkcast     #134                // class java/util/List
     205: nop
     206: checkcast     #88                 // class java/lang/Iterable
     209: astore        10
     211: nop
     212: iconst_0
     213: istore        11
     215: aload         10
     217: astore        12
     219: new           #90                 // class java/util/ArrayList
     222: dup
     223: aload         10
     225: bipush        10
     227: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     230: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
     233: checkcast     #101                // class java/util/Collection
     236: astore        13
     238: iconst_0
     239: istore        14
     241: aload         12
     243: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     248: astore        15
     250: aload         15
     252: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     257: ifeq          304
     260: aload         15
     262: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     267: astore        16
     269: aload         13
     271: aload         16
     273: checkcast     #116                // class java/lang/String
     276: astore        17
     278: astore        19
     280: iconst_0
     281: istore        18
     283: aload         17
     285: invokestatic  #140                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     288: nop
     289: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     292: aload         19
     294: swap
     295: invokeinterface #132,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     300: pop
     301: goto          250
     304: aload         13
     306: checkcast     #134                // class java/util/List
     309: nop
     310: nop
     311: aload         20
     313: swap
     314: invokeinterface #132,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     319: pop
     320: goto          45
     323: aload         4
     325: checkcast     #134                // class java/util/List
     328: nop
     329: areturn

  private static final java.util.Map<java.lang.Integer, day05.Stack<java.lang.Character>> main$parseStore(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #80                 // class java/lang/CharSequence
       4: invokestatic  #86                 // Method kotlin/text/StringsKt.lines:(Ljava/lang/CharSequence;)Ljava/util/List;
       7: checkcast     #88                 // class java/lang/Iterable
      10: invokestatic  #172                // Method kotlin/collections/CollectionsKt.reversed:(Ljava/lang/Iterable;)Ljava/util/List;
      13: checkcast     #88                 // class java/lang/Iterable
      16: astore_1
      17: new           #174                // class java/util/LinkedHashMap
      20: dup
      21: invokespecial #175                // Method java/util/LinkedHashMap."<init>":()V
      24: checkcast     #177                // class java/util/Map
      27: astore_2
      28: nop
      29: iconst_0
      30: istore_3
      31: iconst_0
      32: istore        4
      34: aload_2
      35: astore        5
      37: aload_1
      38: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          301
      55: aload         6
      57: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: astore        7
      64: iload         4
      66: iinc          4, 1
      69: istore        8
      71: iload         8
      73: ifge          79
      76: invokestatic  #180                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      79: iload         8
      81: aload         5
      83: aload         7
      85: checkcast     #116                // class java/lang/String
      88: astore        9
      90: astore        10
      92: istore        11
      94: iconst_0
      95: istore        12
      97: aload         9
      99: checkcast     #80                 // class java/lang/CharSequence
     102: astore        13
     104: iconst_0
     105: istore        14
     107: iconst_0
     108: istore        15
     110: iconst_0
     111: istore        16
     113: iload         16
     115: aload         13
     117: invokeinterface #184,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     122: if_icmpge     293
     125: aload         13
     127: iload         16
     129: invokeinterface #188,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     134: istore        17
     136: iload         15
     138: iinc          15, 1
     141: iload         17
     143: istore        18
     145: istore        19
     147: iconst_0
     148: istore        20
     150: iload         11
     152: ifne          194
     155: iload         18
     157: invokestatic  #194                // Method java/lang/Character.isDigit:(C)Z
     160: ifeq          194
     163: iload         18
     165: invokestatic  #200                // Method kotlin/text/CharsKt.digitToInt:(C)I
     168: istore        21
     170: iload         21
     172: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     175: astore        22
     177: aload         10
     179: aload         22
     181: new           #202                // class day05/Stack
     184: dup
     185: invokespecial #203                // Method day05/Stack."<init>":()V
     188: invokeinterface #207,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     193: pop
     194: iload         18
     196: invokestatic  #210                // Method java/lang/Character.isLetter:(C)Z
     199: ifeq          285
     202: iload         19
     204: iconst_4
     205: idiv
     206: iconst_1
     207: iadd
     208: istore        21
     210: aload         10
     212: iload         21
     214: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     217: invokeinterface #213,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     222: checkcast     #202                // class day05/Stack
     225: astore        23
     227: aload         23
     229: dup
     230: ifnull        283
     233: astore        24
     235: iconst_0
     236: istore        25
     238: aload         24
     240: iconst_1
     241: anewarray     #190                // class java/lang/Character
     244: astore        26
     246: aload         26
     248: iconst_0
     249: iload         18
     251: invokestatic  #216                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     254: aastore
     255: aload         26
     257: invokevirtual #220                // Method day05/Stack.push:([Ljava/lang/Object;)V
     260: iload         21
     262: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     265: astore        27
     267: aload         10
     269: aload         27
     271: aload         24
     273: invokeinterface #207,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     278: pop
     279: nop
     280: goto          285
     283: pop
     284: nop
     285: nop
     286: nop
     287: iinc          16, 1
     290: goto          113
     293: nop
     294: aload         10
     296: astore        5
     298: goto          45
     301: aload         5
     303: areturn

  private static final kotlin.Pair<java.util.Map<java.lang.Integer, day05.Stack<java.lang.Character>>, java.util.List<java.util.List<java.lang.Integer>>> main$parseInput(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #80                 // class java/lang/CharSequence
       4: iconst_1
       5: anewarray     #116                // class java/lang/String
       8: astore_1
       9: aload_1
      10: iconst_0
      11: ldc           #249                // String \n\n
      13: aastore
      14: aload_1
      15: iconst_0
      16: iconst_0
      17: bipush        6
      19: aconst_null
      20: invokestatic  #122                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      23: checkcast     #88                 // class java/lang/Iterable
      26: astore_1
      27: ldc           #251                // String
      29: ldc           #251                // String
      31: invokestatic  #257                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      34: astore_2
      35: iconst_0
      36: istore_3
      37: iconst_0
      38: istore        4
      40: aload_2
      41: astore        5
      43: aload_1
      44: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      49: astore        6
      51: aload         6
      53: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      58: ifeq          138
      61: aload         6
      63: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      68: astore        7
      70: iload         4
      72: iinc          4, 1
      75: istore        8
      77: iload         8
      79: ifge          85
      82: invokestatic  #180                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      85: iload         8
      87: aload         5
      89: aload         7
      91: checkcast     #116                // class java/lang/String
      94: astore        9
      96: astore        10
      98: istore        11
     100: iconst_0
     101: istore        12
     103: iload         11
     105: iconst_2
     106: irem
     107: ifeq          123
     110: aload         10
     112: aconst_null
     113: aload         9
     115: iconst_1
     116: aconst_null
     117: invokestatic  #261                // Method kotlin/Pair.copy$default:(Lkotlin/Pair;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Pair;
     120: goto          133
     123: aload         10
     125: aload         9
     127: aconst_null
     128: iconst_2
     129: aconst_null
     130: invokestatic  #261                // Method kotlin/Pair.copy$default:(Lkotlin/Pair;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Lkotlin/Pair;
     133: astore        5
     135: goto          51
     138: aload         5
     140: getstatic     #267                // Field day05/Day05Kt$main$parseInput$2.INSTANCE:Lday05/Day05Kt$main$parseInput$2;
     143: checkcast     #60                 // class kotlin/jvm/functions/Function1
     146: getstatic     #272                // Field day05/Day05Kt$main$parseInput$3.INSTANCE:Lday05/Day05Kt$main$parseInput$3;
     149: checkcast     #60                 // class kotlin/jvm/functions/Function1
     152: invokestatic  #274                // Method main$map:(Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair;
     155: areturn

  private static final java.lang.String main$part1(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #277                // Method main$parseInput:(Ljava/lang/String;)Lkotlin/Pair;
       4: astore_1
       5: aload_1
       6: invokevirtual #280                // Method kotlin/Pair.component1:()Ljava/lang/Object;
       9: checkcast     #177                // class java/util/Map
      12: astore_2
      13: aload_1
      14: invokevirtual #283                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      17: checkcast     #134                // class java/util/List
      20: astore_3
      21: aload_3
      22: checkcast     #88                 // class java/lang/Iterable
      25: astore        4
      27: iconst_0
      28: istore        5
      30: aload         4
      32: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      37: astore        6
      39: aload         6
      41: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      46: ifeq          270
      49: aload         6
      51: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      56: astore        7
      58: aload         7
      60: checkcast     #134                // class java/util/List
      63: astore        8
      65: iconst_0
      66: istore        9
      68: aload         8
      70: iconst_0
      71: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      76: checkcast     #288                // class java/lang/Number
      79: invokevirtual #291                // Method java/lang/Number.intValue:()I
      82: istore        10
      84: aload         8
      86: iconst_1
      87: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      92: checkcast     #288                // class java/lang/Number
      95: invokevirtual #291                // Method java/lang/Number.intValue:()I
      98: istore        11
     100: aload         8
     102: iconst_2
     103: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     108: checkcast     #288                // class java/lang/Number
     111: invokevirtual #291                // Method java/lang/Number.intValue:()I
     114: istore        12
     116: new           #293                // class kotlin/ranges/IntRange
     119: dup
     120: iconst_1
     121: iload         10
     123: invokespecial #296                // Method kotlin/ranges/IntRange."<init>":(II)V
     126: checkcast     #88                 // class java/lang/Iterable
     129: astore        13
     131: iconst_0
     132: istore        14
     134: aload         13
     136: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     141: astore        15
     143: aload         15
     145: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     150: ifeq          264
     153: aload         15
     155: checkcast     #298                // class kotlin/collections/IntIterator
     158: invokevirtual #301                // Method kotlin/collections/IntIterator.nextInt:()I
     161: istore        16
     163: iconst_0
     164: istore        17
     166: aload_2
     167: iload         11
     169: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     172: invokeinterface #213,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     177: checkcast     #202                // class day05/Stack
     180: dup
     181: ifnull        193
     184: invokevirtual #304                // Method day05/Stack.pop:()Ljava/lang/Object;
     187: checkcast     #190                // class java/lang/Character
     190: goto          195
     193: pop
     194: aconst_null
     195: astore        18
     197: aload         18
     199: dup
     200: ifnull        257
     203: invokevirtual #308                // Method java/lang/Character.charValue:()C
     206: istore        19
     208: iconst_0
     209: istore        20
     211: aload_2
     212: iload         12
     214: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     217: invokeinterface #213,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     222: checkcast     #202                // class day05/Stack
     225: dup
     226: ifnull        252
     229: iconst_1
     230: anewarray     #190                // class java/lang/Character
     233: astore        21
     235: aload         21
     237: iconst_0
     238: iload         19
     240: invokestatic  #216                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
     243: aastore
     244: aload         21
     246: invokevirtual #220                // Method day05/Stack.push:([Ljava/lang/Object;)V
     249: goto          253
     252: pop
     253: nop
     254: goto          259
     257: pop
     258: nop
     259: nop
     260: nop
     261: goto          143
     264: nop
     265: nop
     266: nop
     267: goto          39
     270: nop
     271: aload_2
     272: invokeinterface #312,  1          // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
     277: checkcast     #88                 // class java/lang/Iterable
     280: astore        4
     282: iconst_0
     283: istore        5
     285: aload         4
     287: astore        6
     289: new           #90                 // class java/util/ArrayList
     292: dup
     293: aload         4
     295: bipush        10
     297: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     300: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
     303: checkcast     #101                // class java/util/Collection
     306: astore        7
     308: iconst_0
     309: istore        8
     311: aload         6
     313: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     318: astore        9
     320: aload         9
     322: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     327: ifeq          373
     330: aload         9
     332: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     337: astore        10
     339: aload         7
     341: aload         10
     343: checkcast     #202                // class day05/Stack
     346: astore        11
     348: astore        22
     350: iconst_0
     351: istore        12
     353: aload         11
     355: invokevirtual #304                // Method day05/Stack.pop:()Ljava/lang/Object;
     358: checkcast     #190                // class java/lang/Character
     361: aload         22
     363: swap
     364: invokeinterface #132,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     369: pop
     370: goto          320
     373: aload         7
     375: checkcast     #134                // class java/util/List
     378: nop
     379: checkcast     #88                 // class java/lang/Iterable
     382: ldc           #251                // String
     384: checkcast     #80                 // class java/lang/CharSequence
     387: aconst_null
     388: aconst_null
     389: iconst_0
     390: aconst_null
     391: aconst_null
     392: bipush        62
     394: aconst_null
     395: invokestatic  #316                // 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;
     398: areturn

  private static final java.lang.String main$part2(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #277                // Method main$parseInput:(Ljava/lang/String;)Lkotlin/Pair;
       4: astore_1
       5: aload_1
       6: invokevirtual #280                // Method kotlin/Pair.component1:()Ljava/lang/Object;
       9: checkcast     #177                // class java/util/Map
      12: astore_2
      13: aload_1
      14: invokevirtual #283                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      17: checkcast     #134                // class java/util/List
      20: astore_3
      21: aload_3
      22: checkcast     #88                 // class java/lang/Iterable
      25: astore        4
      27: iconst_0
      28: istore        5
      30: aload         4
      32: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      37: astore        6
      39: aload         6
      41: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      46: ifeq          231
      49: aload         6
      51: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      56: astore        7
      58: aload         7
      60: checkcast     #134                // class java/util/List
      63: astore        8
      65: iconst_0
      66: istore        9
      68: aload         8
      70: iconst_0
      71: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      76: checkcast     #288                // class java/lang/Number
      79: invokevirtual #291                // Method java/lang/Number.intValue:()I
      82: istore        10
      84: aload         8
      86: iconst_1
      87: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      92: checkcast     #288                // class java/lang/Number
      95: invokevirtual #291                // Method java/lang/Number.intValue:()I
      98: istore        11
     100: aload         8
     102: iconst_2
     103: invokeinterface #286,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     108: checkcast     #288                // class java/lang/Number
     111: invokevirtual #291                // Method java/lang/Number.intValue:()I
     114: istore        12
     116: aload_2
     117: iload         11
     119: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     122: invokeinterface #213,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     127: checkcast     #202                // class day05/Stack
     130: dup
     131: ifnull        142
     134: iload         10
     136: invokevirtual #332                // Method day05/Stack.pop:(I)Ljava/util/List;
     139: goto          144
     142: pop
     143: aconst_null
     144: astore        13
     146: aload         13
     148: dup
     149: ifnull        224
     152: astore        14
     154: iconst_0
     155: istore        15
     157: aload_2
     158: iload         12
     160: invokestatic  #144                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     163: invokeinterface #213,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     168: checkcast     #202                // class day05/Stack
     171: dup
     172: ifnull        219
     175: aload         14
     177: checkcast     #101                // class java/util/Collection
     180: astore        16
     182: iconst_0
     183: istore        17
     185: aload         16
     187: astore        18
     189: aload         18
     191: iconst_0
     192: anewarray     #190                // class java/lang/Character
     195: invokeinterface #336,  2          // InterfaceMethod java/util/Collection.toArray:([Ljava/lang/Object;)[Ljava/lang/Object;
     200: checkcast     #338                // class "[Ljava/lang/Character;"
     203: astore        19
     205: aload         19
     207: aload         19
     209: arraylength
     210: invokestatic  #344                // Method java/util/Arrays.copyOf:([Ljava/lang/Object;I)[Ljava/lang/Object;
     213: invokevirtual #220                // Method day05/Stack.push:([Ljava/lang/Object;)V
     216: goto          220
     219: pop
     220: nop
     221: goto          226
     224: pop
     225: nop
     226: nop
     227: nop
     228: goto          39
     231: nop
     232: aload_2
     233: invokeinterface #312,  1          // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
     238: checkcast     #88                 // class java/lang/Iterable
     241: astore        4
     243: iconst_0
     244: istore        5
     246: aload         4
     248: astore        6
     250: new           #90                 // class java/util/ArrayList
     253: dup
     254: aload         4
     256: bipush        10
     258: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     261: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
     264: checkcast     #101                // class java/util/Collection
     267: astore        7
     269: iconst_0
     270: istore        8
     272: aload         6
     274: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     279: astore        9
     281: aload         9
     283: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     288: ifeq          334
     291: aload         9
     293: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     298: astore        10
     300: aload         7
     302: aload         10
     304: checkcast     #202                // class day05/Stack
     307: astore        11
     309: astore        20
     311: iconst_0
     312: istore        12
     314: aload         11
     316: invokevirtual #304                // Method day05/Stack.pop:()Ljava/lang/Object;
     319: checkcast     #190                // class java/lang/Character
     322: aload         20
     324: swap
     325: invokeinterface #132,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     330: pop
     331: goto          281
     334: aload         7
     336: checkcast     #134                // class java/util/List
     339: nop
     340: checkcast     #88                 // class java/lang/Iterable
     343: ldc           #251                // String
     345: checkcast     #80                 // class java/lang/CharSequence
     348: aconst_null
     349: aconst_null
     350: iconst_0
     351: aconst_null
     352: aconst_null
     353: bipush        62
     355: aconst_null
     356: invokestatic  #316                // 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;
     359: areturn

  public static final java.util.Map access$main$parseStore(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #353                // Method main$parseStore:(Ljava/lang/String;)Ljava/util/Map;
       4: areturn

  public static final java.util.List access$main$parseMovements(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #356                // Method main$parseMovements:(Ljava/lang/String;)Ljava/util/List;
       4: areturn
}

Compiled from "Day05.kt"
final class day05.Day05Kt$main$parseInput$2 extends kotlin.jvm.internal.FunctionReferenceImpl implements kotlin.jvm.functions.Function1<java.lang.String, java.util.Map<java.lang.Integer, day05.Stack<java.lang.Character>>> {
  public static final day05.Day05Kt$main$parseInput$2 INSTANCE;

  day05.Day05Kt$main$parseInput$2();
    Code:
       0: aload_0
       1: iconst_1
       2: ldc           #11                 // class kotlin/jvm/internal/Intrinsics$Kotlin
       4: ldc           #13                 // String parseStore
       6: ldc           #15                 // String main$parseStore(Ljava/lang/String;)Ljava/util/Map;
       8: iconst_0
       9: invokespecial #18                 // Method kotlin/jvm/internal/FunctionReferenceImpl."<init>":(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
      12: return

  public final java.util.Map<java.lang.Integer, day05.Stack<java.lang.Character>> invoke(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #25                 // String p0
       3: invokestatic  #31                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: invokestatic  #36                 // Method day05/Day05Kt.access$main$parseStore:(Ljava/lang/String;)Ljava/util/Map;
      10: areturn

  public java.lang.Object invoke(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #40                 // class java/lang/String
       5: invokevirtual #42                 // Method invoke:(Ljava/lang/String;)Ljava/util/Map;
       8: areturn

  static {};
    Code:
       0: new           #2                  // class day05/Day05Kt$main$parseInput$2
       3: dup
       4: invokespecial #47                 // Method "<init>":()V
       7: putstatic     #50                 // Field INSTANCE:Lday05/Day05Kt$main$parseInput$2;
      10: return
}

Compiled from "Day05.kt"
final class day05.Day05Kt$main$parseInput$3 extends kotlin.jvm.internal.FunctionReferenceImpl implements kotlin.jvm.functions.Function1<java.lang.String, java.util.List<? extends java.util.List<? extends java.lang.Integer>>> {
  public static final day05.Day05Kt$main$parseInput$3 INSTANCE;

  day05.Day05Kt$main$parseInput$3();
    Code:
       0: aload_0
       1: iconst_1
       2: ldc           #11                 // class kotlin/jvm/internal/Intrinsics$Kotlin
       4: ldc           #13                 // String parseMovements
       6: ldc           #15                 // String main$parseMovements(Ljava/lang/String;)Ljava/util/List;
       8: iconst_0
       9: invokespecial #18                 // Method kotlin/jvm/internal/FunctionReferenceImpl."<init>":(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
      12: return

  public final java.util.List<java.util.List<java.lang.Integer>> invoke(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #25                 // String p0
       3: invokestatic  #31                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: invokestatic  #36                 // Method day05/Day05Kt.access$main$parseMovements:(Ljava/lang/String;)Ljava/util/List;
      10: areturn

  public java.lang.Object invoke(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #40                 // class java/lang/String
       5: invokevirtual #42                 // Method invoke:(Ljava/lang/String;)Ljava/util/List;
       8: areturn

  static {};
    Code:
       0: new           #2                  // class day05/Day05Kt$main$parseInput$3
       3: dup
       4: invokespecial #47                 // Method "<init>":()V
       7: putstatic     #50                 // Field INSTANCE:Lday05/Day05Kt$main$parseInput$3;
      10: return
}


package chriscoomber.manydice

/**
 * A probability is close enough to another one if it's within this threshold.
 */
const val PROBABILITY_FLOAT_THRESHOLD = 0.0000001f

/**
 * A probability is a real number between 0 and 1 inclusive. Users of this type
 * should check it is within those bounds.
 */
typealias Probability = Float

/**
 * Check whether a probability is "equal" to another one - or as close as is
 * possible with floats.
 */
fun Probability.equalsWithinThreshold(other: Probability): Boolean {
    return this > other - PROBABILITY_FLOAT_THRESHOLD || this < other + PROBABILITY_FLOAT_THRESHOLD
}

/**
 * Check that this function is a probability measure on the given space. I.e., check that
 * it is non-negative and sums to 1.
 *
 * Returns true if and only if it's a probability measure.
 */
fun <Outcome> ((Outcome) -> Probability).isProbabilityMeasure(space: Set<Outcome>): Boolean {
    val sum = space.fold(0f) { totalProb, outcome ->
        val probability = this.invoke(outcome)
        if (probability < 0f || probability > 1f) return false
        totalProb + probability
    }
    return sum.equalsWithinThreshold(1f)
}

fun <Outcome> ((Outcome) -> Probability).requireIsProbabilityMeasure(space: Set<Outcome>) =
    this.isProbabilityMeasure(space) || error("Not a probability measure.")

/**
 * A sample space is a set of "outcomes" equipped with:
 *
 * - A sigma-algebra of "events", i.e. sets of outcomes.
 * This is a bit mathematically technical but in general not all
 * sets are necessarily "measurable". However, we will only be
 * dealing with finite spaces, so the sigma-algebra just contains
 * every possible subset of the space. We don't need to declare
 * this in code.
 *
 * - A probability measure which assigns an event to a
 * "probability", i.e. a real number between 0 and 1 inclusive.
 * The measure must satisfy some sensible properties such as:
 *     - The measure of the empty event (no outcomes) is 0
 *     - The measure of the whole space (all outcomes) is 1
 *     - The measure of a disjoint union of events is equal to
 *     the sum of the measures of the events. (Technical note:
 *     this is only required for countable unions. However, this being
 *     a computer and us being mortals bound by the restrictions
 *     of time, I don't think we'll be calculating any infinite
 *     unions anyway, countable or not.)
 */
interface SampleSpace<Outcome> {
    // TODO iterator instead of set?
    val space: Set<Outcome>
    fun measure(event: Set<Outcome>): Probability
}

/**
 * A random variable is a function from a sample space to some measurable space E
 */
interface RandomVariable<Outcome, E> {
    /**
     * The sample space that this random variable is defined on.
     */
    val sampleSpace: SampleSpace<Outcome>

    /**
     * Evaluate the random variable at a particular outcome.
     */
    fun evaluate(outcome: Outcome): E
}

Compiled from "Theory.kt"
public final class chriscoomber.manydice.TheoryKt {
  public static final float PROBABILITY_FLOAT_THRESHOLD;

  public static final boolean equalsWithinThreshold(float, float);
    Code:
       0: fload_0
       1: fload_1
       2: ldc           #7                  // float 1.0E-7f
       4: fsub
       5: fcmpl
       6: ifgt          18
       9: fload_0
      10: fload_1
      11: ldc           #7                  // float 1.0E-7f
      13: fadd
      14: fcmpg
      15: ifge          22
      18: iconst_1
      19: goto          23
      22: iconst_0
      23: ireturn

  public static final <Outcome> boolean isProbabilityMeasure(kotlin.jvm.functions.Function1<? super Outcome, java.lang.Float>, java.util.Set<? extends Outcome>);
    Code:
       0: aload_0
       1: ldc           #16                 // String <this>
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #24                 // String space
       9: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: checkcast     #26                 // class java/lang/Iterable
      16: astore_3
      17: fconst_0
      18: fstore        4
      20: iconst_0
      21: istore        5
      23: fload         4
      25: fstore        6
      27: aload_3
      28: invokeinterface #30,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      33: astore        7
      35: aload         7
      37: invokeinterface #36,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      42: ifeq          107
      45: aload         7
      47: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      52: astore        8
      54: fload         6
      56: aload         8
      58: astore        9
      60: fstore        10
      62: iconst_0
      63: istore        11
      65: aload_0
      66: aload         9
      68: invokeinterface #46,  2           // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      73: checkcast     #48                 // class java/lang/Number
      76: invokevirtual #52                 // Method java/lang/Number.floatValue:()F
      79: fstore        12
      81: fload         12
      83: fconst_0
      84: fcmpg
      85: iflt          95
      88: fload         12
      90: fconst_1
      91: fcmpl
      92: ifle          97
      95: iconst_0
      96: ireturn
      97: fload         10
      99: fload         12
     101: fadd
     102: fstore        6
     104: goto          35
     107: fload         6
     109: fstore_2
     110: fload_2
     111: fconst_1
     112: invokestatic  #54                 // Method equalsWithinThreshold:(FF)Z
     115: ireturn

  public static final <Outcome> boolean requireIsProbabilityMeasure(kotlin.jvm.functions.Function1<? super Outcome, java.lang.Float>, java.util.Set<? extends Outcome>);
    Code:
       0: aload_0
       1: ldc           #16                 // String <this>
       3: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #24                 // String space
       9: invokestatic  #22                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokestatic  #75                 // Method isProbabilityMeasure:(Lkotlin/jvm/functions/Function1;Ljava/util/Set;)Z
      17: ifne          33
      20: new           #77                 // class java/lang/IllegalStateException
      23: dup
      24: ldc           #79                 // String Not a probability measure.
      26: invokevirtual #83                 // Method java/lang/Object.toString:()Ljava/lang/String;
      29: invokespecial #87                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      32: athrow
      33: iconst_1
      34: ireturn
}


package com.jackson.tictactoe.utils

object MinMaxAlgorithm {
    private var player = 'x'
    private var opponent = 'o'

    private fun isMovesLeft(board: Array<CharArray>): Boolean {
        for (i in 0..2) for (j in 0..2) if (board[i][j] == '_') return true
        return false
    }

    private fun evaluate(b: Array<CharArray>): Int {
        // Checking for Rows for X or O victory.
        for (row in 0..2) {
            if (b[row][0] == b[row][1] &&
                b[row][1] == b[row][2]
            ) {
                if (b[row][0] == player) return +10 else if (b[row][0] == opponent) return -10
            }
        }

        for (col in 0..2) {
            if (b[0][col] == b[1][col] &&
                b[1][col] == b[2][col]
            ) {
                if (b[0][col] == player) return +10 else if (b[0][col] == opponent) return -10
            }
        }

        if (b[0][0] == b[1][1] && b[1][1] == b[2][2]) {
            if (b[0][0] == player) return +10 else if (b[0][0] == opponent) return -10
        }
        if (b[0][2] == b[1][1] && b[1][1] == b[2][0]) {
            if (b[0][2] == player) return +10 else if (b[0][2] == opponent) return -10
        }

        return 0
    }

    private fun minimax(
        board: Array<CharArray>,
        depth: Int, isMax: Boolean
    ): Int {
        val score = evaluate(board)

        if (score == 10) return score

        if (score == -10) return score

        if (!isMovesLeft(board)) return 0

        return if (isMax) {
            var best = -1000

            for (i in 0..2) {
                for (j in 0..2) {
                    if (board[i][j] == '_') {
                        board[i][j] = player
                        best = Math.max(
                            best, minimax(
                                board,
                                depth + 1, !isMax
                            )
                        )
                        board[i][j] = '_'
                    }
                }
            }
            best
        } else {
            var best = 1000

            for (i in 0..2) {
                for (j in 0..2) {
                    if (board[i][j] == '_') {
                        board[i][j] = opponent
                        best = Math.min(
                            best, minimax(
                                board,
                                depth + 1, !isMax
                            )
                        )

                        // Undo the move
                        board[i][j] = '_'
                    }
                }
            }
            best
        }
    }

    @JvmStatic
    fun findBestMove(board: Array<CharArray>): Move {
        var bestVal = -1000
        val bestMove = Move()
        bestMove.row = -1
        bestMove.col = -1

        for (i in 0..2) {
            for (j in 0..2) {
                if (board[i][j] == '_') {
                    board[i][j] = player
                    val moveVal = minimax(board, 0, false)
                    board[i][j] = '_'
                    if (moveVal > bestVal) {
                        bestMove.row = i
                        bestMove.col = j
                        bestVal = moveVal
                    }
                }
            }
        }

        return bestMove
    }
    class Move {
        @JvmField
        var row = 0
        @JvmField
        var col = 0
    }
}

Compiled from "MinMaxAlgorithm.kt"
public final class com.jackson.tictactoe.utils.MinMaxAlgorithm {
  public static final com.jackson.tictactoe.utils.MinMaxAlgorithm INSTANCE;

  private static char player;

  private static char opponent;

  private com.jackson.tictactoe.utils.MinMaxAlgorithm();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  private final boolean isMovesLeft(char[][]);
    Code:
       0: iconst_0
       1: istore_2
       2: iload_2
       3: iconst_3
       4: if_icmpge     38
       7: iconst_0
       8: istore_3
       9: iload_3
      10: iconst_3
      11: if_icmpge     32
      14: aload_1
      15: iload_2
      16: aaload
      17: iload_3
      18: caload
      19: bipush        95
      21: if_icmpne     26
      24: iconst_1
      25: ireturn
      26: iinc          3, 1
      29: goto          9
      32: iinc          2, 1
      35: goto          2
      38: iconst_0
      39: ireturn

  private final int evaluate(char[][]);
    Code:
       0: iconst_0
       1: istore_2
       2: iload_2
       3: iconst_3
       4: if_icmpge     67
       7: aload_1
       8: iload_2
       9: aaload
      10: iconst_0
      11: caload
      12: aload_1
      13: iload_2
      14: aaload
      15: iconst_1
      16: caload
      17: if_icmpne     61
      20: aload_1
      21: iload_2
      22: aaload
      23: iconst_1
      24: caload
      25: aload_1
      26: iload_2
      27: aaload
      28: iconst_2
      29: caload
      30: if_icmpne     61
      33: aload_1
      34: iload_2
      35: aaload
      36: iconst_0
      37: caload
      38: getstatic     #23                 // Field player:C
      41: if_icmpne     47
      44: bipush        10
      46: ireturn
      47: aload_1
      48: iload_2
      49: aaload
      50: iconst_0
      51: caload
      52: getstatic     #26                 // Field opponent:C
      55: if_icmpne     61
      58: bipush        -10
      60: ireturn
      61: iinc          2, 1
      64: goto          2
      67: iconst_0
      68: istore_2
      69: iload_2
      70: iconst_3
      71: if_icmpge     134
      74: aload_1
      75: iconst_0
      76: aaload
      77: iload_2
      78: caload
      79: aload_1
      80: iconst_1
      81: aaload
      82: iload_2
      83: caload
      84: if_icmpne     128
      87: aload_1
      88: iconst_1
      89: aaload
      90: iload_2
      91: caload
      92: aload_1
      93: iconst_2
      94: aaload
      95: iload_2
      96: caload
      97: if_icmpne     128
     100: aload_1
     101: iconst_0
     102: aaload
     103: iload_2
     104: caload
     105: getstatic     #23                 // Field player:C
     108: if_icmpne     114
     111: bipush        10
     113: ireturn
     114: aload_1
     115: iconst_0
     116: aaload
     117: iload_2
     118: caload
     119: getstatic     #26                 // Field opponent:C
     122: if_icmpne     128
     125: bipush        -10
     127: ireturn
     128: iinc          2, 1
     131: goto          69
     134: aload_1
     135: iconst_0
     136: aaload
     137: iconst_0
     138: caload
     139: aload_1
     140: iconst_1
     141: aaload
     142: iconst_1
     143: caload
     144: if_icmpne     188
     147: aload_1
     148: iconst_1
     149: aaload
     150: iconst_1
     151: caload
     152: aload_1
     153: iconst_2
     154: aaload
     155: iconst_2
     156: caload
     157: if_icmpne     188
     160: aload_1
     161: iconst_0
     162: aaload
     163: iconst_0
     164: caload
     165: getstatic     #23                 // Field player:C
     168: if_icmpne     174
     171: bipush        10
     173: ireturn
     174: aload_1
     175: iconst_0
     176: aaload
     177: iconst_0
     178: caload
     179: getstatic     #26                 // Field opponent:C
     182: if_icmpne     188
     185: bipush        -10
     187: ireturn
     188: aload_1
     189: iconst_0
     190: aaload
     191: iconst_2
     192: caload
     193: aload_1
     194: iconst_1
     195: aaload
     196: iconst_1
     197: caload
     198: if_icmpne     242
     201: aload_1
     202: iconst_1
     203: aaload
     204: iconst_1
     205: caload
     206: aload_1
     207: iconst_2
     208: aaload
     209: iconst_0
     210: caload
     211: if_icmpne     242
     214: aload_1
     215: iconst_0
     216: aaload
     217: iconst_2
     218: caload
     219: getstatic     #23                 // Field player:C
     222: if_icmpne     228
     225: bipush        10
     227: ireturn
     228: aload_1
     229: iconst_0
     230: aaload
     231: iconst_2
     232: caload
     233: getstatic     #26                 // Field opponent:C
     236: if_icmpne     242
     239: bipush        -10
     241: ireturn
     242: iconst_0
     243: ireturn

  private final int minimax(char[][], int, boolean);
    Code:
       0: aload_0
       1: aload_1
       2: invokespecial #33                 // Method evaluate:([[C)I
       5: istore        4
       7: iload         4
       9: bipush        10
      11: if_icmpne     17
      14: iload         4
      16: ireturn
      17: iload         4
      19: bipush        -10
      21: if_icmpne     27
      24: iload         4
      26: ireturn
      27: aload_0
      28: aload_1
      29: invokespecial #35                 // Method isMovesLeft:([[C)Z
      32: ifne          37
      35: iconst_0
      36: ireturn
      37: iload_3
      38: ifeq          136
      41: sipush        -1000
      44: istore        5
      46: iconst_0
      47: istore        6
      49: iload         6
      51: iconst_3
      52: if_icmpge     131
      55: iconst_0
      56: istore        7
      58: iload         7
      60: iconst_3
      61: if_icmpge     125
      64: aload_1
      65: iload         6
      67: aaload
      68: iload         7
      70: caload
      71: bipush        95
      73: if_icmpne     119
      76: aload_1
      77: iload         6
      79: aaload
      80: iload         7
      82: getstatic     #23                 // Field player:C
      85: castore
      86: iload         5
      88: aload_0
      89: aload_1
      90: iload_2
      91: iconst_1
      92: iadd
      93: iload_3
      94: ifne          101
      97: iconst_1
      98: goto          102
     101: iconst_0
     102: invokespecial #37                 // Method minimax:([[CIZ)I
     105: invokestatic  #43                 // Method java/lang/Math.max:(II)I
     108: istore        5
     110: aload_1
     111: iload         6
     113: aaload
     114: iload         7
     116: bipush        95
     118: castore
     119: iinc          7, 1
     122: goto          58
     125: iinc          6, 1
     128: goto          49
     131: iload         5
     133: goto          228
     136: sipush        1000
     139: istore        5
     141: iconst_0
     142: istore        6
     144: iload         6
     146: iconst_3
     147: if_icmpge     226
     150: iconst_0
     151: istore        7
     153: iload         7
     155: iconst_3
     156: if_icmpge     220
     159: aload_1
     160: iload         6
     162: aaload
     163: iload         7
     165: caload
     166: bipush        95
     168: if_icmpne     214
     171: aload_1
     172: iload         6
     174: aaload
     175: iload         7
     177: getstatic     #26                 // Field opponent:C
     180: castore
     181: iload         5
     183: aload_0
     184: aload_1
     185: iload_2
     186: iconst_1
     187: iadd
     188: iload_3
     189: ifne          196
     192: iconst_1
     193: goto          197
     196: iconst_0
     197: invokespecial #37                 // Method minimax:([[CIZ)I
     200: invokestatic  #46                 // Method java/lang/Math.min:(II)I
     203: istore        5
     205: aload_1
     206: iload         6
     208: aaload
     209: iload         7
     211: bipush        95
     213: castore
     214: iinc          7, 1
     217: goto          153
     220: iinc          6, 1
     223: goto          144
     226: iload         5
     228: ireturn

  public static final com.jackson.tictactoe.utils.MinMaxAlgorithm$Move findBestMove(char[][]);
    Code:
       0: aload_0
       1: ldc           #57                 // String board
       3: invokestatic  #63                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: sipush        -1000
       9: istore_1
      10: new           #65                 // class com/jackson/tictactoe/utils/MinMaxAlgorithm$Move
      13: dup
      14: invokespecial #66                 // Method com/jackson/tictactoe/utils/MinMaxAlgorithm$Move."<init>":()V
      17: astore_2
      18: aload_2
      19: iconst_m1
      20: putfield      #68                 // Field com/jackson/tictactoe/utils/MinMaxAlgorithm$Move.row:I
      23: aload_2
      24: iconst_m1
      25: putfield      #70                 // Field com/jackson/tictactoe/utils/MinMaxAlgorithm$Move.col:I
      28: iconst_0
      29: istore_3
      30: iload_3
      31: iconst_3
      32: if_icmpge     115
      35: iconst_0
      36: istore        4
      38: iload         4
      40: iconst_3
      41: if_icmpge     109
      44: aload_0
      45: iload_3
      46: aaload
      47: iload         4
      49: caload
      50: bipush        95
      52: if_icmpne     103
      55: aload_0
      56: iload_3
      57: aaload
      58: iload         4
      60: getstatic     #23                 // Field player:C
      63: castore
      64: getstatic     #73                 // Field INSTANCE:Lcom/jackson/tictactoe/utils/MinMaxAlgorithm;
      67: aload_0
      68: iconst_0
      69: iconst_0
      70: invokespecial #37                 // Method minimax:([[CIZ)I
      73: istore        5
      75: aload_0
      76: iload_3
      77: aaload
      78: iload         4
      80: bipush        95
      82: castore
      83: iload         5
      85: iload_1
      86: if_icmple     103
      89: aload_2
      90: iload_3
      91: putfield      #68                 // Field com/jackson/tictactoe/utils/MinMaxAlgorithm$Move.row:I
      94: aload_2
      95: iload         4
      97: putfield      #70                 // Field com/jackson/tictactoe/utils/MinMaxAlgorithm$Move.col:I
     100: iload         5
     102: istore_1
     103: iinc          4, 1
     106: goto          38
     109: iinc          3, 1
     112: goto          30
     115: aload_2
     116: areturn

  static {};
    Code:
       0: new           #2                  // class com/jackson/tictactoe/utils/MinMaxAlgorithm
       3: dup
       4: invokespecial #79                 // Method "<init>":()V
       7: putstatic     #73                 // Field INSTANCE:Lcom/jackson/tictactoe/utils/MinMaxAlgorithm;
      10: bipush        120
      12: putstatic     #23                 // Field player:C
      15: bipush        111
      17: putstatic     #26                 // Field opponent:C
      20: return
}

Compiled from "MinMaxAlgorithm.kt"
public final class com.jackson.tictactoe.utils.MinMaxAlgorithm$Move {
  public int row;

  public int col;

  public com.jackson.tictactoe.utils.MinMaxAlgorithm$Move();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return
}


package com.itscoder.ljuns.practise.algorithm

/**
 * Created by ljuns at 2019/1/5.
 * I am just a developer.
 * 插入排序
 * 从第 2 个元素开始和前面的元素比较并排序
 * 例如：1, 3, 2
 * 1、第一次 for 循环：3 和 1 比较，不需要改变
 * 2.1、第二次 for 循环：2 和 3 比较，调换位置变成 1, 2, 3，此时 j == 1
 * 2.2、2 再和 1 比较，不需要改变，排序结束
 */

class InsertionSort {

    fun main(args: Array<String>) {
        val arr = intArrayOf(3, 1, 1, 6, 2, 4, 19)
        sort(arr)
    }

    private fun sort(arr: IntArray) {
        for (i in arr.indices) {
            var j = i
            // 判断 j > 0 有两层意义：1、第一个元素不用比较；2、后面的比较排序到第 1 个元素时停止
            while (j > 0 && arr[j] < arr[j - 1]) {
                val temp = arr[j]
                arr[j] = arr[j - 1]
                arr[j - 1] = temp
                j --
            }
        }

        for (i in arr) {
            println(i)
        }
    }
}

Compiled from "InsertionSort.kt"
public final class com.itscoder.ljuns.practise.algorithm.InsertionSort {
  public com.itscoder.ljuns.practise.algorithm.InsertionSort();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final void main(java.lang.String[]);
    Code:
       0: aload_1
       1: ldc           #15                 // String args
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: bipush        7
       8: newarray       int
      10: astore_3
      11: aload_3
      12: iconst_0
      13: iconst_3
      14: iastore
      15: aload_3
      16: iconst_1
      17: iconst_1
      18: iastore
      19: aload_3
      20: iconst_2
      21: iconst_1
      22: iastore
      23: aload_3
      24: iconst_3
      25: bipush        6
      27: iastore
      28: aload_3
      29: iconst_4
      30: iconst_2
      31: iastore
      32: aload_3
      33: iconst_5
      34: iconst_4
      35: iastore
      36: aload_3
      37: bipush        6
      39: bipush        19
      41: iastore
      42: aload_3
      43: astore_2
      44: aload_0
      45: aload_2
      46: invokespecial #25                 // Method sort:([I)V
      49: return

  private final void sort(int[]);
    Code:
       0: iconst_0
       1: istore_2
       2: aload_1
       3: arraylength
       4: istore_3
       5: iload_2
       6: iload_3
       7: if_icmpge     67
      10: iload_2
      11: istore        4
      13: iload         4
      15: ifle          61
      18: aload_1
      19: iload         4
      21: iaload
      22: aload_1
      23: iload         4
      25: iconst_1
      26: isub
      27: iaload
      28: if_icmpge     61
      31: aload_1
      32: iload         4
      34: iaload
      35: istore        5
      37: aload_1
      38: iload         4
      40: aload_1
      41: iload         4
      43: iconst_1
      44: isub
      45: iaload
      46: iastore
      47: aload_1
      48: iload         4
      50: iconst_1
      51: isub
      52: iload         5
      54: iastore
      55: iinc          4, -1
      58: goto          13
      61: iinc          2, 1
      64: goto          5
      67: iconst_0
      68: istore_2
      69: aload_1
      70: arraylength
      71: istore_3
      72: iload_2
      73: iload_3
      74: if_icmpge     96
      77: aload_1
      78: iload_2
      79: iaload
      80: istore        4
      82: getstatic     #34                 // Field java/lang/System.out:Ljava/io/PrintStream;
      85: iload         4
      87: invokevirtual #40                 // Method java/io/PrintStream.println:(I)V
      90: iinc          2, 1
      93: goto          72
      96: return
}


package com.itscoder.ljuns.practise.algorithm

/**
 * Created by ljuns at 2019/1/9.
 * I am just a developer.
 * 希尔排序
 */

fun main(args: Array<String>) {
    val arr = intArrayOf(3, 1, 1, 6, 2, 4, 19)
    shellSort(arr)

    arr.forEach { println(it) }
}

/**
 * 3, 1, 1, 6, 2, 4, 19
 * 1、gap = arr.size / 2，即分成 gap 组（偶数个元素是 gap 组，奇数个元素是 gap+1 组）
 * 2、每一组进行插入排序，插入排序就是后一个和前一个比较，后一个小就进入步骤 3
 * 3、交换位置，交换位置后还需重新和前面的比较，因为交换位置后有可能比前面的还小
 * 4、每次都是 gap /= 2
 * 5、重复 1～4
 */
fun shellSort(arr: IntArray) {

    var gap = arr.size / 2

    // for(int gap = arr.size / 2; gap > 0; gap /= 2)
    for (i in (arr.size / 2) downTo 0 step gap) {

        for (i in (gap until arr.size).withIndex()) {
            var j = i.value

            while (j >= gap && arr[j] < arr[j - gap]) {
                // 交换位置
                val temp = arr[j]
                arr[j] = arr[j - gap]
                arr[j - gap] = temp

                j -= gap
            }
        }

        // 每次都是 gap/2，叫做希尔增量
        gap /= 2
    }

    /*((arr.size / 2) downTo 0 step gap).forEach { item ->
        (gap until arr.size).forEachIndexed { key, index ->
            var j = index

            while (j >= gap && arr[j] < arr[j - gap]) {
                // 交换位置
                val temp = arr[j]
                arr[j] = arr[j - gap]
                arr[j - gap] = temp

                j -= gap
            }
        }

        gap /= 2
    }*/
}

Compiled from "ShellSort.kt"
public final class com.itscoder.ljuns.practise.algorithm.ShellSortKt {
  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: bipush        7
       8: newarray       int
      10: astore_2
      11: aload_2
      12: iconst_0
      13: iconst_3
      14: iastore
      15: aload_2
      16: iconst_1
      17: iconst_1
      18: iastore
      19: aload_2
      20: iconst_2
      21: iconst_1
      22: iastore
      23: aload_2
      24: iconst_3
      25: bipush        6
      27: iastore
      28: aload_2
      29: iconst_4
      30: iconst_2
      31: iastore
      32: aload_2
      33: iconst_5
      34: iconst_4
      35: iastore
      36: aload_2
      37: bipush        6
      39: bipush        19
      41: iastore
      42: aload_2
      43: astore_1
      44: aload_1
      45: invokestatic  #19                 // Method shellSort:([I)V
      48: aload_1
      49: astore_2
      50: iconst_0
      51: istore_3
      52: iconst_0
      53: istore        4
      55: aload_2
      56: arraylength
      57: istore        5
      59: iload         4
      61: iload         5
      63: if_icmpge     95
      66: aload_2
      67: iload         4
      69: iaload
      70: istore        6
      72: iload         6
      74: istore        7
      76: iconst_0
      77: istore        8
      79: getstatic     #25                 // Field java/lang/System.out:Ljava/io/PrintStream;
      82: iload         7
      84: invokevirtual #31                 // Method java/io/PrintStream.println:(I)V
      87: nop
      88: nop
      89: iinc          4, 1
      92: goto          59
      95: nop
      96: return

  public static final void shellSort(int[]);
    Code:
       0: aload_0
       1: ldc           #43                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: arraylength
       8: iconst_2
       9: idiv
      10: istore_1
      11: aload_0
      12: arraylength
      13: iconst_2
      14: idiv
      15: istore_2
      16: iload_1
      17: istore_3
      18: iload_3
      19: ifgt          54
      22: new           #45                 // class java/lang/IllegalArgumentException
      25: dup
      26: new           #47                 // class java/lang/StringBuilder
      29: dup
      30: invokespecial #51                 // Method java/lang/StringBuilder."<init>":()V
      33: ldc           #53                 // String Step must be positive, was:
      35: invokevirtual #57                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: iload_3
      39: invokevirtual #60                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      42: bipush        46
      44: invokevirtual #63                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      47: invokevirtual #67                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      50: invokespecial #70                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      53: athrow
      54: iload_3
      55: ineg
      56: istore_3
      57: iload_2
      58: istore        4
      60: iload_2
      61: iconst_0
      62: iload_3
      63: invokestatic  #76                 // Method kotlin/internal/ProgressionUtilKt.getProgressionLastElement:(III)I
      66: istore        5
      68: iload_3
      69: istore        6
      71: iload         5
      73: iload         4
      75: if_icmpgt     205
      78: iload_1
      79: aload_0
      80: arraylength
      81: invokestatic  #82                 // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
      84: checkcast     #84                 // class java/lang/Iterable
      87: invokestatic  #90                 // Method kotlin/collections/CollectionsKt.withIndex:(Ljava/lang/Iterable;)Ljava/lang/Iterable;
      90: invokeinterface #94,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      95: astore        7
      97: aload         7
      99: invokeinterface #100,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     104: ifeq          184
     107: aload         7
     109: invokeinterface #104,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     114: checkcast     #106                // class kotlin/collections/IndexedValue
     117: astore        8
     119: aload         8
     121: invokevirtual #109                // Method kotlin/collections/IndexedValue.getValue:()Ljava/lang/Object;
     124: checkcast     #111                // class java/lang/Number
     127: invokevirtual #115                // Method java/lang/Number.intValue:()I
     130: istore        9
     132: iload         9
     134: iload_1
     135: if_icmplt     97
     138: aload_0
     139: iload         9
     141: iaload
     142: aload_0
     143: iload         9
     145: iload_1
     146: isub
     147: iaload
     148: if_icmpge     97
     151: aload_0
     152: iload         9
     154: iaload
     155: istore        10
     157: aload_0
     158: iload         9
     160: aload_0
     161: iload         9
     163: iload_1
     164: isub
     165: iaload
     166: iastore
     167: aload_0
     168: iload         9
     170: iload_1
     171: isub
     172: iload         10
     174: iastore
     175: iload         9
     177: iload_1
     178: isub
     179: istore        9
     181: goto          132
     184: iload_1
     185: iconst_2
     186: idiv
     187: istore_1
     188: iload         4
     190: iload         5
     192: if_icmpeq     205
     195: iload         4
     197: iload         6
     199: iadd
     200: istore        4
     202: goto          78
     205: return
}


package com.itscoder.ljuns.practise.algorithm

/**
 * Created by ljuns at 2019/1/8.
 * I am just a developer.
 * 归并排序
 * 1、先将数组中间分割，直到无法分割
 *                                                 3, 1, 1, 6, 2, 4, 19
 *                                                 3, 1, 1, 6
 *                                                 3, 1
 *                                                 3  1
 * 2、对最小的部分开始排序                            1  3     1, 6
 *                                                 1  3     1  6
 *                                                 1  1  3  6       2, 4, 19
 *                                                 1  1  3  6       2, 4    19
 *                                                 1  1  3  6       2  4
 *                                                 1  1  2  3  4  6     19
 *                                                 1  1  2  3  4  6 19
 * 3、合并上层的分割
 */

fun main(args: Array<String>) {
    val arr = intArrayOf(3, 1, 1, 6, 2, 4, 19)
    val temp = intArrayOf(0, 0, 0, 0, 0, 0, 0)
    mergeSort(arr, 0, arr.size - 1, temp)

    arr.forEach { println(it) }
}

fun mergeSort(arr: IntArray, left: Int, right: Int, temp: IntArray) {
    if (left < right) {
        val mid = (left + right) / 2
        // 分割左边
        mergeSort(arr, left, mid, temp)
        // 分割右边
        mergeSort(arr, mid + 1, right, temp)
        // 合并排序
        merge(arr, left, mid, right, temp)
    }
}

fun merge(arr: IntArray, left: Int, mid: Int, right: Int, temp: IntArray) {
    var l = left
    // 从右边的第一个开始
    var r = mid + 1

    var i = 0
    while (l <= mid && r <= right) {
        if (arr[l] <= arr[r]) {
            // 将左边的元素给临时数组，并把左边指向下一个
            temp[i++] = arr[l++]
        } else {
            // 将右边的元素给临时数组，并把右边指向下一个
            temp[i++] = arr[r++]
        }
    }

    // 将左边剩余的元素放到临时数组
    while (l <= mid) {
        temp[i++] = arr[l++]
    }

    // 将右边剩余的元素放到临时数组
    while (r <= right) {
        temp[i++] = arr[r++]
    }

    // 此时的临时数组已经是个有序数组了
    var left = left
    i = 0
    // 将临时数组的元素复制到原数组，原数组的起始位置是合并前左半部分的第一个位置，即 left
    while (left <= right) {
        arr[left++] = temp[i++]
    }
}

Compiled from "MergeSort.kt"
public final class com.itscoder.ljuns.practise.algorithm.MergeSortKt {
  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: bipush        7
       8: newarray       int
      10: astore_2
      11: aload_2
      12: iconst_0
      13: iconst_3
      14: iastore
      15: aload_2
      16: iconst_1
      17: iconst_1
      18: iastore
      19: aload_2
      20: iconst_2
      21: iconst_1
      22: iastore
      23: aload_2
      24: iconst_3
      25: bipush        6
      27: iastore
      28: aload_2
      29: iconst_4
      30: iconst_2
      31: iastore
      32: aload_2
      33: iconst_5
      34: iconst_4
      35: iastore
      36: aload_2
      37: bipush        6
      39: bipush        19
      41: iastore
      42: aload_2
      43: astore_1
      44: bipush        7
      46: newarray       int
      48: astore_3
      49: aload_3
      50: iconst_0
      51: iconst_0
      52: iastore
      53: aload_3
      54: iconst_1
      55: iconst_0
      56: iastore
      57: aload_3
      58: iconst_2
      59: iconst_0
      60: iastore
      61: aload_3
      62: iconst_3
      63: iconst_0
      64: iastore
      65: aload_3
      66: iconst_4
      67: iconst_0
      68: iastore
      69: aload_3
      70: iconst_5
      71: iconst_0
      72: iastore
      73: aload_3
      74: bipush        6
      76: iconst_0
      77: iastore
      78: aload_3
      79: astore_2
      80: aload_1
      81: iconst_0
      82: aload_1
      83: arraylength
      84: iconst_1
      85: isub
      86: aload_2
      87: invokestatic  #19                 // Method mergeSort:([III[I)V
      90: aload_1
      91: astore_3
      92: iconst_0
      93: istore        4
      95: iconst_0
      96: istore        5
      98: aload_3
      99: arraylength
     100: istore        6
     102: iload         5
     104: iload         6
     106: if_icmpge     138
     109: aload_3
     110: iload         5
     112: iaload
     113: istore        7
     115: iload         7
     117: istore        8
     119: iconst_0
     120: istore        9
     122: getstatic     #25                 // Field java/lang/System.out:Ljava/io/PrintStream;
     125: iload         8
     127: invokevirtual #31                 // Method java/io/PrintStream.println:(I)V
     130: nop
     131: nop
     132: iinc          5, 1
     135: goto          102
     138: nop
     139: return

  public static final void mergeSort(int[], int, int, int[]);
    Code:
       0: aload_0
       1: ldc           #44                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_3
       7: ldc           #45                 // String temp
       9: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iload_1
      13: iload_2
      14: if_icmpge     51
      17: iload_1
      18: iload_2
      19: iadd
      20: iconst_2
      21: idiv
      22: istore        4
      24: aload_0
      25: iload_1
      26: iload         4
      28: aload_3
      29: invokestatic  #19                 // Method mergeSort:([III[I)V
      32: aload_0
      33: iload         4
      35: iconst_1
      36: iadd
      37: iload_2
      38: aload_3
      39: invokestatic  #19                 // Method mergeSort:([III[I)V
      42: aload_0
      43: iload_1
      44: iload         4
      46: iload_2
      47: aload_3
      48: invokestatic  #49                 // Method merge:([IIII[I)V
      51: return

  public static final void merge(int[], int, int, int, int[]);
    Code:
       0: aload_0
       1: ldc           #44                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload         4
       8: ldc           #45                 // String temp
      10: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      13: iload_1
      14: istore        5
      16: iload_2
      17: iconst_1
      18: iadd
      19: istore        6
      21: iconst_0
      22: istore        7
      24: iload         5
      26: iload_2
      27: if_icmpgt     83
      30: iload         6
      32: iload_3
      33: if_icmpgt     83
      36: aload_0
      37: iload         5
      39: iaload
      40: aload_0
      41: iload         6
      43: iaload
      44: if_icmpgt     65
      47: aload         4
      49: iload         7
      51: iinc          7, 1
      54: aload_0
      55: iload         5
      57: iinc          5, 1
      60: iaload
      61: iastore
      62: goto          24
      65: aload         4
      67: iload         7
      69: iinc          7, 1
      72: aload_0
      73: iload         6
      75: iinc          6, 1
      78: iaload
      79: iastore
      80: goto          24
      83: iload         5
      85: iload_2
      86: if_icmpgt     107
      89: aload         4
      91: iload         7
      93: iinc          7, 1
      96: aload_0
      97: iload         5
      99: iinc          5, 1
     102: iaload
     103: iastore
     104: goto          83
     107: iload         6
     109: iload_3
     110: if_icmpgt     131
     113: aload         4
     115: iload         7
     117: iinc          7, 1
     120: aload_0
     121: iload         6
     123: iinc          6, 1
     126: iaload
     127: iastore
     128: goto          107
     131: iload_1
     132: istore        8
     134: iconst_0
     135: istore        7
     137: iload         8
     139: iload_3
     140: if_icmpgt     161
     143: aload_0
     144: iload         8
     146: iinc          8, 1
     149: aload         4
     151: iload         7
     153: iinc          7, 1
     156: iaload
     157: iastore
     158: goto          137
     161: return
}


package com.itscoder.ljuns.practise.algorithm

import java.util.Collections.swap

/**
 * Created by ljuns at 2019/1/7.
 * I am just a developer.
 * 堆排序
 * 大顶堆：根节点 >= 左子节点 && 根节点 >= 右子节点
 * 小顶堆：根节点 <= 左子节点 && 根节点 <= 右子节点
 * 1、升序构建大顶堆，降序构建小顶堆
 * 2、交换根节点和最后一个子节点，此时的最后一个子节点不再参与排序
 * 3、重复 1、2
 */

fun main(args: Array<String>) {
    val arr = intArrayOf(3, 1, 1, 6, 2, 4, 19)
//    val arr = intArrayOf(9,8,7,6,5,4,3,2,1)
    headSort(arr)

    for (i in arr) {
        println(i)
    }
}

fun headSort(arr: IntArray) {

    /**
     * 构造堆
     */
    // for(int i = arr.size/2 -1; i >= 0; i --)
    // start 是最后一个子节点不为空的节点
    val start = arr.size / 2 - 1
    for ((key, value) in (start downTo 0).withIndex()) {
        // println("key: $value, value: ${arr[value]}")
        headAdjust(arr, value, arr.size)
    }

    /**
     * 交换位置，再次调整为堆
     */
    for ((index, value) in (arr.size - 1 downTo 1).withIndex()) {
        // 交换根节点后最后一个子节点
        swap(arr, 0, value)
        // 重新调整为大顶堆
        // 为什么从 0 开始？因为交换了根节点和最后一个子节点，其他节点都不变，变得只是根节点，所以只需要看根节点
        headAdjust(arr, 0, value)
    }
}

/**
 * 构建堆
 */
fun headAdjust(arr: IntArray, i: Int, len: Int) {
    var temp = arr[i]
    var i = i

    // for (int j = 2 * i + 1; j < len; j = j * 2 + 1)
    // 2 * i + 1 表示左子节点，2 * i + 2 表示右子节点
    var start = 2 * i + 1
    while (start < len) {

        // 如果右子节点比左子节点大，用右子节点来比较
        if (start + 1 < len && arr[start] < arr[start + 1]) {
            start++
        }

        // 如果子节点比父节点大，调换位置
        if (arr[start] > temp) {
            arr[i] = arr[start]
            i = start
        } else {
            //父节点比子节点都大，不需要调整
            break
        }

        // start * 2 + 1：因为有可能子节点又不满足大顶堆了，需要再次调整
        start = start * 2 + 1
        arr[i] = temp
    }
}

/**
 * 交换根节点和最后一个子节点
 */
fun swap(arr: IntArray, origin: Int, target: Int) {
    val temp = arr[origin]
    arr[origin] = arr[target]
    arr[target] = temp
}

Compiled from "HeadSort.kt"
public final class com.itscoder.ljuns.practise.algorithm.HeadSortKt {
  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: bipush        7
       8: newarray       int
      10: astore_2
      11: aload_2
      12: iconst_0
      13: iconst_3
      14: iastore
      15: aload_2
      16: iconst_1
      17: iconst_1
      18: iastore
      19: aload_2
      20: iconst_2
      21: iconst_1
      22: iastore
      23: aload_2
      24: iconst_3
      25: bipush        6
      27: iastore
      28: aload_2
      29: iconst_4
      30: iconst_2
      31: iastore
      32: aload_2
      33: iconst_5
      34: iconst_4
      35: iastore
      36: aload_2
      37: bipush        6
      39: bipush        19
      41: iastore
      42: aload_2
      43: astore_1
      44: aload_1
      45: invokestatic  #19                 // Method headSort:([I)V
      48: iconst_0
      49: istore_2
      50: aload_1
      51: arraylength
      52: istore_3
      53: iload_2
      54: iload_3
      55: if_icmpge     77
      58: aload_1
      59: iload_2
      60: iaload
      61: istore        4
      63: getstatic     #25                 // Field java/lang/System.out:Ljava/io/PrintStream;
      66: iload         4
      68: invokevirtual #31                 // Method java/io/PrintStream.println:(I)V
      71: iinc          2, 1
      74: goto          53
      77: return

  public static final void headSort(int[]);
    Code:
       0: aload_0
       1: ldc           #38                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: arraylength
       8: iconst_2
       9: idiv
      10: iconst_1
      11: isub
      12: istore_1
      13: iload_1
      14: istore_2
      15: iconst_0
      16: istore_3
      17: iconst_m1
      18: iload_2
      19: if_icmpge     46
      22: iload_3
      23: istore        4
      25: iload_3
      26: iconst_1
      27: iadd
      28: istore_3
      29: iload_2
      30: istore        5
      32: aload_0
      33: iload         5
      35: aload_0
      36: arraylength
      37: invokestatic  #42                 // Method headAdjust:([III)V
      40: iinc          2, -1
      43: goto          17
      46: aload_0
      47: arraylength
      48: iconst_1
      49: isub
      50: istore_2
      51: iconst_0
      52: istore_3
      53: iconst_0
      54: iload_2
      55: if_icmpge     88
      58: iload_3
      59: istore        4
      61: iload_3
      62: iconst_1
      63: iadd
      64: istore_3
      65: iload_2
      66: istore        5
      68: aload_0
      69: iconst_0
      70: iload         5
      72: invokestatic  #45                 // Method swap:([III)V
      75: aload_0
      76: iconst_0
      77: iload         5
      79: invokestatic  #42                 // Method headAdjust:([III)V
      82: iinc          2, -1
      85: goto          53
      88: return

  public static final void headAdjust(int[], int, int);
    Code:
       0: aload_0
       1: ldc           #38                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iload_1
       8: iaload
       9: istore_3
      10: iload_1
      11: istore        4
      13: iconst_2
      14: iload         4
      16: imul
      17: iconst_1
      18: iadd
      19: istore        5
      21: iload         5
      23: iload_2
      24: if_icmpge     93
      27: iload         5
      29: iconst_1
      30: iadd
      31: iload_2
      32: if_icmpge     51
      35: aload_0
      36: iload         5
      38: iaload
      39: aload_0
      40: iload         5
      42: iconst_1
      43: iadd
      44: iaload
      45: if_icmpge     51
      48: iinc          5, 1
      51: aload_0
      52: iload         5
      54: iaload
      55: iload_3
      56: if_icmple     74
      59: aload_0
      60: iload         4
      62: aload_0
      63: iload         5
      65: iaload
      66: iastore
      67: iload         5
      69: istore        4
      71: goto          77
      74: goto          93
      77: iload         5
      79: iconst_2
      80: imul
      81: iconst_1
      82: iadd
      83: istore        5
      85: aload_0
      86: iload         4
      88: iload_3
      89: iastore
      90: goto          21
      93: return

  public static final void swap(int[], int, int);
    Code:
       0: aload_0
       1: ldc           #38                 // String arr
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iload_1
       8: iaload
       9: istore_3
      10: aload_0
      11: iload_1
      12: aload_0
      13: iload_2
      14: iaload
      15: iastore
      16: aload_0
      17: iload_2
      18: iload_3
      19: iastore
      20: return
}


package com.itscoder.ljuns.practise.algorithm

/**
 * Created by ljuns at 2019/1/5.
 * I am just a developer.
 * 快速排序
 * 例如：3, 1, 1, 6, 2, 4, 19
 * 1、定义 left 为最左边，right 为最右边；
 * 2、选定 left 位置的元素为 temp；
 * 3、用 temp 从最右边开始比较，大于等于 temp 就 right--，否则 right 位置的元素替换掉 left 的元素，并且 left++；
 * 4、用 temp 从 left 开始比较，小于等于 temp 就 left++，否则 left 位置的元素替换掉 right 的元素，并且 right--；
 * 5、此时以 temp 为中心分为两部分，左边的都比 temp 小，右边的都比 temp 大。
 * 左边：left 仍为最左边，right 为 temp，右边：left 为 temp+1，right 为最右边；重复2～5，直到 left >= temp 的位置
 */

//class QuickSort {

    fun main(args: Array<String>) {
        val arr = intArrayOf(3, 1, 1, 6, 2, 4, 19)
        quickSort(arr, 0, arr.size - 1)

        for (i in arr) {
            println(i)
        }
    }

    private fun quickSort(arr: IntArray, left: Int, right: Int) {
        if (left >= right || arr.size <= 1) return

//        val mid = partition(arr, left, right)
        val mid = partition2(arr, left, right)
        quickSort(arr, left, mid)
        quickSort(arr, mid + 1, right)
    }

    private fun partition2(arr: IntArray, left: Int, right: Int) : Int {
        var l = left + 1
        var r = right
        val temp = arr[left]

        while (l <= r) {
            if (temp < arr[l] && temp > arr[r]) {
                val t = arr[l]
                arr[l] = arr[r]
                arr[r] = t
                l++
                r--
            }

            if (temp >= arr[l]) l++
            if (temp <= arr[r]) r--
        }
        arr[left] = arr[r]
        arr[r] = temp

        return r
    }

    private fun partition(arr: IntArray, left: Int, right: Int) : Int {
        var left = left
        var right = right
        val temp = arr[left]

        while (left < right) {
            // 比较右边
            while (temp <= arr[right] && left < right) {
                -- right
            }

            // 右边的比 temp 小，需要把 right 放在 left 的位置，并且 left 从下一个位置开始
            if (left < right) {
                arr[left] = arr[right]
                left ++
            }

            // 比较左边
            while (temp >= arr[left] && left < right) {
                ++ left
            }

            // 左边的比 temp 大，需要把 left 放在 right 的位置，并且 right 从前一个位置开始
            if (left < right) {
                arr[right] = arr[left]
                right --
            }
        }

        // 此时 left == right
        arr[left] = temp
        return left
    }
//}

Compiled from "QuickSort.kt"
public final class com.itscoder.ljuns.practise.algorithm.QuickSortKt {
  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: bipush        7
       8: newarray       int
      10: astore_2
      11: aload_2
      12: iconst_0
      13: iconst_3
      14: iastore
      15: aload_2
      16: iconst_1
      17: iconst_1
      18: iastore
      19: aload_2
      20: iconst_2
      21: iconst_1
      22: iastore
      23: aload_2
      24: iconst_3
      25: bipush        6
      27: iastore
      28: aload_2
      29: iconst_4
      30: iconst_2
      31: iastore
      32: aload_2
      33: iconst_5
      34: iconst_4
      35: iastore
      36: aload_2
      37: bipush        6
      39: bipush        19
      41: iastore
      42: aload_2
      43: astore_1
      44: aload_1
      45: iconst_0
      46: aload_1
      47: arraylength
      48: iconst_1
      49: isub
      50: invokestatic  #19                 // Method quickSort:([III)V
      53: iconst_0
      54: istore_2
      55: aload_1
      56: arraylength
      57: istore_3
      58: iload_2
      59: iload_3
      60: if_icmpge     82
      63: aload_1
      64: iload_2
      65: iaload
      66: istore        4
      68: getstatic     #25                 // Field java/lang/System.out:Ljava/io/PrintStream;
      71: iload         4
      73: invokevirtual #31                 // Method java/io/PrintStream.println:(I)V
      76: iinc          2, 1
      79: goto          58
      82: return

  private static final void quickSort(int[], int, int);
    Code:
       0: iload_1
       1: iload_2
       2: if_icmpge     11
       5: aload_0
       6: arraylength
       7: iconst_1
       8: if_icmpgt     12
      11: return
      12: aload_0
      13: iload_1
      14: iload_2
      15: invokestatic  #41                 // Method partition2:([III)I
      18: istore_3
      19: aload_0
      20: iload_1
      21: iload_3
      22: invokestatic  #19                 // Method quickSort:([III)V
      25: aload_0
      26: iload_3
      27: iconst_1
      28: iadd
      29: iload_2
      30: invokestatic  #19                 // Method quickSort:([III)V
      33: return

  private static final int partition2(int[], int, int);
    Code:
       0: iload_1
       1: iconst_1
       2: iadd
       3: istore_3
       4: iload_2
       5: istore        4
       7: aload_0
       8: iload_1
       9: iaload
      10: istore        5
      12: iload_3
      13: iload         4
      15: if_icmpgt     85
      18: iload         5
      20: aload_0
      21: iload_3
      22: iaload
      23: if_icmpge     59
      26: iload         5
      28: aload_0
      29: iload         4
      31: iaload
      32: if_icmple     59
      35: aload_0
      36: iload_3
      37: iaload
      38: istore        6
      40: aload_0
      41: iload_3
      42: aload_0
      43: iload         4
      45: iaload
      46: iastore
      47: aload_0
      48: iload         4
      50: iload         6
      52: iastore
      53: iinc          3, 1
      56: iinc          4, -1
      59: iload         5
      61: aload_0
      62: iload_3
      63: iaload
      64: if_icmplt     70
      67: iinc          3, 1
      70: iload         5
      72: aload_0
      73: iload         4
      75: iaload
      76: if_icmpgt     12
      79: iinc          4, -1
      82: goto          12
      85: aload_0
      86: iload_1
      87: aload_0
      88: iload         4
      90: iaload
      91: iastore
      92: aload_0
      93: iload         4
      95: iload         5
      97: iastore
      98: iload         4
     100: ireturn

  private static final int partition(int[], int, int);
    Code:
       0: iload_1
       1: istore_3
       2: iload_2
       3: istore        4
       5: aload_0
       6: iload_3
       7: iaload
       8: istore        5
      10: iload_3
      11: iload         4
      13: if_icmpge     92
      16: iload         5
      18: aload_0
      19: iload         4
      21: iaload
      22: if_icmpgt     37
      25: iload_3
      26: iload         4
      28: if_icmpge     37
      31: iinc          4, -1
      34: goto          16
      37: iload_3
      38: iload         4
      40: if_icmpge     53
      43: aload_0
      44: iload_3
      45: aload_0
      46: iload         4
      48: iaload
      49: iastore
      50: iinc          3, 1
      53: iload         5
      55: aload_0
      56: iload_3
      57: iaload
      58: if_icmplt     73
      61: iload_3
      62: iload         4
      64: if_icmpge     73
      67: iinc          3, 1
      70: goto          53
      73: iload_3
      74: iload         4
      76: if_icmpge     10
      79: aload_0
      80: iload         4
      82: aload_0
      83: iload_3
      84: iaload
      85: iastore
      86: iinc          4, -1
      89: goto          10
      92: aload_0
      93: iload_3
      94: iload         5
      96: iastore
      97: iload_3
      98: ireturn
}