/**
 * # Largest Palindromic Number
 * Problem:
 * https://leetcode.com/problems/largest-palindromic-number/
 */
class LargestPalindromicNumber {
    fun largestPalindromic(num: String): String {
        val digits = intArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        for (c in num) {
            val digit = c.digitToInt()
            digits[digit] += 1
        }

        val available = digits.mapIndexed { digit, count ->
            digit to count
        }.filter { (_, count) ->
            count > 0
        }.sortedWith { (digit1, count1), (digit2, count2) ->
            /**
             * Returns zero if the arguments are equal,
             * a negative number if the first argument is less than the second,
             * or a positive number if the first argument is greater than the second.
             */
            val oneRank = (if (count1 > 1) 100 else 0) + digit1
            val twoRank = (if (count2 > 1) 100 else 0) + digit2
            twoRank - oneRank// sort descending
        }

        val mirror = mirror(available)
        val palindrome = palindrome(mirror)

        // Filter leading 0's
        return if (palindrome.first() == '0') {
            palindrome.replace("0", "").takeIf { it.isNotEmpty() } ?: "0"
        } else palindrome
    }

    private fun palindrome(mirror: Pair<String, String?>): String {
        val (str, left) = mirror
        return if (left != null)
            str + left + str.reversed()
        else str + str.reversed()
    }

    private fun mirror(available: List<Pair<Int, Int>>): Pair<String, String?> {
        fun biggestLeftover(currentDigit: Int, secondLeft: String?): Int {
            val secondLeftSafe = secondLeft?.toInt() ?: 0
            val next = available.getOrNull(1)?.first
                ?: return maxOf(currentDigit, secondLeftSafe)
            return if (next > currentDigit) {
                maxOf(next, secondLeftSafe)
            } else maxOf(currentDigit, secondLeftSafe)
        }

        if (available.isEmpty()) return "" to null
        val (digit, count) = available.first()
        return if (count.isEven()) {
            val first = digit.toString().repeat(count / 2)
            val (secondStr, secondLeft) = mirror(available.drop(1))
            first + secondStr to secondLeft
        } else {
            if (count > 1) {
                // not even; count >= 3
                val first = digit.toString().repeat((count - 1) / 2)
                val (secondStr, secondLeft) = mirror(available.drop(1))
                first + secondStr to biggestLeftover(
                    currentDigit = digit,
                    secondLeft = secondLeft
                ).toString()
            } else {
                // count = 1
                "" to digit.toString()
            }
        }
    }

    private fun Int.isEven(): Boolean = this % 2 == 0
}

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

  public final java.lang.String largestPalindromic(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String num
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: bipush        11
       8: newarray       int
      10: astore_3
      11: aload_3
      12: iconst_0
      13: iconst_0
      14: iastore
      15: aload_3
      16: iconst_1
      17: iconst_0
      18: iastore
      19: aload_3
      20: iconst_2
      21: iconst_0
      22: iastore
      23: aload_3
      24: iconst_3
      25: iconst_0
      26: iastore
      27: aload_3
      28: iconst_4
      29: iconst_0
      30: iastore
      31: aload_3
      32: iconst_5
      33: iconst_0
      34: iastore
      35: aload_3
      36: bipush        6
      38: iconst_0
      39: iastore
      40: aload_3
      41: bipush        7
      43: iconst_0
      44: iastore
      45: aload_3
      46: bipush        8
      48: iconst_0
      49: iastore
      50: aload_3
      51: bipush        9
      53: iconst_0
      54: iastore
      55: aload_3
      56: bipush        10
      58: iconst_0
      59: iastore
      60: aload_3
      61: astore_2
      62: iconst_0
      63: istore_3
      64: aload_1
      65: invokevirtual #27                 // Method java/lang/String.length:()I
      68: istore        4
      70: iload_3
      71: iload         4
      73: if_icmpge     106
      76: aload_1
      77: iload_3
      78: invokevirtual #31                 // Method java/lang/String.charAt:(I)C
      81: istore        5
      83: iload         5
      85: invokestatic  #37                 // Method kotlin/text/CharsKt.digitToInt:(C)I
      88: istore        6
      90: aload_2
      91: iload         6
      93: aload_2
      94: iload         6
      96: iaload
      97: iconst_1
      98: iadd
      99: iastore
     100: iinc          3, 1
     103: goto          70
     106: aload_2
     107: astore        4
     109: iconst_0
     110: istore        5
     112: aload         4
     114: astore        6
     116: new           #39                 // class java/util/ArrayList
     119: dup
     120: aload         4
     122: arraylength
     123: invokespecial #42                 // Method java/util/ArrayList."<init>":(I)V
     126: checkcast     #44                 // class java/util/Collection
     129: astore        7
     131: iconst_0
     132: istore        8
     134: iconst_0
     135: istore        9
     137: iconst_0
     138: istore        10
     140: aload         6
     142: arraylength
     143: istore        11
     145: iload         10
     147: iload         11
     149: if_icmpge     205
     152: aload         6
     154: iload         10
     156: iaload
     157: istore        12
     159: aload         7
     161: iload         9
     163: iinc          9, 1
     166: iload         12
     168: istore        13
     170: istore        14
     172: astore        16
     174: iconst_0
     175: istore        15
     177: iload         14
     179: invokestatic  #50                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     182: iload         13
     184: invokestatic  #50                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     187: invokestatic  #56                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     190: aload         16
     192: swap
     193: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     198: pop
     199: iinc          10, 1
     202: goto          145
     205: aload         7
     207: checkcast     #62                 // class java/util/List
     210: nop
     211: checkcast     #64                 // class java/lang/Iterable
     214: astore        4
     216: nop
     217: iconst_0
     218: istore        5
     220: aload         4
     222: astore        6
     224: new           #39                 // class java/util/ArrayList
     227: dup
     228: invokespecial #65                 // Method java/util/ArrayList."<init>":()V
     231: checkcast     #44                 // class java/util/Collection
     234: astore        7
     236: iconst_0
     237: istore        8
     239: aload         6
     241: invokeinterface #69,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     246: astore        9
     248: aload         9
     250: invokeinterface #75,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     255: ifeq          316
     258: aload         9
     260: invokeinterface #79,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     265: astore        10
     267: aload         10
     269: checkcast     #81                 // class kotlin/Pair
     272: astore        11
     274: iconst_0
     275: istore        12
     277: aload         11
     279: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
     282: checkcast     #86                 // class java/lang/Number
     285: invokevirtual #89                 // Method java/lang/Number.intValue:()I
     288: istore        13
     290: iload         13
     292: ifle          299
     295: iconst_1
     296: goto          300
     299: iconst_0
     300: ifeq          248
     303: aload         7
     305: aload         10
     307: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     312: pop
     313: goto          248
     316: aload         7
     318: checkcast     #62                 // class java/util/List
     321: nop
     322: checkcast     #64                 // class java/lang/Iterable
     325: invokedynamic #109,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function2;
     330: invokedynamic #120,  0            // InvokeDynamic #1:compare:(Lkotlin/jvm/functions/Function2;)Ljava/util/Comparator;
     335: invokestatic  #126                // Method kotlin/collections/CollectionsKt.sortedWith:(Ljava/lang/Iterable;Ljava/util/Comparator;)Ljava/util/List;
     338: astore_3
     339: aload_0
     340: aload_3
     341: invokespecial #130                // Method mirror:(Ljava/util/List;)Lkotlin/Pair;
     344: astore        4
     346: aload_0
     347: aload         4
     349: invokespecial #134                // Method palindrome:(Lkotlin/Pair;)Ljava/lang/String;
     352: astore        5
     354: aload         5
     356: checkcast     #136                // class java/lang/CharSequence
     359: invokestatic  #142                // Method kotlin/text/StringsKt.first:(Ljava/lang/CharSequence;)C
     362: bipush        48
     364: if_icmpne     426
     367: aload         5
     369: ldc           #144                // String 0
     371: ldc           #146                // String
     373: iconst_0
     374: iconst_4
     375: aconst_null
     376: invokestatic  #150                // Method kotlin/text/StringsKt.replace$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/String;
     379: astore        7
     381: aload         7
     383: astore        8
     385: iconst_0
     386: istore        9
     388: aload         8
     390: checkcast     #136                // class java/lang/CharSequence
     393: invokeinterface #151,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     398: ifle          405
     401: iconst_1
     402: goto          406
     405: iconst_0
     406: nop
     407: ifeq          415
     410: aload         7
     412: goto          416
     415: aconst_null
     416: dup
     417: ifnonnull     428
     420: pop
     421: ldc           #144                // String 0
     423: goto          428
     426: aload         5
     428: areturn

  private final java.lang.String palindrome(kotlin.Pair<java.lang.String, java.lang.String>);
    Code:
       0: aload_1
       1: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
       4: checkcast     #23                 // class java/lang/String
       7: astore_2
       8: aload_1
       9: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
      12: checkcast     #23                 // class java/lang/String
      15: astore_3
      16: aload_3
      17: ifnull        54
      20: new           #188                // class java/lang/StringBuilder
      23: dup
      24: invokespecial #189                // Method java/lang/StringBuilder."<init>":()V
      27: aload_2
      28: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: aload_3
      32: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      35: aload_2
      36: checkcast     #136                // class java/lang/CharSequence
      39: invokestatic  #197                // Method kotlin/text/StringsKt.reversed:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      42: invokevirtual #201                // Method java/lang/Object.toString:()Ljava/lang/String;
      45: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      48: invokevirtual #202                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      51: goto          81
      54: new           #188                // class java/lang/StringBuilder
      57: dup
      58: invokespecial #189                // Method java/lang/StringBuilder."<init>":()V
      61: aload_2
      62: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      65: aload_2
      66: checkcast     #136                // class java/lang/CharSequence
      69: invokestatic  #197                // Method kotlin/text/StringsKt.reversed:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      72: invokevirtual #201                // Method java/lang/Object.toString:()Ljava/lang/String;
      75: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      78: invokevirtual #202                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      81: areturn

  private final kotlin.Pair<java.lang.String, java.lang.String> mirror(java.util.List<kotlin.Pair<java.lang.Integer, java.lang.Integer>>);
    Code:
       0: aload_1
       1: invokeinterface #208,  1          // InterfaceMethod java/util/List.isEmpty:()Z
       6: ifeq          16
       9: ldc           #146                // String
      11: aconst_null
      12: invokestatic  #56                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      15: areturn
      16: aload_1
      17: invokestatic  #211                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      20: checkcast     #81                 // class kotlin/Pair
      23: astore_2
      24: aload_2
      25: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      28: checkcast     #86                 // class java/lang/Number
      31: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      34: istore_3
      35: aload_2
      36: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
      39: checkcast     #86                 // class java/lang/Number
      42: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      45: istore        4
      47: aload_0
      48: iload         4
      50: invokespecial #215                // Method isEven:(I)Z
      53: ifeq          134
      56: iload_3
      57: invokestatic  #218                // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      60: checkcast     #136                // class java/lang/CharSequence
      63: iload         4
      65: iconst_2
      66: idiv
      67: invokestatic  #222                // Method kotlin/text/StringsKt.repeat:(Ljava/lang/CharSequence;I)Ljava/lang/String;
      70: astore        5
      72: aload_0
      73: aload_1
      74: checkcast     #64                 // class java/lang/Iterable
      77: iconst_1
      78: invokestatic  #226                // Method kotlin/collections/CollectionsKt.drop:(Ljava/lang/Iterable;I)Ljava/util/List;
      81: invokespecial #130                // Method mirror:(Ljava/util/List;)Lkotlin/Pair;
      84: astore        6
      86: aload         6
      88: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      91: checkcast     #23                 // class java/lang/String
      94: astore        7
      96: aload         6
      98: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
     101: checkcast     #23                 // class java/lang/String
     104: astore        8
     106: new           #188                // class java/lang/StringBuilder
     109: dup
     110: invokespecial #189                // Method java/lang/StringBuilder."<init>":()V
     113: aload         5
     115: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     118: aload         7
     120: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     123: invokevirtual #202                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     126: aload         8
     128: invokestatic  #56                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     131: goto          237
     134: iload         4
     136: iconst_1
     137: if_icmple     228
     140: iload_3
     141: invokestatic  #218                // Method java/lang/String.valueOf:(I)Ljava/lang/String;
     144: checkcast     #136                // class java/lang/CharSequence
     147: iload         4
     149: iconst_1
     150: isub
     151: iconst_2
     152: idiv
     153: invokestatic  #222                // Method kotlin/text/StringsKt.repeat:(Ljava/lang/CharSequence;I)Ljava/lang/String;
     156: astore        5
     158: aload_0
     159: aload_1
     160: checkcast     #64                 // class java/lang/Iterable
     163: iconst_1
     164: invokestatic  #226                // Method kotlin/collections/CollectionsKt.drop:(Ljava/lang/Iterable;I)Ljava/util/List;
     167: invokespecial #130                // Method mirror:(Ljava/util/List;)Lkotlin/Pair;
     170: astore        6
     172: aload         6
     174: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     177: checkcast     #23                 // class java/lang/String
     180: astore        7
     182: aload         6
     184: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
     187: checkcast     #23                 // class java/lang/String
     190: astore        8
     192: new           #188                // class java/lang/StringBuilder
     195: dup
     196: invokespecial #189                // Method java/lang/StringBuilder."<init>":()V
     199: aload         5
     201: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     204: aload         7
     206: invokevirtual #193                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     209: invokevirtual #202                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     212: aload_1
     213: iload_3
     214: aload         8
     216: invokestatic  #230                // Method mirror$biggestLeftover:(Ljava/util/List;ILjava/lang/String;)I
     219: invokestatic  #218                // Method java/lang/String.valueOf:(I)Ljava/lang/String;
     222: invokestatic  #56                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     225: goto          237
     228: ldc           #146                // String
     230: iload_3
     231: invokestatic  #218                // Method java/lang/String.valueOf:(I)Ljava/lang/String;
     234: invokestatic  #56                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     237: areturn

  private final boolean isEven(int);
    Code:
       0: iload_1
       1: iconst_2
       2: irem
       3: ifne          10
       6: iconst_1
       7: goto          11
      10: iconst_0
      11: ireturn

  private static final int largestPalindromic$lambda$2(kotlin.Pair, kotlin.Pair);
    Code:
       0: aload_0
       1: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
       4: checkcast     #86                 // class java/lang/Number
       7: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      10: istore_2
      11: aload_0
      12: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
      15: checkcast     #86                 // class java/lang/Number
      18: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      21: istore_3
      22: aload_1
      23: invokevirtual #186                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      26: checkcast     #86                 // class java/lang/Number
      29: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      32: istore        4
      34: aload_1
      35: invokevirtual #84                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
      38: checkcast     #86                 // class java/lang/Number
      41: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      44: istore        5
      46: iload_3
      47: iconst_1
      48: if_icmple     56
      51: bipush        100
      53: goto          57
      56: iconst_0
      57: iload_2
      58: iadd
      59: istore        6
      61: iload         5
      63: iconst_1
      64: if_icmple     72
      67: bipush        100
      69: goto          73
      72: iconst_0
      73: iload         4
      75: iadd
      76: istore        7
      78: iload         7
      80: iload         6
      82: isub
      83: ireturn

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

  private static final int mirror$biggestLeftover(java.util.List<kotlin.Pair<java.lang.Integer, java.lang.Integer>>, int, java.lang.String);
    Code:
       0: aload_2
       1: dup
       2: ifnull        11
       5: invokestatic  #252                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
       8: goto          13
      11: pop
      12: iconst_0
      13: istore_3
      14: aload_0
      15: iconst_1
      16: invokestatic  #256                // Method kotlin/collections/CollectionsKt.getOrNull:(Ljava/util/List;I)Ljava/lang/Object;
      19: checkcast     #81                 // class kotlin/Pair
      22: dup
      23: ifnull        38
      26: invokevirtual #259                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      29: checkcast     #86                 // class java/lang/Number
      32: invokevirtual #89                 // Method java/lang/Number.intValue:()I
      35: goto          45
      38: pop
      39: iload_1
      40: iload_3
      41: invokestatic  #265                // Method java/lang/Math.max:(II)I
      44: ireturn
      45: istore        4
      47: iload         4
      49: iload_1
      50: if_icmple     62
      53: iload         4
      55: iload_3
      56: invokestatic  #265                // Method java/lang/Math.max:(II)I
      59: goto          67
      62: iload_1
      63: iload_3
      64: invokestatic  #265                // Method java/lang/Math.max:(II)I
      67: ireturn
}


fun main() {
    val sut = NextClosestTime()

    for (h in 0..23) {
        val hour = if (h < 10) "0$h" else h.toString()
        for (m in 0..59) {
            val minute = if (m < 10) "0$m" else m.toString()
            val time = "$hour:$minute"
            println("\"$time\" -> \"${sut.nextClosestTime(time)}\"")
        }
    }
}

class NextClosestTime {
    fun nextClosestTime(time: String): String {
        val digits = mutableSetOf<Int>()
        digits.add(time[0].digitToInt())
        digits.add(time[1].digitToInt())
        digits.add(time[3].digitToInt())
        digits.add(time[4].digitToInt())
        val sortedDigits = digits.sorted()

        val hour = String(charArrayOf(time[0], time[1]))
        val minute = String(charArrayOf(time[3], time[4]))
        val minuteInt = minute.toInt()
        val hasZero: Boolean = sortedDigits.first() == 0

        return tryNextMinute(
            sortedDigits = sortedDigits,
            hour = hour,
            minute = minute,
            minuteInt = minuteInt,
            hasZero = hasZero
        ) ?: tryNextHorWithMinimizedMin(
            sortedDigits = sortedDigits,
            hour = hour,
            hasZero = hasZero
        ) ?: minimizeTime(sortedDigits)
    }

    private fun tryNextMinute(
        sortedDigits: List<Int>,
        hour: String,
        minute: String,
        minuteInt: Int,
        hasZero: Boolean
    ): String? {
        if (minute == "59") return null

        for (i in sortedDigits.indices) {
            val digit1 = sortedDigits[i]
            if (hasZero) {
                // try single digit
                if (digit1 > minuteInt) return "$hour:0$digit1"
            }

            for (j in sortedDigits.indices) {
                val digit2 = sortedDigits[j]
                val newMinute = validMinute(digit1, digit2)
                if (newMinute != null && newMinute > minuteInt) return "$hour:${format(newMinute)}"
            }
        }

        return null
    }

    private fun tryNextHorWithMinimizedMin(
        sortedDigits: List<Int>,
        hour: String,
        hasZero: Boolean
    ): String? {
        fun minimizedMin(): String = sortedDigits.first().run {
            if (hasZero) "0$this" else "$this$this"
        }

        if (hour == "23") return null
        val hourInt = hour.toInt()

        for (i in sortedDigits.indices) {
            val digit1 = sortedDigits[i]
            if (hasZero) {
                // try single digit
                if (digit1 > hourInt) return "0$digit1:${minimizedMin()}"
            }

            for (j in sortedDigits.indices) {
                val digit2 = sortedDigits[j]
                val newHour = validHour(digit1, digit2)
                if (newHour != null && newHour > hourInt) return "${format(newHour)}:${minimizedMin()}"
            }
        }

        return null
    }

    private fun minimizeTime(
        sortedDigits: List<Int>
    ): String {
        val first = sortedDigits.first()
        return "$first$first:$first$first"
    }

    private fun format(newNumber: Int): String = if (newNumber < 10)
        "0$newNumber" else newNumber.toString()

    private fun validHour(digit1: Int, digit2: Int): Int? {
        val newHour = digit1 * 10 + digit2
        return newHour.takeIf { it in 0..23 }
    }

    private fun validMinute(digit1: Int, digit2: Int): Int? {
        val newMinute = digit1 * 10 + digit2
        return newMinute.takeIf { it in 0..59 }
    }

    /**
     * LeetCode compatibility
     */
    private fun Char.digitToInt(): Int = this.toInt() - '0'.toInt()
}

Compiled from "NextClosestTime.kt"
public final class NextClosestTimeKt {
  public static final void main();
    Code:
       0: new           #8                  // class NextClosestTime
       3: dup
       4: invokespecial #11                 // Method NextClosestTime."<init>":()V
       7: astore_0
       8: iconst_0
       9: istore_1
      10: iload_1
      11: bipush        24
      13: if_icmpge     175
      16: iload_1
      17: bipush        10
      19: if_icmpge     44
      22: new           #13                 // class java/lang/StringBuilder
      25: dup
      26: invokespecial #14                 // Method java/lang/StringBuilder."<init>":()V
      29: bipush        48
      31: invokevirtual #18                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      34: iload_1
      35: invokevirtual #21                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      38: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      41: goto          48
      44: iload_1
      45: invokestatic  #31                 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      48: astore_2
      49: iconst_0
      50: istore_3
      51: iload_3
      52: bipush        60
      54: if_icmpge     169
      57: iload_3
      58: bipush        10
      60: if_icmpge     85
      63: new           #13                 // class java/lang/StringBuilder
      66: dup
      67: invokespecial #14                 // Method java/lang/StringBuilder."<init>":()V
      70: bipush        48
      72: invokevirtual #18                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      75: iload_3
      76: invokevirtual #21                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      79: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      82: goto          89
      85: iload_3
      86: invokestatic  #31                 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      89: astore        4
      91: new           #13                 // class java/lang/StringBuilder
      94: dup
      95: invokespecial #14                 // Method java/lang/StringBuilder."<init>":()V
      98: aload_2
      99: invokevirtual #34                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     102: bipush        58
     104: invokevirtual #18                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     107: aload         4
     109: invokevirtual #34                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     112: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     115: astore        5
     117: new           #13                 // class java/lang/StringBuilder
     120: dup
     121: invokespecial #14                 // Method java/lang/StringBuilder."<init>":()V
     124: bipush        34
     126: invokevirtual #18                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     129: aload         5
     131: invokevirtual #34                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     134: ldc           #36                 // String \" -> \"
     136: invokevirtual #34                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     139: aload_0
     140: aload         5
     142: invokevirtual #40                 // Method NextClosestTime.nextClosestTime:(Ljava/lang/String;)Ljava/lang/String;
     145: invokevirtual #34                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     148: bipush        34
     150: invokevirtual #18                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     153: invokevirtual #25                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     156: getstatic     #46                 // Field java/lang/System.out:Ljava/io/PrintStream;
     159: swap
     160: invokevirtual #52                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     163: iinc          3, 1
     166: goto          51
     169: iinc          1, 1
     172: goto          10
     175: return

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

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

  public final java.lang.String nextClosestTime(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String time
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #23                 // class java/util/LinkedHashSet
       9: dup
      10: invokespecial #24                 // Method java/util/LinkedHashSet."<init>":()V
      13: checkcast     #26                 // class java/util/Set
      16: astore_2
      17: aload_2
      18: aload_0
      19: aload_1
      20: iconst_0
      21: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
      24: invokespecial #36                 // Method digitToInt:(C)I
      27: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      30: invokeinterface #46,  2           // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      35: pop
      36: aload_2
      37: aload_0
      38: aload_1
      39: iconst_1
      40: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
      43: invokespecial #36                 // Method digitToInt:(C)I
      46: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      49: invokeinterface #46,  2           // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      54: pop
      55: aload_2
      56: aload_0
      57: aload_1
      58: iconst_3
      59: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
      62: invokespecial #36                 // Method digitToInt:(C)I
      65: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      68: invokeinterface #46,  2           // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      73: pop
      74: aload_2
      75: aload_0
      76: aload_1
      77: iconst_4
      78: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
      81: invokespecial #36                 // Method digitToInt:(C)I
      84: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      87: invokeinterface #46,  2           // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      92: pop
      93: aload_2
      94: checkcast     #48                 // class java/lang/Iterable
      97: invokestatic  #54                 // Method kotlin/collections/CollectionsKt.sorted:(Ljava/lang/Iterable;)Ljava/util/List;
     100: astore_3
     101: iconst_2
     102: newarray       char
     104: astore        5
     106: aload         5
     108: iconst_0
     109: aload_1
     110: iconst_0
     111: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
     114: castore
     115: aload         5
     117: iconst_1
     118: aload_1
     119: iconst_1
     120: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
     123: castore
     124: aload         5
     126: astore        5
     128: new           #28                 // class java/lang/String
     131: dup
     132: aload         5
     134: invokespecial #57                 // Method java/lang/String."<init>":([C)V
     137: astore        4
     139: iconst_2
     140: newarray       char
     142: astore        6
     144: aload         6
     146: iconst_0
     147: aload_1
     148: iconst_3
     149: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
     152: castore
     153: aload         6
     155: iconst_1
     156: aload_1
     157: iconst_4
     158: invokevirtual #32                 // Method java/lang/String.charAt:(I)C
     161: castore
     162: aload         6
     164: astore        6
     166: new           #28                 // class java/lang/String
     169: dup
     170: aload         6
     172: invokespecial #57                 // Method java/lang/String."<init>":([C)V
     175: astore        5
     177: aload         5
     179: invokestatic  #61                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     182: istore        6
     184: aload_3
     185: invokestatic  #65                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
     188: checkcast     #67                 // class java/lang/Number
     191: invokevirtual #71                 // Method java/lang/Number.intValue:()I
     194: ifne          201
     197: iconst_1
     198: goto          202
     201: iconst_0
     202: istore        7
     204: aload_0
     205: aload_3
     206: aload         4
     208: aload         5
     210: iload         6
     212: iload         7
     214: invokespecial #75                 // Method tryNextMinute:(Ljava/util/List;Ljava/lang/String;Ljava/lang/String;IZ)Ljava/lang/String;
     217: dup
     218: ifnonnull     241
     221: pop
     222: aload_0
     223: aload_3
     224: aload         4
     226: iload         7
     228: invokespecial #79                 // Method tryNextHorWithMinimizedMin:(Ljava/util/List;Ljava/lang/String;Z)Ljava/lang/String;
     231: dup
     232: ifnonnull     241
     235: pop
     236: aload_0
     237: aload_3
     238: invokespecial #83                 // Method minimizeTime:(Ljava/util/List;)Ljava/lang/String;
     241: areturn

  private final java.lang.String tryNextMinute(java.util.List<java.lang.Integer>, java.lang.String, java.lang.String, int, boolean);
    Code:
       0: aload_3
       1: ldc           #99                 // String 59
       3: invokestatic  #103                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
       6: ifeq          11
       9: aconst_null
      10: areturn
      11: iconst_0
      12: istore        6
      14: aload_1
      15: checkcast     #105                // class java/util/Collection
      18: invokeinterface #108,  1          // InterfaceMethod java/util/Collection.size:()I
      23: istore        7
      25: iload         6
      27: iload         7
      29: if_icmpge     191
      32: aload_1
      33: iload         6
      35: invokeinterface #112,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      40: checkcast     #67                 // class java/lang/Number
      43: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      46: istore        8
      48: iload         5
      50: ifeq          85
      53: iload         8
      55: iload         4
      57: if_icmple     85
      60: new           #114                // class java/lang/StringBuilder
      63: dup
      64: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      67: aload_2
      68: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      71: ldc           #121                // String :0
      73: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      76: iload         8
      78: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      81: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      84: areturn
      85: iconst_0
      86: istore        9
      88: aload_1
      89: checkcast     #105                // class java/util/Collection
      92: invokeinterface #108,  1          // InterfaceMethod java/util/Collection.size:()I
      97: istore        10
      99: iload         9
     101: iload         10
     103: if_icmpge     185
     106: aload_1
     107: iload         9
     109: invokeinterface #112,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     114: checkcast     #67                 // class java/lang/Number
     117: invokevirtual #71                 // Method java/lang/Number.intValue:()I
     120: istore        11
     122: aload_0
     123: iload         8
     125: iload         11
     127: invokespecial #132                // Method validMinute:(II)Ljava/lang/Integer;
     130: astore        12
     132: aload         12
     134: ifnull        179
     137: aload         12
     139: invokevirtual #133                // Method java/lang/Integer.intValue:()I
     142: iload         4
     144: if_icmple     179
     147: new           #114                // class java/lang/StringBuilder
     150: dup
     151: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
     154: aload_2
     155: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     158: bipush        58
     160: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     163: aload_0
     164: aload         12
     166: invokevirtual #133                // Method java/lang/Integer.intValue:()I
     169: invokespecial #140                // Method format:(I)Ljava/lang/String;
     172: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     175: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     178: areturn
     179: iinc          9, 1
     182: goto          99
     185: iinc          6, 1
     188: goto          25
     191: aconst_null
     192: areturn

  private final java.lang.String tryNextHorWithMinimizedMin(java.util.List<java.lang.Integer>, java.lang.String, boolean);
    Code:
       0: aload_2
       1: ldc           #149                // String 23
       3: invokestatic  #103                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
       6: ifeq          11
       9: aconst_null
      10: areturn
      11: aload_2
      12: invokestatic  #61                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      15: istore        4
      17: iconst_0
      18: istore        5
      20: aload_1
      21: checkcast     #105                // class java/util/Collection
      24: invokeinterface #108,  1          // InterfaceMethod java/util/Collection.size:()I
      29: istore        6
      31: iload         5
      33: iload         6
      35: if_icmpge     209
      38: aload_1
      39: iload         5
      41: invokeinterface #112,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      46: checkcast     #67                 // class java/lang/Number
      49: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      52: istore        7
      54: iload_3
      55: ifeq          99
      58: iload         7
      60: iload         4
      62: if_icmple     99
      65: new           #114                // class java/lang/StringBuilder
      68: dup
      69: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      72: bipush        48
      74: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      77: iload         7
      79: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      82: bipush        58
      84: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      87: aload_1
      88: iload_3
      89: invokestatic  #153                // Method tryNextHorWithMinimizedMin$minimizedMin:(Ljava/util/List;Z)Ljava/lang/String;
      92: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      95: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      98: areturn
      99: iconst_0
     100: istore        8
     102: aload_1
     103: checkcast     #105                // class java/util/Collection
     106: invokeinterface #108,  1          // InterfaceMethod java/util/Collection.size:()I
     111: istore        9
     113: iload         8
     115: iload         9
     117: if_icmpge     203
     120: aload_1
     121: iload         8
     123: invokeinterface #112,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     128: checkcast     #67                 // class java/lang/Number
     131: invokevirtual #71                 // Method java/lang/Number.intValue:()I
     134: istore        10
     136: aload_0
     137: iload         7
     139: iload         10
     141: invokespecial #156                // Method validHour:(II)Ljava/lang/Integer;
     144: astore        11
     146: aload         11
     148: ifnull        197
     151: aload         11
     153: invokevirtual #133                // Method java/lang/Integer.intValue:()I
     156: iload         4
     158: if_icmple     197
     161: new           #114                // class java/lang/StringBuilder
     164: dup
     165: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
     168: aload_0
     169: aload         11
     171: invokevirtual #133                // Method java/lang/Integer.intValue:()I
     174: invokespecial #140                // Method format:(I)Ljava/lang/String;
     177: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     180: bipush        58
     182: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     185: aload_1
     186: iload_3
     187: invokestatic  #153                // Method tryNextHorWithMinimizedMin$minimizedMin:(Ljava/util/List;Z)Ljava/lang/String;
     190: invokevirtual #119                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     193: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     196: areturn
     197: iinc          8, 1
     200: goto          113
     203: iinc          5, 1
     206: goto          31
     209: aconst_null
     210: areturn

  private final java.lang.String minimizeTime(java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: invokestatic  #65                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
       4: checkcast     #67                 // class java/lang/Number
       7: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      10: istore_2
      11: new           #114                // class java/lang/StringBuilder
      14: dup
      15: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      18: iload_2
      19: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      22: iload_2
      23: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      26: bipush        58
      28: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      31: iload_2
      32: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      35: iload_2
      36: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      39: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      42: areturn

  private final java.lang.String format(int);
    Code:
       0: iload_1
       1: bipush        10
       3: if_icmpge     28
       6: new           #114                // class java/lang/StringBuilder
       9: dup
      10: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      13: bipush        48
      15: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      18: iload_1
      19: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      22: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      25: goto          32
      28: iload_1
      29: invokestatic  #161                // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      32: areturn

  private final java.lang.Integer validHour(int, int);
    Code:
       0: iload_1
       1: bipush        10
       3: imul
       4: iload_2
       5: iadd
       6: istore_3
       7: iload_3
       8: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: astore        4
      13: aload         4
      15: checkcast     #67                 // class java/lang/Number
      18: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      21: istore        5
      23: iconst_0
      24: istore        6
      26: iconst_0
      27: iload         5
      29: if_icmpgt     47
      32: iload         5
      34: bipush        24
      36: if_icmpge     43
      39: iconst_1
      40: goto          48
      43: iconst_0
      44: goto          48
      47: iconst_0
      48: ifeq          56
      51: aload         4
      53: goto          57
      56: aconst_null
      57: areturn

  private final java.lang.Integer validMinute(int, int);
    Code:
       0: iload_1
       1: bipush        10
       3: imul
       4: iload_2
       5: iadd
       6: istore_3
       7: iload_3
       8: invokestatic  #42                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: astore        4
      13: aload         4
      15: checkcast     #67                 // class java/lang/Number
      18: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      21: istore        5
      23: iconst_0
      24: istore        6
      26: iconst_0
      27: iload         5
      29: if_icmpgt     47
      32: iload         5
      34: bipush        60
      36: if_icmpge     43
      39: iconst_1
      40: goto          48
      43: iconst_0
      44: goto          48
      47: iconst_0
      48: ifeq          56
      51: aload         4
      53: goto          57
      56: aconst_null
      57: areturn

  private final int digitToInt(char);
    Code:
       0: iload_1
       1: bipush        48
       3: isub
       4: ireturn

  private static final java.lang.String tryNextHorWithMinimizedMin$minimizedMin(java.util.List<java.lang.Integer>, boolean);
    Code:
       0: aload_0
       1: invokestatic  #65                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
       4: checkcast     #67                 // class java/lang/Number
       7: invokevirtual #71                 // Method java/lang/Number.intValue:()I
      10: istore_2
      11: iconst_0
      12: istore_3
      13: iload_1
      14: ifeq          39
      17: new           #114                // class java/lang/StringBuilder
      20: dup
      21: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      24: bipush        48
      26: invokevirtual #136                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      29: iload_2
      30: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      33: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      36: goto          57
      39: new           #114                // class java/lang/StringBuilder
      42: dup
      43: invokespecial #115                // Method java/lang/StringBuilder."<init>":()V
      46: iload_2
      47: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      50: iload_2
      51: invokevirtual #124                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      54: invokevirtual #128                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      57: nop
      58: areturn
}


import kotlin.math.pow
import kotlin.math.sqrt

typealias Point = IntArray

/**
 * # Minimum Area Rectangle
 *
 * _Note: Time Limit Exceeded (not optimal)_
 *
 * Problem:
 * https://leetcode.com/problems/minimum-area-rectangle/
 */
class MinimumAreaRectangle {

    fun minAreaRect(points: Array<Point>): Int {
        var minArea: Int? = null
        chooseFourUnique(points) { a, b, c, d ->
            if (parallel(a, b, c, d) && rectangle(a, b, c, d)) {
                println("rect: ${a.toList()}, ${b.toList()}, ${c.toList()}, ${d.toList()}")
                val area = area(a, b, c, d)
                minArea = minArea?.let { minOf(it, area) } ?: area
            }
        }
        return minArea ?: 0
    }

    private inline fun chooseFourUnique(
        points: Array<Point>,
        block: (Point, Point, Point, Point) -> Unit
    ) {
        for (a in points) {
            for (b in points) {
                if (a sameAs b) continue
                for (c in points) {
                    if (a sameAs c || b sameAs c) continue
                    for (d in points) {
                        if (a sameAs d || b sameAs d || c sameAs d) continue
                        block(a, b, c, d)
                    }
                }
            }
        }
    }

    private infix fun Point.sameAs(other: Point): Boolean =
        x() == other.x() && y() == other.y()

    private fun area(
        a: Point, b: Point,
        c: Point, d: Point
    ): Int {
        val minX = minOf(a.x(), b.x(), c.x(), d.x())
        val maxX = maxOf(a.x(), b.x(), c.x(), d.x())
        val minY = minOf(a.y(), b.y(), c.y(), d.y())
        val maxY = maxOf(a.y(), b.y(), c.y(), d.y())
        return (maxX - minX) * (maxY - minY)
    }

    private fun parallel(
        a: Point, b: Point,
        c: Point, d: Point,
    ): Boolean {
        val points = arrayOf(a, b, c, d)
        if (points.map { it.x() }.toSet().size > 2) return false
        if (points.map { it.y() }.toSet().size > 2) return false
        return true
    }

    /**
     * Conditions for rectangle:
     * - distance(a,b) == distance(c,d)
     * - distance(a,c) == distance(b,d)
     * - distance(a,d) == distance(b,c)
     *
     * @return whether four points form an rectangle, note: it might be rotated
     */
    private fun rectangle(
        a: Point, b: Point,
        c: Point, d: Point
    ): Boolean = distance(a, b) == distance(c, d) &&
            distance(a, c) == distance(b, d) &&
            distance(a, d) == distance(b, c)

    /**
     * Formula:
     * d=√((x2 – x1)² + (y2 – y1)²)
     */
    private fun distance(p1: Point, p2: Point): Double = sqrt(
        (p1.x().toDouble() - p2.x()).pow(2.0) +
                (p1.y().toDouble() - p2.y()).pow(2.0)
    )

    private fun IntArray.x() = this[0]

    private fun IntArray.y() = this[1]
}

Compiled from "MinimumAreaRectangle.kt"
public final class MinimumAreaRectangleKt {
}

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

  public final int minAreaRect(int[][]);
    Code:
       0: aload_1
       1: ldc           #15                 // String points
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #23                 // class kotlin/jvm/internal/Ref$ObjectRef
       9: dup
      10: invokespecial #24                 // Method kotlin/jvm/internal/Ref$ObjectRef."<init>":()V
      13: astore_2
      14: aload_0
      15: astore_3
      16: iconst_0
      17: istore        4
      19: iconst_0
      20: istore        5
      22: aload_1
      23: checkcast     #26                 // class "[Ljava/lang/Object;"
      26: arraylength
      27: istore        6
      29: iload         5
      31: iload         6
      33: if_icmpge     402
      36: aload_1
      37: iload         5
      39: aaload
      40: astore        7
      42: iconst_0
      43: istore        8
      45: aload_1
      46: checkcast     #26                 // class "[Ljava/lang/Object;"
      49: arraylength
      50: istore        9
      52: iload         8
      54: iload         9
      56: if_icmpge     396
      59: aload_1
      60: iload         8
      62: aaload
      63: astore        10
      65: aload_3
      66: aload         7
      68: aload         10
      70: invokespecial #30                 // Method sameAs:([I[I)Z
      73: ifne          390
      76: iconst_0
      77: istore        11
      79: aload_1
      80: checkcast     #26                 // class "[Ljava/lang/Object;"
      83: arraylength
      84: istore        12
      86: iload         11
      88: iload         12
      90: if_icmpge     390
      93: aload_1
      94: iload         11
      96: aaload
      97: astore        13
      99: aload_3
     100: aload         7
     102: aload         13
     104: invokespecial #30                 // Method sameAs:([I[I)Z
     107: ifne          384
     110: aload_3
     111: aload         10
     113: aload         13
     115: invokespecial #30                 // Method sameAs:([I[I)Z
     118: ifeq          124
     121: goto          384
     124: iconst_0
     125: istore        14
     127: aload_1
     128: checkcast     #26                 // class "[Ljava/lang/Object;"
     131: arraylength
     132: istore        15
     134: iload         14
     136: iload         15
     138: if_icmpge     384
     141: aload_1
     142: iload         14
     144: aaload
     145: astore        16
     147: aload_3
     148: aload         7
     150: aload         16
     152: invokespecial #30                 // Method sameAs:([I[I)Z
     155: ifne          378
     158: aload_3
     159: aload         10
     161: aload         16
     163: invokespecial #30                 // Method sameAs:([I[I)Z
     166: ifne          378
     169: aload_3
     170: aload         13
     172: aload         16
     174: invokespecial #30                 // Method sameAs:([I[I)Z
     177: ifeq          183
     180: goto          378
     183: aload         7
     185: aload         10
     187: aload         13
     189: aload         16
     191: astore        17
     193: astore        18
     195: astore        19
     197: astore        20
     199: iconst_0
     200: istore        21
     202: aload_0
     203: aload         20
     205: aload         19
     207: aload         18
     209: aload         17
     211: invokespecial #34                 // Method parallel:([I[I[I[I)Z
     214: ifeq          376
     217: aload_0
     218: aload         20
     220: aload         19
     222: aload         18
     224: aload         17
     226: invokespecial #37                 // Method rectangle:([I[I[I[I)Z
     229: ifeq          376
     232: new           #39                 // class java/lang/StringBuilder
     235: dup
     236: invokespecial #40                 // Method java/lang/StringBuilder."<init>":()V
     239: ldc           #42                 // String rect:
     241: invokevirtual #46                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     244: aload         20
     246: invokestatic  #52                 // Method kotlin/collections/ArraysKt.toList:([I)Ljava/util/List;
     249: invokevirtual #55                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     252: ldc           #57                 // String ,
     254: invokevirtual #46                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     257: aload         19
     259: invokestatic  #52                 // Method kotlin/collections/ArraysKt.toList:([I)Ljava/util/List;
     262: invokevirtual #55                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     265: ldc           #57                 // String ,
     267: invokevirtual #46                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     270: aload         18
     272: invokestatic  #52                 // Method kotlin/collections/ArraysKt.toList:([I)Ljava/util/List;
     275: invokevirtual #55                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     278: ldc           #57                 // String ,
     280: invokevirtual #46                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     283: aload         17
     285: invokestatic  #52                 // Method kotlin/collections/ArraysKt.toList:([I)Ljava/util/List;
     288: invokevirtual #55                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     291: invokevirtual #61                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     294: getstatic     #67                 // Field java/lang/System.out:Ljava/io/PrintStream;
     297: swap
     298: invokevirtual #73                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     301: aload_0
     302: aload         20
     304: aload         19
     306: aload         18
     308: aload         17
     310: invokespecial #77                 // Method area:([I[I[I[I)I
     313: istore        22
     315: aload_2
     316: aload_2
     317: getfield      #81                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     320: checkcast     #83                 // class java/lang/Integer
     323: dup
     324: ifnull        367
     327: checkcast     #85                 // class java/lang/Number
     330: invokevirtual #89                 // Method java/lang/Number.intValue:()I
     333: istore        23
     335: astore        24
     337: iconst_0
     338: istore        25
     340: iload         23
     342: iload         22
     344: invokestatic  #95                 // Method java/lang/Math.min:(II)I
     347: nop
     348: invokestatic  #99                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     351: aload         24
     353: swap
     354: nop
     355: checkcast     #85                 // class java/lang/Number
     358: invokevirtual #89                 // Method java/lang/Number.intValue:()I
     361: invokestatic  #99                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     364: goto          373
     367: pop
     368: iload         22
     370: invokestatic  #99                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     373: putfield      #81                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     376: nop
     377: nop
     378: iinc          14, 1
     381: goto          134
     384: iinc          11, 1
     387: goto          86
     390: iinc          8, 1
     393: goto          52
     396: iinc          5, 1
     399: goto          29
     402: nop
     403: aload_2
     404: getfield      #81                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     407: checkcast     #83                 // class java/lang/Integer
     410: dup
     411: ifnull        420
     414: invokevirtual #100                // Method java/lang/Integer.intValue:()I
     417: goto          422
     420: pop
     421: iconst_0
     422: ireturn

  private final void chooseFourUnique(int[][], kotlin.jvm.functions.Function4<? super int[], ? super int[], ? super int[], ? super int[], kotlin.Unit>);
    Code:
       0: iconst_0
       1: istore_3
       2: iconst_0
       3: istore        4
       5: aload_1
       6: checkcast     #26                 // class "[Ljava/lang/Object;"
       9: arraylength
      10: istore        5
      12: iload         4
      14: iload         5
      16: if_icmpge     205
      19: aload_1
      20: iload         4
      22: aaload
      23: astore        6
      25: iconst_0
      26: istore        7
      28: aload_1
      29: checkcast     #26                 // class "[Ljava/lang/Object;"
      32: arraylength
      33: istore        8
      35: iload         7
      37: iload         8
      39: if_icmpge     199
      42: aload_1
      43: iload         7
      45: aaload
      46: astore        9
      48: aload_0
      49: aload         6
      51: aload         9
      53: invokespecial #30                 // Method sameAs:([I[I)Z
      56: ifne          193
      59: iconst_0
      60: istore        10
      62: aload_1
      63: checkcast     #26                 // class "[Ljava/lang/Object;"
      66: arraylength
      67: istore        11
      69: iload         10
      71: iload         11
      73: if_icmpge     193
      76: aload_1
      77: iload         10
      79: aaload
      80: astore        12
      82: aload_0
      83: aload         6
      85: aload         12
      87: invokespecial #30                 // Method sameAs:([I[I)Z
      90: ifne          187
      93: aload_0
      94: aload         9
      96: aload         12
      98: invokespecial #30                 // Method sameAs:([I[I)Z
     101: ifeq          107
     104: goto          187
     107: iconst_0
     108: istore        13
     110: aload_1
     111: checkcast     #26                 // class "[Ljava/lang/Object;"
     114: arraylength
     115: istore        14
     117: iload         13
     119: iload         14
     121: if_icmpge     187
     124: aload_1
     125: iload         13
     127: aaload
     128: astore        15
     130: aload_0
     131: aload         6
     133: aload         15
     135: invokespecial #30                 // Method sameAs:([I[I)Z
     138: ifne          181
     141: aload_0
     142: aload         9
     144: aload         15
     146: invokespecial #30                 // Method sameAs:([I[I)Z
     149: ifne          181
     152: aload_0
     153: aload         12
     155: aload         15
     157: invokespecial #30                 // Method sameAs:([I[I)Z
     160: ifeq          166
     163: goto          181
     166: aload_2
     167: aload         6
     169: aload         9
     171: aload         12
     173: aload         15
     175: invokeinterface #129,  5          // InterfaceMethod kotlin/jvm/functions/Function4.invoke:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     180: pop
     181: iinc          13, 1
     184: goto          117
     187: iinc          10, 1
     190: goto          69
     193: iinc          7, 1
     196: goto          35
     199: iinc          4, 1
     202: goto          12
     205: return

  private final boolean sameAs(int[], int[]);
    Code:
       0: aload_0
       1: aload_1
       2: invokespecial #135                // Method x:([I)I
       5: aload_0
       6: aload_2
       7: invokespecial #135                // Method x:([I)I
      10: if_icmpne     30
      13: aload_0
      14: aload_1
      15: invokespecial #138                // Method y:([I)I
      18: aload_0
      19: aload_2
      20: invokespecial #138                // Method y:([I)I
      23: if_icmpne     30
      26: iconst_1
      27: goto          31
      30: iconst_0
      31: ireturn

  private final int area(int[], int[], int[], int[]);
    Code:
       0: aload_0
       1: aload_1
       2: invokespecial #135                // Method x:([I)I
       5: iconst_3
       6: newarray       int
       8: astore        6
      10: aload         6
      12: iconst_0
      13: aload_0
      14: aload_2
      15: invokespecial #135                // Method x:([I)I
      18: iastore
      19: aload         6
      21: iconst_1
      22: aload_0
      23: aload_3
      24: invokespecial #135                // Method x:([I)I
      27: iastore
      28: aload         6
      30: iconst_2
      31: aload_0
      32: aload         4
      34: invokespecial #135                // Method x:([I)I
      37: iastore
      38: aload         6
      40: invokestatic  #146                // Method kotlin/comparisons/ComparisonsKt.minOf:(I[I)I
      43: istore        5
      45: aload_0
      46: aload_1
      47: invokespecial #135                // Method x:([I)I
      50: iconst_3
      51: newarray       int
      53: astore        7
      55: aload         7
      57: iconst_0
      58: aload_0
      59: aload_2
      60: invokespecial #135                // Method x:([I)I
      63: iastore
      64: aload         7
      66: iconst_1
      67: aload_0
      68: aload_3
      69: invokespecial #135                // Method x:([I)I
      72: iastore
      73: aload         7
      75: iconst_2
      76: aload_0
      77: aload         4
      79: invokespecial #135                // Method x:([I)I
      82: iastore
      83: aload         7
      85: invokestatic  #149                // Method kotlin/comparisons/ComparisonsKt.maxOf:(I[I)I
      88: istore        6
      90: aload_0
      91: aload_1
      92: invokespecial #138                // Method y:([I)I
      95: iconst_3
      96: newarray       int
      98: astore        8
     100: aload         8
     102: iconst_0
     103: aload_0
     104: aload_2
     105: invokespecial #138                // Method y:([I)I
     108: iastore
     109: aload         8
     111: iconst_1
     112: aload_0
     113: aload_3
     114: invokespecial #138                // Method y:([I)I
     117: iastore
     118: aload         8
     120: iconst_2
     121: aload_0
     122: aload         4
     124: invokespecial #138                // Method y:([I)I
     127: iastore
     128: aload         8
     130: invokestatic  #146                // Method kotlin/comparisons/ComparisonsKt.minOf:(I[I)I
     133: istore        7
     135: aload_0
     136: aload_1
     137: invokespecial #138                // Method y:([I)I
     140: iconst_3
     141: newarray       int
     143: astore        9
     145: aload         9
     147: iconst_0
     148: aload_0
     149: aload_2
     150: invokespecial #138                // Method y:([I)I
     153: iastore
     154: aload         9
     156: iconst_1
     157: aload_0
     158: aload_3
     159: invokespecial #138                // Method y:([I)I
     162: iastore
     163: aload         9
     165: iconst_2
     166: aload_0
     167: aload         4
     169: invokespecial #138                // Method y:([I)I
     172: iastore
     173: aload         9
     175: invokestatic  #149                // Method kotlin/comparisons/ComparisonsKt.maxOf:(I[I)I
     178: istore        8
     180: iload         6
     182: iload         5
     184: isub
     185: iload         8
     187: iload         7
     189: isub
     190: imul
     191: ireturn

  private final boolean parallel(int[], int[], int[], int[]);
    Code:
       0: iconst_4
       1: anewarray     #120                // class "[I"
       4: astore        6
       6: aload         6
       8: iconst_0
       9: aload_1
      10: aastore
      11: aload         6
      13: iconst_1
      14: aload_2
      15: aastore
      16: aload         6
      18: iconst_2
      19: aload_3
      20: aastore
      21: aload         6
      23: iconst_3
      24: aload         4
      26: aastore
      27: aload         6
      29: astore        5
      31: aload         5
      33: checkcast     #26                 // class "[Ljava/lang/Object;"
      36: astore        6
      38: iconst_0
      39: istore        7
      41: aload         6
      43: astore        8
      45: new           #155                // class java/util/ArrayList
      48: dup
      49: aload         6
      51: arraylength
      52: invokespecial #158                // Method java/util/ArrayList."<init>":(I)V
      55: checkcast     #160                // class java/util/Collection
      58: astore        9
      60: iconst_0
      61: istore        10
      63: iconst_0
      64: istore        11
      66: aload         8
      68: arraylength
      69: istore        12
      71: iload         11
      73: iload         12
      75: if_icmpge     123
      78: aload         8
      80: iload         11
      82: aaload
      83: astore        13
      85: aload         9
      87: aload         13
      89: checkcast     #120                // class "[I"
      92: astore        14
      94: astore        16
      96: iconst_0
      97: istore        15
      99: aload_0
     100: aload         14
     102: invokespecial #135                // Method x:([I)I
     105: invokestatic  #99                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     108: aload         16
     110: swap
     111: invokeinterface #164,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     116: pop
     117: iinc          11, 1
     120: goto          71
     123: aload         9
     125: checkcast     #166                // class java/util/List
     128: nop
     129: checkcast     #168                // class java/lang/Iterable
     132: invokestatic  #174                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     135: invokeinterface #179,  1          // InterfaceMethod java/util/Set.size:()I
     140: iconst_2
     141: if_icmple     146
     144: iconst_0
     145: ireturn
     146: aload         5
     148: checkcast     #26                 // class "[Ljava/lang/Object;"
     151: astore        6
     153: iconst_0
     154: istore        7
     156: aload         6
     158: astore        8
     160: new           #155                // class java/util/ArrayList
     163: dup
     164: aload         6
     166: arraylength
     167: invokespecial #158                // Method java/util/ArrayList."<init>":(I)V
     170: checkcast     #160                // class java/util/Collection
     173: astore        9
     175: iconst_0
     176: istore        10
     178: iconst_0
     179: istore        11
     181: aload         8
     183: arraylength
     184: istore        12
     186: iload         11
     188: iload         12
     190: if_icmpge     238
     193: aload         8
     195: iload         11
     197: aaload
     198: astore        13
     200: aload         9
     202: aload         13
     204: checkcast     #120                // class "[I"
     207: astore        14
     209: astore        16
     211: iconst_0
     212: istore        15
     214: aload_0
     215: aload         14
     217: invokespecial #138                // Method y:([I)I
     220: invokestatic  #99                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     223: aload         16
     225: swap
     226: invokeinterface #164,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     231: pop
     232: iinc          11, 1
     235: goto          186
     238: aload         9
     240: checkcast     #166                // class java/util/List
     243: nop
     244: checkcast     #168                // class java/lang/Iterable
     247: invokestatic  #174                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     250: invokeinterface #179,  1          // InterfaceMethod java/util/Set.size:()I
     255: iconst_2
     256: if_icmple     261
     259: iconst_0
     260: ireturn
     261: iconst_1
     262: ireturn

  private final boolean rectangle(int[], int[], int[], int[]);
    Code:
       0: aload_0
       1: aload_1
       2: aload_2
       3: invokespecial #192                // Method distance:([I[I)D
       6: aload_0
       7: aload_3
       8: aload         4
      10: invokespecial #192                // Method distance:([I[I)D
      13: dcmpg
      14: ifne          21
      17: iconst_1
      18: goto          22
      21: iconst_0
      22: ifeq          79
      25: aload_0
      26: aload_1
      27: aload_3
      28: invokespecial #192                // Method distance:([I[I)D
      31: aload_0
      32: aload_2
      33: aload         4
      35: invokespecial #192                // Method distance:([I[I)D
      38: dcmpg
      39: ifne          46
      42: iconst_1
      43: goto          47
      46: iconst_0
      47: ifeq          79
      50: aload_0
      51: aload_1
      52: aload         4
      54: invokespecial #192                // Method distance:([I[I)D
      57: aload_0
      58: aload_2
      59: aload_3
      60: invokespecial #192                // Method distance:([I[I)D
      63: dcmpg
      64: ifne          71
      67: iconst_1
      68: goto          72
      71: iconst_0
      72: ifeq          79
      75: iconst_1
      76: goto          80
      79: iconst_0
      80: ireturn

  private final double distance(int[], int[]);
    Code:
       0: nop
       1: aload_0
       2: aload_1
       3: invokespecial #135                // Method x:([I)I
       6: i2d
       7: aload_0
       8: aload_2
       9: invokespecial #135                // Method x:([I)I
      12: i2d
      13: dsub
      14: ldc2_w        #193                // double 2.0d
      17: invokestatic  #198                // Method java/lang/Math.pow:(DD)D
      20: aload_0
      21: aload_1
      22: invokespecial #138                // Method y:([I)I
      25: i2d
      26: aload_0
      27: aload_2
      28: invokespecial #138                // Method y:([I)I
      31: i2d
      32: dsub
      33: ldc2_w        #193                // double 2.0d
      36: invokestatic  #198                // Method java/lang/Math.pow:(DD)D
      39: dadd
      40: invokestatic  #202                // Method java/lang/Math.sqrt:(D)D
      43: dreturn

  private final int x(int[]);
    Code:
       0: aload_1
       1: iconst_0
       2: iaload
       3: ireturn

  private final int y(int[]);
    Code:
       0: aload_1
       1: iconst_1
       2: iaload
       3: ireturn
}


fun numberOfWaysToMakeChange(n: Int, denoms: List<Int>): Int {
    // Write your code here.
    println("----------- CASE: n = $n, denoms = $denoms ----------------")
    val allWays = ways(
        n = n,
        ds = denoms,
    )
    println("All ways: $allWays")
    val uniqueWays = allWays.map { it.sorted() }.toSet()
    println("Unique ways: $uniqueWays")
    println("------------- END CASE ---------------")
    return uniqueWays.size
}

/*
    n = 3, denoms = [1,2]
    ways(3) = ways(1) + ways(2)
 */
fun ways(
    n: Int,
    ds: List<Int>,
    ways: List<Int> = emptyList()
): List<List<Int>> {
    if (n < 0) return emptyList()
    if (n == 0) return listOf(ways)

    val validDs = ds.filter { it <= n }
    return validDs.foldRight(initial = emptyList()) { d, allWays ->
        ways(n = n - d, ways = ways + d, ds = validDs) + allWays
    }
}

Compiled from "AllWaysToMakeChange.kt"
public final class AllWaysToMakeChangeKt {
  public static final int numberOfWaysToMakeChange(int, java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: ldc           #10                 // String denoms
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #18                 // class java/lang/StringBuilder
       9: dup
      10: invokespecial #22                 // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #24                 // String ----------- CASE: n =
      15: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: iload_0
      19: invokevirtual #31                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      22: ldc           #33                 // String , denoms =
      24: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: aload_1
      28: invokevirtual #36                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      31: ldc           #38                 // String  ----------------
      33: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      36: invokevirtual #42                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      39: getstatic     #48                 // Field java/lang/System.out:Ljava/io/PrintStream;
      42: swap
      43: invokevirtual #54                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      46: iload_0
      47: aload_1
      48: aconst_null
      49: iconst_4
      50: aconst_null
      51: invokestatic  #58                 // Method ways$default:(ILjava/util/List;Ljava/util/List;ILjava/lang/Object;)Ljava/util/List;
      54: astore_2
      55: new           #18                 // class java/lang/StringBuilder
      58: dup
      59: invokespecial #22                 // Method java/lang/StringBuilder."<init>":()V
      62: ldc           #60                 // String All ways:
      64: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      67: aload_2
      68: invokevirtual #36                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      71: invokevirtual #42                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      74: getstatic     #48                 // Field java/lang/System.out:Ljava/io/PrintStream;
      77: swap
      78: invokevirtual #54                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      81: aload_2
      82: checkcast     #62                 // class java/lang/Iterable
      85: astore        4
      87: iconst_0
      88: istore        5
      90: aload         4
      92: astore        6
      94: new           #64                 // class java/util/ArrayList
      97: dup
      98: aload         4
     100: bipush        10
     102: invokestatic  #70                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     105: invokespecial #73                 // Method java/util/ArrayList."<init>":(I)V
     108: checkcast     #75                 // class java/util/Collection
     111: astore        7
     113: iconst_0
     114: istore        8
     116: aload         6
     118: invokeinterface #79,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     123: astore        9
     125: aload         9
     127: invokeinterface #85,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     132: ifeq          178
     135: aload         9
     137: invokeinterface #89,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     142: astore        10
     144: aload         7
     146: aload         10
     148: checkcast     #91                 // class java/util/List
     151: astore        11
     153: astore        13
     155: iconst_0
     156: istore        12
     158: aload         11
     160: checkcast     #62                 // class java/lang/Iterable
     163: invokestatic  #95                 // Method kotlin/collections/CollectionsKt.sorted:(Ljava/lang/Iterable;)Ljava/util/List;
     166: aload         13
     168: swap
     169: invokeinterface #99,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     174: pop
     175: goto          125
     178: aload         7
     180: checkcast     #91                 // class java/util/List
     183: nop
     184: checkcast     #62                 // class java/lang/Iterable
     187: invokestatic  #103                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     190: astore_3
     191: new           #18                 // class java/lang/StringBuilder
     194: dup
     195: invokespecial #22                 // Method java/lang/StringBuilder."<init>":()V
     198: ldc           #105                // String Unique ways:
     200: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     203: aload_3
     204: invokevirtual #36                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     207: invokevirtual #42                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     210: getstatic     #48                 // Field java/lang/System.out:Ljava/io/PrintStream;
     213: swap
     214: invokevirtual #54                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     217: ldc           #107                // String ------------- END CASE ---------------
     219: getstatic     #48                 // Field java/lang/System.out:Ljava/io/PrintStream;
     222: swap
     223: invokevirtual #54                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     226: aload_3
     227: invokeinterface #113,  1          // InterfaceMethod java/util/Set.size:()I
     232: ireturn

  public static final java.util.List<java.util.List<java.lang.Integer>> ways(int, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>);
    Code:
       0: aload_1
       1: ldc           #135                // String ds
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #136                // String ways
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iload_0
      13: ifge          20
      16: invokestatic  #140                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      19: areturn
      20: iload_0
      21: ifne          29
      24: aload_2
      25: invokestatic  #144                // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      28: areturn
      29: aload_1
      30: checkcast     #62                 // class java/lang/Iterable
      33: astore        4
      35: iconst_0
      36: istore        5
      38: aload         4
      40: astore        6
      42: new           #64                 // class java/util/ArrayList
      45: dup
      46: invokespecial #145                // Method java/util/ArrayList."<init>":()V
      49: checkcast     #75                 // class java/util/Collection
      52: astore        7
      54: iconst_0
      55: istore        8
      57: aload         6
      59: invokeinterface #79,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      64: astore        9
      66: aload         9
      68: invokeinterface #85,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      73: ifeq          125
      76: aload         9
      78: invokeinterface #89,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      83: astore        10
      85: aload         10
      87: checkcast     #147                // class java/lang/Number
      90: invokevirtual #150                // Method java/lang/Number.intValue:()I
      93: istore        11
      95: iconst_0
      96: istore        12
      98: iload         11
     100: iload_0
     101: if_icmpgt     108
     104: iconst_1
     105: goto          109
     108: iconst_0
     109: ifeq          66
     112: aload         7
     114: aload         10
     116: invokeinterface #99,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     121: pop
     122: goto          66
     125: aload         7
     127: checkcast     #91                 // class java/util/List
     130: nop
     131: astore_3
     132: aload_3
     133: astore        4
     135: invokestatic  #140                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
     138: astore        5
     140: iconst_0
     141: istore        6
     143: aload         5
     145: astore        7
     147: aload         4
     149: invokeinterface #153,  1          // InterfaceMethod java/util/List.isEmpty:()Z
     154: ifne          249
     157: aload         4
     159: aload         4
     161: invokeinterface #154,  1          // InterfaceMethod java/util/List.size:()I
     166: invokeinterface #158,  2          // InterfaceMethod java/util/List.listIterator:(I)Ljava/util/ListIterator;
     171: astore        8
     173: aload         8
     175: invokeinterface #163,  1          // InterfaceMethod java/util/ListIterator.hasPrevious:()Z
     180: ifeq          249
     183: aload         8
     185: invokeinterface #166,  1          // InterfaceMethod java/util/ListIterator.previous:()Ljava/lang/Object;
     190: aload         7
     192: astore        9
     194: checkcast     #147                // class java/lang/Number
     197: invokevirtual #150                // Method java/lang/Number.intValue:()I
     200: istore        10
     202: iconst_0
     203: istore        11
     205: iload_0
     206: iload         10
     208: isub
     209: istore        12
     211: aload_2
     212: checkcast     #75                 // class java/util/Collection
     215: iload         10
     217: invokestatic  #172                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     220: invokestatic  #176                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
     223: astore        13
     225: iload         12
     227: aload_3
     228: aload         13
     230: invokestatic  #178                // Method ways:(ILjava/util/List;Ljava/util/List;)Ljava/util/List;
     233: checkcast     #75                 // class java/util/Collection
     236: aload         9
     238: checkcast     #62                 // class java/lang/Iterable
     241: invokestatic  #181                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
     244: astore        7
     246: goto          173
     249: aload         7
     251: areturn

  public static java.util.List ways$default(int, java.util.List, java.util.List, int, java.lang.Object);
    Code:
       0: iload_3
       1: iconst_4
       2: iand
       3: ifeq          10
       6: invokestatic  #140                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
       9: astore_2
      10: iload_0
      11: aload_1
      12: aload_2
      13: invokestatic  #178                // Method ways:(ILjava/util/List;Ljava/util/List;)Ljava/util/List;
      16: areturn
}


/**
 * # 567. Permutation in String
 * Problem:
 * https://leetcode.com/problems/permutation-in-string/
 *
 * WARNING: This solution is not optimal!
 */
class PermutationInString {
    fun checkInclusion(target: String, source: String): Boolean {
        if (target.length > source.length) return false
        return permuteFind(target) {
            source.contains(it)
        }
    }

    private fun permuteFind(
        arr: String,
        n: Int = arr.length,
        k: Int = 0,
        find: (String) -> Boolean
    ): Boolean {
        if (k == n - 1) {
            return find(arr)
        }

        for (i in k until n) {
            val newArr = arr.swap(k, i)
            if (i != k && arr == newArr) continue
            if (permuteFind(arr = newArr, n = n, k = k + 1, find = find)) {
                return true
            }
        }
        return false
    }

    private fun String.swap(i: Int, j: Int): String {
        if (i == j) return this
        val arr = this.toCharArray()
        val temp = arr[i]
        arr[i] = arr[j]
        arr[j] = temp
        return arr.concatToString()
    }
}

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

  public final boolean checkInclusion(java.lang.String, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String target
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #23                 // String source
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: invokevirtual #29                 // Method java/lang/String.length:()I
      16: aload_2
      17: invokevirtual #29                 // Method java/lang/String.length:()I
      20: if_icmple     25
      23: iconst_0
      24: ireturn
      25: aload_0
      26: aload_1
      27: iconst_0
      28: iconst_0
      29: aload_2
      30: invokedynamic #48,  0             // InvokeDynamic #0:invoke:(Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
      35: bipush        6
      37: aconst_null
      38: invokestatic  #52                 // Method permuteFind$default:(LPermutationInString;Ljava/lang/String;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Z
      41: ireturn

  private final boolean permuteFind(java.lang.String, int, int, kotlin.jvm.functions.Function1<? super java.lang.String, java.lang.Boolean>);
    Code:
       0: iload_3
       1: iload_2
       2: iconst_1
       3: isub
       4: if_icmpne     22
       7: aload         4
       9: aload_1
      10: invokeinterface #60,  2           // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      15: checkcast     #62                 // class java/lang/Boolean
      18: invokevirtual #66                 // Method java/lang/Boolean.booleanValue:()Z
      21: ireturn
      22: iload_3
      23: istore        5
      25: iload         5
      27: iload_2
      28: if_icmpge     79
      31: aload_0
      32: aload_1
      33: iload_3
      34: iload         5
      36: invokespecial #70                 // Method swap:(Ljava/lang/String;II)Ljava/lang/String;
      39: astore        6
      41: iload         5
      43: iload_3
      44: if_icmpeq     56
      47: aload_1
      48: aload         6
      50: invokestatic  #74                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      53: ifne          73
      56: aload_0
      57: aload         6
      59: iload_2
      60: iload_3
      61: iconst_1
      62: iadd
      63: aload         4
      65: invokespecial #76                 // Method permuteFind:(Ljava/lang/String;IILkotlin/jvm/functions/Function1;)Z
      68: ifeq          73
      71: iconst_1
      72: ireturn
      73: iinc          5, 1
      76: goto          25
      79: iconst_0
      80: ireturn

  static boolean permuteFind$default(PermutationInString, java.lang.String, int, int, kotlin.jvm.functions.Function1, int, java.lang.Object);
    Code:
       0: iload         5
       2: iconst_2
       3: iand
       4: ifeq          12
       7: aload_1
       8: invokevirtual #29                 // Method java/lang/String.length:()I
      11: istore_2
      12: iload         5
      14: iconst_4
      15: iand
      16: ifeq          21
      19: iconst_0
      20: istore_3
      21: aload_0
      22: aload_1
      23: iload_2
      24: iload_3
      25: aload         4
      27: invokespecial #76                 // Method permuteFind:(Ljava/lang/String;IILkotlin/jvm/functions/Function1;)Z
      30: ireturn

  private final java.lang.String swap(java.lang.String, int, int);
    Code:
       0: iload_2
       1: iload_3
       2: if_icmpne     7
       5: aload_1
       6: areturn
       7: aload_1
       8: invokevirtual #88                 // Method java/lang/String.toCharArray:()[C
      11: dup
      12: ldc           #90                 // String toCharArray(...)
      14: invokestatic  #93                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      17: astore        4
      19: aload         4
      21: iload_2
      22: caload
      23: istore        5
      25: aload         4
      27: iload_2
      28: aload         4
      30: iload_3
      31: caload
      32: castore
      33: aload         4
      35: iload_3
      36: iload         5
      38: castore
      39: aload         4
      41: invokestatic  #99                 // Method kotlin/text/StringsKt.concatToString:([C)Ljava/lang/String;
      44: areturn

  private static final boolean checkInclusion$lambda$0(java.lang.String, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #106                // String it
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #108                // class java/lang/CharSequence
      10: aload_1
      11: checkcast     #108                // class java/lang/CharSequence
      14: iconst_0
      15: iconst_2
      16: aconst_null
      17: invokestatic  #112                // Method kotlin/text/StringsKt.contains$default:(Ljava/lang/CharSequence;Ljava/lang/CharSequence;ZILjava/lang/Object;)Z
      20: ireturn
}