package com.github.corneil.aoc2019.day14

import java.io.File

typealias ChemicalQty = Pair<Long, String>

data class ReactionFormula(val inputs: List<ChemicalQty>, val output: ChemicalQty)

fun readChemicalQty(it: String): ChemicalQty {
    val tokens = it.trim().split(" ")
    require(tokens.size == 2)
    return ChemicalQty(tokens[0].toLong(), tokens[1].trim())
}

fun readReaction(input: String): ReactionFormula {
    val inputs = input.substringBefore("=>").split(",").map {
        readChemicalQty(it)
    }
    return ReactionFormula(inputs, readChemicalQty(input.substringAfter("=>")))
}

fun readReactions(input: List<String>) = input.map { readReaction(it) }

fun add(value: MutableMap<String, Long>, output: ChemicalQty) {
    val qty = value[output.second]
    if (qty != null) {
        value[output.second] = qty + output.first
    } else {
        value[output.second] = output.first
    }
}

fun produce(
    output: ChemicalQty,
    formulae: Map<String, ReactionFormula>,
    sideEffect: MutableMap<String, Long>,
    used: MutableMap<String, Long>
) {
    val remain = sideEffect[output.second]
    if (remain != null && remain > 0L) {
        useRemainingChemicals(remain, output, formulae, sideEffect, used)
    } else {
        val formula = formulae[output.second]
        if (formula != null) {
            applyFormula(output, formula, formulae, sideEffect, used)
        } else {
            // This is usually the ORE
            add(used, output)
        }
    }
}

fun useRemainingChemicals(
    remain: Long,
    output: ChemicalQty,
    formulae: Map<String, ReactionFormula>,
    sideEffect: MutableMap<String, Long>,
    used: MutableMap<String, Long>
) {
    if (remain >= output.first) {
        val qty = remain - output.first
        sideEffect[output.second] = qty
        require(qty >= 0) { "Expected Qty to be zero or greater for ${output.second} not $qty" }
    } else {
        sideEffect.remove(output.second)
        produce(ChemicalQty(output.first - remain, output.second), formulae, sideEffect, used)
    }
}

fun applyFormula(
    output: ChemicalQty,
    formula: ReactionFormula,
    formulae: Map<String, ReactionFormula>,
    sideEffect: MutableMap<String, Long>,
    used: MutableMap<String, Long>
) {
    val repeats = if (output.first < formula.output.first) {
        1L
    } else {
        output.first / formula.output.first +
                if (output.first % formula.output.first == 0L) 0L else 1L
    }
    val produced = apply(formula, repeats, formulae, sideEffect, used)
    if (output.first < produced.first) {
        sideEffect[output.second] = produced.first - output.first
    }
}

fun apply(
    formula: ReactionFormula,
    repeats: Long,
    formulae: Map<String, ReactionFormula>,
    sideEffect: MutableMap<String, Long>,
    used: MutableMap<String, Long>
): ChemicalQty {
    formula.inputs.forEach {
        produce(ChemicalQty(it.first * repeats, it.second), formulae, sideEffect, used)
    }
    return ChemicalQty(formula.output.first * repeats, formula.output.second)
}

fun determineInputForOutput(input: String, output: ChemicalQty, formulae: List<ReactionFormula>): Long {
    val formula = formulae.map { it.output.second to it }.toMap()
    val used = mutableMapOf<String, Long>()
    val sideEffect = mutableMapOf<String, Long>()
    produce(output, formula, sideEffect, used)
    println("$output = $used, Side Effects = $sideEffect")
    return used[input] ?: 0L
}

fun executeReactions(
    increment: Long,
    input: ChemicalQty,
    output: String,
    formula: Map<String, ReactionFormula>,
    used: MutableMap<String, Long>
): Pair<Long, Long> {
    val sideEffect = mutableMapOf<String, Long>()
    var inc = increment
    var counter = 0L
    while (input.first > used[input.second] ?: 0L) {
        produce(ChemicalQty(inc, output), formula, sideEffect, used)
        counter += inc
        if (counter % 10000L == 0L) {
            print("produce $output for $input = $counter\r")
        }
        val usedSoFar = used[input.second] ?: 0L
        if (inc == 100L && (10L * usedSoFar / input.first > 7L)) {
            inc = 10L
        } else if (inc == 10L && (10L * usedSoFar / input.first > 8L)) {
            inc = 1L
        }
    }
    println("Used = $used, Side Effect = $sideEffect")
    return Pair(counter, inc)
}

fun determineOuputForInput(input: ChemicalQty, output: String, formulae: List<ReactionFormula>): Long {
    val formula = formulae.map { it.output.second to it }.toMap()
    val used = mutableMapOf<String, Long>()
    var increment = 1000L // Start with 100 and drop down to save some time
    var counter: Long
    do {
        increment /= 10L
        val pair = executeReactions(increment, input, output, formula, used)
        counter = pair.first
        increment = pair.second
    } while (increment > 1L) // If last increment isn't 1 redo
    val result = if (used[input.second] == input.first) counter else counter - 1L
    println("output $input = $result")
    return result
}

fun main(args: Array<String>) {
    val fileName = if (args.size > 1) args[0] else "input.txt"
    val formulae = readReactions(File(fileName).readLines())
    val output = determineInputForOutput("ORE", ChemicalQty(1L, "FUEL"), formulae)
    println("Output = ORE = $output")
    require(output == 612880L) // ensure check for refactoring
    val fuel = determineOuputForInput(ChemicalQty(1000000000000L, "ORE"), "FUEL", formulae)
    println("Fuel = $fuel")
    require(fuel == 2509120L)
}

Compiled from "solution.kt"
public final class com.github.corneil.aoc2019.day14.SolutionKt {
  public static final kotlin.Pair<java.lang.Long, java.lang.String> readChemicalQty(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #10                 // String it
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/CharSequence
      10: invokestatic  #24                 // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      13: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
      16: checkcast     #18                 // class java/lang/CharSequence
      19: iconst_1
      20: anewarray     #30                 // class java/lang/String
      23: astore_2
      24: aload_2
      25: iconst_0
      26: ldc           #32                 // String
      28: aastore
      29: aload_2
      30: iconst_0
      31: iconst_0
      32: bipush        6
      34: aconst_null
      35: invokestatic  #36                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      38: astore_1
      39: aload_1
      40: invokeinterface #42,  1           // InterfaceMethod java/util/List.size:()I
      45: iconst_2
      46: if_icmpne     53
      49: iconst_1
      50: goto          54
      53: iconst_0
      54: ifne          72
      57: ldc           #44                 // String Failed requirement.
      59: astore_3
      60: new           #46                 // class java/lang/IllegalArgumentException
      63: dup
      64: aload_3
      65: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
      68: invokespecial #50                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      71: athrow
      72: new           #52                 // class kotlin/Pair
      75: dup
      76: aload_1
      77: iconst_0
      78: invokeinterface #56,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      83: checkcast     #30                 // class java/lang/String
      86: invokestatic  #62                 // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
      89: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      92: aload_1
      93: iconst_1
      94: invokeinterface #56,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      99: checkcast     #30                 // class java/lang/String
     102: checkcast     #18                 // class java/lang/CharSequence
     105: invokestatic  #24                 // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
     108: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
     111: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     114: areturn

  public static final com.github.corneil.aoc2019.day14.ReactionFormula readReaction(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #78                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: ldc           #80                 // String =>
       9: aconst_null
      10: iconst_2
      11: aconst_null
      12: invokestatic  #84                 // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      15: checkcast     #18                 // class java/lang/CharSequence
      18: iconst_1
      19: anewarray     #30                 // class java/lang/String
      22: astore_2
      23: aload_2
      24: iconst_0
      25: ldc           #86                 // String ,
      27: aastore
      28: aload_2
      29: iconst_0
      30: iconst_0
      31: bipush        6
      33: aconst_null
      34: invokestatic  #36                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      37: checkcast     #88                 // class java/lang/Iterable
      40: astore_2
      41: iconst_0
      42: istore_3
      43: aload_2
      44: astore        4
      46: new           #90                 // class java/util/ArrayList
      49: dup
      50: aload_2
      51: bipush        10
      53: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      56: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
      59: checkcast     #101                // class java/util/Collection
      62: astore        5
      64: iconst_0
      65: istore        6
      67: aload         4
      69: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      74: astore        7
      76: aload         7
      78: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      83: ifeq          126
      86: aload         7
      88: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      93: astore        8
      95: aload         5
      97: aload         8
      99: checkcast     #30                 // class java/lang/String
     102: astore        9
     104: astore        11
     106: iconst_0
     107: istore        10
     109: aload         9
     111: invokestatic  #117                // Method readChemicalQty:(Ljava/lang/String;)Lkotlin/Pair;
     114: aload         11
     116: swap
     117: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     122: pop
     123: goto          76
     126: aload         5
     128: checkcast     #38                 // class java/util/List
     131: nop
     132: astore_1
     133: new           #123                // class com/github/corneil/aoc2019/day14/ReactionFormula
     136: dup
     137: aload_1
     138: aload_0
     139: ldc           #80                 // String =>
     141: aconst_null
     142: iconst_2
     143: aconst_null
     144: invokestatic  #126                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     147: invokestatic  #117                // Method readChemicalQty:(Ljava/lang/String;)Lkotlin/Pair;
     150: invokespecial #129                // Method com/github/corneil/aoc2019/day14/ReactionFormula."<init>":(Ljava/util/List;Lkotlin/Pair;)V
     153: areturn

  public static final java.util.List<com.github.corneil.aoc2019.day14.ReactionFormula> readReactions(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #78                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #88                 // class java/lang/Iterable
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: astore_3
      15: new           #90                 // class java/util/ArrayList
      18: dup
      19: aload_1
      20: bipush        10
      22: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      25: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
      28: checkcast     #101                // class java/util/Collection
      31: astore        4
      33: iconst_0
      34: istore        5
      36: aload_3
      37: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      42: astore        6
      44: aload         6
      46: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      51: ifeq          94
      54: aload         6
      56: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      61: astore        7
      63: aload         4
      65: aload         7
      67: checkcast     #30                 // class java/lang/String
      70: astore        8
      72: astore        10
      74: iconst_0
      75: istore        9
      77: aload         8
      79: invokestatic  #146                // Method readReaction:(Ljava/lang/String;)Lcom/github/corneil/aoc2019/day14/ReactionFormula;
      82: aload         10
      84: swap
      85: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      90: pop
      91: goto          44
      94: aload         4
      96: checkcast     #38                 // class java/util/List
      99: nop
     100: areturn

  public static final void add(java.util.Map<java.lang.String, java.lang.Long>, kotlin.Pair<java.lang.Long, java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #151                // String value
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #153                // String output
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      17: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      22: checkcast     #58                 // class java/lang/Long
      25: astore_2
      26: aload_2
      27: ifnull        62
      30: aload_0
      31: aload_1
      32: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      35: aload_2
      36: invokevirtual #165                // Method java/lang/Long.longValue:()J
      39: aload_1
      40: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      43: checkcast     #170                // class java/lang/Number
      46: invokevirtual #171                // Method java/lang/Number.longValue:()J
      49: ladd
      50: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      53: invokeinterface #175,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      58: pop
      59: goto          77
      62: aload_0
      63: aload_1
      64: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      67: aload_1
      68: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      71: invokeinterface #175,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      76: pop
      77: return

  public static final void produce(kotlin.Pair<java.lang.Long, java.lang.String>, java.util.Map<java.lang.String, com.github.corneil.aoc2019.day14.ReactionFormula>, java.util.Map<java.lang.String, java.lang.Long>, java.util.Map<java.lang.String, java.lang.Long>);
    Code:
       0: aload_0
       1: ldc           #153                // String output
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #184                // String formulae
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_2
      13: ldc           #186                // String sideEffect
      15: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_3
      19: ldc           #188                // String used
      21: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      24: aload_2
      25: aload_0
      26: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      29: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      34: checkcast     #58                 // class java/lang/Long
      37: astore        4
      39: aload         4
      41: ifnull        69
      44: aload         4
      46: invokevirtual #165                // Method java/lang/Long.longValue:()J
      49: lconst_0
      50: lcmp
      51: ifle          69
      54: aload         4
      56: invokevirtual #165                // Method java/lang/Long.longValue:()J
      59: aload_0
      60: aload_1
      61: aload_2
      62: aload_3
      63: invokestatic  #192                // Method useRemainingChemicals:(JLkotlin/Pair;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
      66: goto          106
      69: aload_1
      70: aload_0
      71: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      74: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      79: checkcast     #123                // class com/github/corneil/aoc2019/day14/ReactionFormula
      82: astore        5
      84: aload         5
      86: ifnull        101
      89: aload_0
      90: aload         5
      92: aload_1
      93: aload_2
      94: aload_3
      95: invokestatic  #196                // Method applyFormula:(Lkotlin/Pair;Lcom/github/corneil/aoc2019/day14/ReactionFormula;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
      98: goto          106
     101: aload_3
     102: aload_0
     103: invokestatic  #198                // Method add:(Ljava/util/Map;Lkotlin/Pair;)V
     106: return

  public static final void useRemainingChemicals(long, kotlin.Pair<java.lang.Long, java.lang.String>, java.util.Map<java.lang.String, com.github.corneil.aoc2019.day14.ReactionFormula>, java.util.Map<java.lang.String, java.lang.Long>, java.util.Map<java.lang.String, java.lang.Long>);
    Code:
       0: aload_2
       1: ldc           #153                // String output
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_3
       7: ldc           #184                // String formulae
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload         4
      14: ldc           #186                // String sideEffect
      16: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      19: aload         5
      21: ldc           #188                // String used
      23: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      26: lload_0
      27: aload_2
      28: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      31: checkcast     #170                // class java/lang/Number
      34: invokevirtual #171                // Method java/lang/Number.longValue:()J
      37: lcmp
      38: iflt          144
      41: lload_0
      42: aload_2
      43: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      46: checkcast     #170                // class java/lang/Number
      49: invokevirtual #171                // Method java/lang/Number.longValue:()J
      52: lsub
      53: lstore        6
      55: lload         6
      57: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      60: astore        9
      62: aload         4
      64: aload_2
      65: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      68: aload         9
      70: invokeinterface #175,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      75: pop
      76: lload         6
      78: lconst_0
      79: lcmp
      80: iflt          87
      83: iconst_1
      84: goto          88
      87: iconst_0
      88: ifne          190
      91: iconst_0
      92: istore        8
      94: new           #204                // class java/lang/StringBuilder
      97: dup
      98: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     101: ldc           #209                // String Expected Qty to be zero or greater for
     103: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     106: aload_2
     107: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     110: checkcast     #30                 // class java/lang/String
     113: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     116: ldc           #215                // String  not
     118: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     121: lload         6
     123: invokevirtual #218                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     126: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     129: astore        8
     131: new           #46                 // class java/lang/IllegalArgumentException
     134: dup
     135: aload         8
     137: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
     140: invokespecial #50                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
     143: athrow
     144: aload         4
     146: aload_2
     147: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     150: invokeinterface #222,  2          // InterfaceMethod java/util/Map.remove:(Ljava/lang/Object;)Ljava/lang/Object;
     155: pop
     156: new           #52                 // class kotlin/Pair
     159: dup
     160: aload_2
     161: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     164: checkcast     #170                // class java/lang/Number
     167: invokevirtual #171                // Method java/lang/Number.longValue:()J
     170: lload_0
     171: lsub
     172: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     175: aload_2
     176: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     179: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     182: aload_3
     183: aload         4
     185: aload         5
     187: invokestatic  #224                // Method produce:(Lkotlin/Pair;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
     190: return

  public static final void applyFormula(kotlin.Pair<java.lang.Long, java.lang.String>, com.github.corneil.aoc2019.day14.ReactionFormula, java.util.Map<java.lang.String, com.github.corneil.aoc2019.day14.ReactionFormula>, java.util.Map<java.lang.String, java.lang.Long>, java.util.Map<java.lang.String, java.lang.Long>);
    Code:
       0: aload_0
       1: ldc           #153                // String output
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #228                // String formula
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_2
      13: ldc           #184                // String formulae
      15: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_3
      19: ldc           #186                // String sideEffect
      21: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      24: aload         4
      26: ldc           #188                // String used
      28: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      31: aload_0
      32: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      35: checkcast     #170                // class java/lang/Number
      38: invokevirtual #171                // Method java/lang/Number.longValue:()J
      41: aload_1
      42: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
      45: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      48: checkcast     #170                // class java/lang/Number
      51: invokevirtual #171                // Method java/lang/Number.longValue:()J
      54: lcmp
      55: ifge          62
      58: lconst_1
      59: goto          121
      62: aload_0
      63: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      66: checkcast     #170                // class java/lang/Number
      69: invokevirtual #171                // Method java/lang/Number.longValue:()J
      72: aload_1
      73: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
      76: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      79: checkcast     #170                // class java/lang/Number
      82: invokevirtual #171                // Method java/lang/Number.longValue:()J
      85: ldiv
      86: aload_0
      87: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      90: checkcast     #170                // class java/lang/Number
      93: invokevirtual #171                // Method java/lang/Number.longValue:()J
      96: aload_1
      97: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
     100: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     103: checkcast     #170                // class java/lang/Number
     106: invokevirtual #171                // Method java/lang/Number.longValue:()J
     109: lrem
     110: lconst_0
     111: lcmp
     112: ifne          119
     115: lconst_0
     116: goto          120
     119: lconst_1
     120: ladd
     121: lstore        5
     123: aload_1
     124: lload         5
     126: aload_2
     127: aload_3
     128: aload         4
     130: invokestatic  #236                // Method apply:(Lcom/github/corneil/aoc2019/day14/ReactionFormula;JLjava/util/Map;Ljava/util/Map;Ljava/util/Map;)Lkotlin/Pair;
     133: astore        7
     135: aload_0
     136: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     139: checkcast     #170                // class java/lang/Number
     142: invokevirtual #171                // Method java/lang/Number.longValue:()J
     145: aload         7
     147: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     150: checkcast     #170                // class java/lang/Number
     153: invokevirtual #171                // Method java/lang/Number.longValue:()J
     156: lcmp
     157: ifge          196
     160: aload_3
     161: aload_0
     162: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     165: aload         7
     167: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     170: checkcast     #170                // class java/lang/Number
     173: invokevirtual #171                // Method java/lang/Number.longValue:()J
     176: aload_0
     177: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     180: checkcast     #170                // class java/lang/Number
     183: invokevirtual #171                // Method java/lang/Number.longValue:()J
     186: lsub
     187: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     190: invokeinterface #175,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     195: pop
     196: return

  public static final kotlin.Pair<java.lang.Long, java.lang.String> apply(com.github.corneil.aoc2019.day14.ReactionFormula, long, java.util.Map<java.lang.String, com.github.corneil.aoc2019.day14.ReactionFormula>, java.util.Map<java.lang.String, java.lang.Long>, java.util.Map<java.lang.String, java.lang.Long>);
    Code:
       0: aload_0
       1: ldc           #228                // String formula
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_3
       7: ldc           #184                // String formulae
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload         4
      14: ldc           #186                // String sideEffect
      16: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      19: aload         5
      21: ldc           #188                // String used
      23: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      26: aload_0
      27: invokevirtual #243                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getInputs:()Ljava/util/List;
      30: checkcast     #88                 // class java/lang/Iterable
      33: astore        6
      35: iconst_0
      36: istore        7
      38: aload         6
      40: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      45: astore        8
      47: aload         8
      49: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      54: ifeq          117
      57: aload         8
      59: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      64: astore        9
      66: aload         9
      68: checkcast     #52                 // class kotlin/Pair
      71: astore        10
      73: iconst_0
      74: istore        11
      76: new           #52                 // class kotlin/Pair
      79: dup
      80: aload         10
      82: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      85: checkcast     #170                // class java/lang/Number
      88: invokevirtual #171                // Method java/lang/Number.longValue:()J
      91: lload_1
      92: lmul
      93: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      96: aload         10
      98: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     101: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     104: aload_3
     105: aload         4
     107: aload         5
     109: invokestatic  #224                // Method produce:(Lkotlin/Pair;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
     112: nop
     113: nop
     114: goto          47
     117: nop
     118: new           #52                 // class kotlin/Pair
     121: dup
     122: aload_0
     123: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
     126: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     129: checkcast     #170                // class java/lang/Number
     132: invokevirtual #171                // Method java/lang/Number.longValue:()J
     135: lload_1
     136: lmul
     137: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     140: aload_0
     141: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
     144: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     147: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     150: areturn

  public static final long determineInputForOutput(java.lang.String, kotlin.Pair<java.lang.Long, java.lang.String>, java.util.List<com.github.corneil.aoc2019.day14.ReactionFormula>);
    Code:
       0: aload_0
       1: ldc           #78                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #153                // String output
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_2
      13: ldc           #184                // String formulae
      15: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_2
      19: checkcast     #88                 // class java/lang/Iterable
      22: astore        4
      24: iconst_0
      25: istore        5
      27: aload         4
      29: astore        6
      31: new           #90                 // class java/util/ArrayList
      34: dup
      35: aload         4
      37: bipush        10
      39: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      42: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
      45: checkcast     #101                // class java/util/Collection
      48: astore        7
      50: iconst_0
      51: istore        8
      53: aload         6
      55: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      60: astore        9
      62: aload         9
      64: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      69: ifeq          120
      72: aload         9
      74: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      79: astore        10
      81: aload         7
      83: aload         10
      85: checkcast     #123                // class com/github/corneil/aoc2019/day14/ReactionFormula
      88: astore        11
      90: astore        13
      92: iconst_0
      93: istore        12
      95: aload         11
      97: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
     100: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     103: aload         11
     105: invokestatic  #256                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     108: aload         13
     110: swap
     111: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     116: pop
     117: goto          62
     120: aload         7
     122: checkcast     #38                 // class java/util/List
     125: nop
     126: checkcast     #88                 // class java/lang/Iterable
     129: invokestatic  #262                // Method kotlin/collections/MapsKt.toMap:(Ljava/lang/Iterable;)Ljava/util/Map;
     132: astore_3
     133: new           #264                // class java/util/LinkedHashMap
     136: dup
     137: invokespecial #265                // Method java/util/LinkedHashMap."<init>":()V
     140: checkcast     #158                // class java/util/Map
     143: astore        4
     145: new           #264                // class java/util/LinkedHashMap
     148: dup
     149: invokespecial #265                // Method java/util/LinkedHashMap."<init>":()V
     152: checkcast     #158                // class java/util/Map
     155: astore        5
     157: aload_1
     158: aload_3
     159: aload         5
     161: aload         4
     163: invokestatic  #224                // Method produce:(Lkotlin/Pair;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
     166: new           #204                // class java/lang/StringBuilder
     169: dup
     170: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     173: aload_1
     174: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     177: ldc_w         #270                // String  =
     180: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     183: aload         4
     185: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     188: ldc_w         #272                // String , Side Effects =
     191: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     194: aload         5
     196: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     199: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     202: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
     205: swap
     206: invokevirtual #284                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     209: aload         4
     211: aload_0
     212: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     217: checkcast     #58                 // class java/lang/Long
     220: dup
     221: ifnull        230
     224: invokevirtual #165                // Method java/lang/Long.longValue:()J
     227: goto          232
     230: pop
     231: lconst_0
     232: lreturn

  public static final kotlin.Pair<java.lang.Long, java.lang.Long> executeReactions(long, kotlin.Pair<java.lang.Long, java.lang.String>, java.lang.String, java.util.Map<java.lang.String, com.github.corneil.aoc2019.day14.ReactionFormula>, java.util.Map<java.lang.String, java.lang.Long>);
    Code:
       0: aload_2
       1: ldc           #78                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_3
       7: ldc           #153                // String output
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload         4
      14: ldc           #228                // String formula
      16: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      19: aload         5
      21: ldc           #188                // String used
      23: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      26: new           #264                // class java/util/LinkedHashMap
      29: dup
      30: invokespecial #265                // Method java/util/LinkedHashMap."<init>":()V
      33: checkcast     #158                // class java/util/Map
      36: astore        6
      38: lload_0
      39: lstore        7
      41: lconst_0
      42: lstore        9
      44: aload_2
      45: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      48: checkcast     #170                // class java/lang/Number
      51: invokevirtual #171                // Method java/lang/Number.longValue:()J
      54: aload         5
      56: aload_2
      57: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      60: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      65: checkcast     #58                 // class java/lang/Long
      68: dup
      69: ifnull        78
      72: invokevirtual #165                // Method java/lang/Long.longValue:()J
      75: goto          80
      78: pop
      79: lconst_0
      80: lcmp
      81: ifle          285
      84: new           #52                 // class kotlin/Pair
      87: dup
      88: lload         7
      90: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      93: aload_3
      94: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      97: aload         4
      99: aload         6
     101: aload         5
     103: invokestatic  #224                // Method produce:(Lkotlin/Pair;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;)V
     106: lload         9
     108: lload         7
     110: ladd
     111: lstore        9
     113: lload         9
     115: ldc2_w        #289                // long 10000l
     118: lrem
     119: lconst_0
     120: lcmp
     121: ifne          177
     124: new           #204                // class java/lang/StringBuilder
     127: dup
     128: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     131: ldc_w         #292                // String produce
     134: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     137: aload_3
     138: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     141: ldc_w         #294                // String  for
     144: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     147: aload_2
     148: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     151: ldc_w         #270                // String  =
     154: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     157: lload         9
     159: invokevirtual #218                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     162: bipush        13
     164: invokevirtual #297                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     167: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     170: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
     173: swap
     174: invokevirtual #300                // Method java/io/PrintStream.print:(Ljava/lang/Object;)V
     177: aload         5
     179: aload_2
     180: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     183: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     188: checkcast     #58                 // class java/lang/Long
     191: dup
     192: ifnull        201
     195: invokevirtual #165                // Method java/lang/Long.longValue:()J
     198: goto          203
     201: pop
     202: lconst_0
     203: lstore        11
     205: lload         7
     207: ldc2_w        #301                // long 100l
     210: lcmp
     211: ifne          246
     214: ldc2_w        #303                // long 10l
     217: lload         11
     219: lmul
     220: aload_2
     221: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     224: checkcast     #170                // class java/lang/Number
     227: invokevirtual #171                // Method java/lang/Number.longValue:()J
     230: ldiv
     231: ldc2_w        #305                // long 7l
     234: lcmp
     235: ifle          246
     238: ldc2_w        #303                // long 10l
     241: lstore        7
     243: goto          44
     246: lload         7
     248: ldc2_w        #303                // long 10l
     251: lcmp
     252: ifne          44
     255: ldc2_w        #303                // long 10l
     258: lload         11
     260: lmul
     261: aload_2
     262: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     265: checkcast     #170                // class java/lang/Number
     268: invokevirtual #171                // Method java/lang/Number.longValue:()J
     271: ldiv
     272: ldc2_w        #307                // long 8l
     275: lcmp
     276: ifle          44
     279: lconst_1
     280: lstore        7
     282: goto          44
     285: new           #204                // class java/lang/StringBuilder
     288: dup
     289: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     292: ldc_w         #310                // String Used =
     295: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     298: aload         5
     300: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     303: ldc_w         #312                // String , Side Effect =
     306: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     309: aload         6
     311: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     314: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     317: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
     320: swap
     321: invokevirtual #284                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     324: new           #52                 // class kotlin/Pair
     327: dup
     328: lload         9
     330: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     333: lload         7
     335: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     338: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     341: areturn

  public static final long determineOuputForInput(kotlin.Pair<java.lang.Long, java.lang.String>, java.lang.String, java.util.List<com.github.corneil.aoc2019.day14.ReactionFormula>);
    Code:
       0: aload_0
       1: ldc           #78                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #153                // String output
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_2
      13: ldc           #184                // String formulae
      15: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_2
      19: checkcast     #88                 // class java/lang/Iterable
      22: astore        4
      24: iconst_0
      25: istore        5
      27: aload         4
      29: astore        6
      31: new           #90                 // class java/util/ArrayList
      34: dup
      35: aload         4
      37: bipush        10
      39: invokestatic  #96                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      42: invokespecial #99                 // Method java/util/ArrayList."<init>":(I)V
      45: checkcast     #101                // class java/util/Collection
      48: astore        7
      50: iconst_0
      51: istore        8
      53: aload         6
      55: invokeinterface #105,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      60: astore        9
      62: aload         9
      64: invokeinterface #111,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      69: ifeq          120
      72: aload         9
      74: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      79: astore        10
      81: aload         7
      83: aload         10
      85: checkcast     #123                // class com/github/corneil/aoc2019/day14/ReactionFormula
      88: astore        11
      90: astore        13
      92: iconst_0
      93: istore        12
      95: aload         11
      97: invokevirtual #232                // Method com/github/corneil/aoc2019/day14/ReactionFormula.getOutput:()Lkotlin/Pair;
     100: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     103: aload         11
     105: invokestatic  #256                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     108: aload         13
     110: swap
     111: invokeinterface #121,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     116: pop
     117: goto          62
     120: aload         7
     122: checkcast     #38                 // class java/util/List
     125: nop
     126: checkcast     #88                 // class java/lang/Iterable
     129: invokestatic  #262                // Method kotlin/collections/MapsKt.toMap:(Ljava/lang/Iterable;)Ljava/util/Map;
     132: astore_3
     133: new           #264                // class java/util/LinkedHashMap
     136: dup
     137: invokespecial #265                // Method java/util/LinkedHashMap."<init>":()V
     140: checkcast     #158                // class java/util/Map
     143: astore        4
     145: ldc2_w        #320                // long 1000l
     148: lstore        5
     150: lconst_0
     151: lstore        7
     153: lload         5
     155: ldc2_w        #303                // long 10l
     158: ldiv
     159: lstore        5
     161: lload         5
     163: aload_0
     164: aload_1
     165: aload_3
     166: aload         4
     168: invokestatic  #323                // Method executeReactions:(JLkotlin/Pair;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lkotlin/Pair;
     171: astore        9
     173: aload         9
     175: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     178: checkcast     #170                // class java/lang/Number
     181: invokevirtual #171                // Method java/lang/Number.longValue:()J
     184: lstore        7
     186: aload         9
     188: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     191: checkcast     #170                // class java/lang/Number
     194: invokevirtual #171                // Method java/lang/Number.longValue:()J
     197: lstore        5
     199: lload         5
     201: lconst_1
     202: lcmp
     203: ifgt          153
     206: aload         4
     208: aload_0
     209: invokevirtual #156                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     212: invokeinterface #161,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     217: checkcast     #58                 // class java/lang/Long
     220: aload_0
     221: invokevirtual #168                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     224: checkcast     #170                // class java/lang/Number
     227: invokevirtual #171                // Method java/lang/Number.longValue:()J
     230: lstore        11
     232: dup
     233: ifnonnull     240
     236: pop
     237: goto          254
     240: invokevirtual #165                // Method java/lang/Long.longValue:()J
     243: lload         11
     245: lcmp
     246: ifne          254
     249: lload         7
     251: goto          258
     254: lload         7
     256: lconst_1
     257: lsub
     258: lstore        9
     260: new           #204                // class java/lang/StringBuilder
     263: dup
     264: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     267: ldc_w         #325                // String output
     270: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     273: aload_0
     274: invokevirtual #268                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     277: ldc_w         #270                // String  =
     280: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     283: lload         9
     285: invokevirtual #218                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     288: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     291: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
     294: swap
     295: invokevirtual #284                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     298: lload         9
     300: lreturn

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc_w         #332                // String args
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: arraylength
       9: iconst_1
      10: if_icmple     19
      13: aload_0
      14: iconst_0
      15: aaload
      16: goto          22
      19: ldc_w         #334                // String input.txt
      22: astore_1
      23: new           #336                // class java/io/File
      26: dup
      27: aload_1
      28: invokespecial #337                // Method java/io/File."<init>":(Ljava/lang/String;)V
      31: aconst_null
      32: iconst_1
      33: aconst_null
      34: invokestatic  #343                // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      37: invokestatic  #345                // Method readReactions:(Ljava/util/List;)Ljava/util/List;
      40: astore_2
      41: ldc_w         #347                // String ORE
      44: new           #52                 // class kotlin/Pair
      47: dup
      48: lconst_1
      49: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      52: ldc_w         #349                // String FUEL
      55: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      58: aload_2
      59: invokestatic  #351                // Method determineInputForOutput:(Ljava/lang/String;Lkotlin/Pair;Ljava/util/List;)J
      62: lstore_3
      63: new           #204                // class java/lang/StringBuilder
      66: dup
      67: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
      70: ldc_w         #353                // String Output = ORE =
      73: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      76: lload_3
      77: invokevirtual #218                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      80: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      83: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
      86: swap
      87: invokevirtual #284                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      90: lload_3
      91: ldc2_w        #354                // long 612880l
      94: lcmp
      95: ifne          102
      98: iconst_1
      99: goto          103
     102: iconst_0
     103: ifne          123
     106: ldc           #44                 // String Failed requirement.
     108: astore        6
     110: new           #46                 // class java/lang/IllegalArgumentException
     113: dup
     114: aload         6
     116: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
     119: invokespecial #50                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
     122: athrow
     123: new           #52                 // class kotlin/Pair
     126: dup
     127: ldc2_w        #356                // long 1000000000000l
     130: invokestatic  #66                 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     133: ldc_w         #347                // String ORE
     136: invokespecial #69                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     139: ldc_w         #349                // String FUEL
     142: aload_2
     143: invokestatic  #359                // Method determineOuputForInput:(Lkotlin/Pair;Ljava/lang/String;Ljava/util/List;)J
     146: lstore        5
     148: new           #204                // class java/lang/StringBuilder
     151: dup
     152: invokespecial #207                // Method java/lang/StringBuilder."<init>":()V
     155: ldc_w         #361                // String Fuel =
     158: invokevirtual #213                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     161: lload         5
     163: invokevirtual #218                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     166: invokevirtual #219                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     169: getstatic     #278                // Field java/lang/System.out:Ljava/io/PrintStream;
     172: swap
     173: invokevirtual #284                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     176: lload         5
     178: ldc2_w        #362                // long 2509120l
     181: lcmp
     182: ifne          189
     185: iconst_1
     186: goto          190
     189: iconst_0
     190: ifne          210
     193: ldc           #44                 // String Failed requirement.
     195: astore        7
     197: new           #46                 // class java/lang/IllegalArgumentException
     200: dup
     201: aload         7
     203: invokevirtual #28                 // Method java/lang/Object.toString:()Ljava/lang/String;
     206: invokespecial #50                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
     209: athrow
     210: return
}


package ru.amai.study.hackerrank.practice.interviewPreparationKit.strings.special

import java.lang.Integer.max
import java.util.*

fun subStrCount(string: String): Long =
    cntSubstringsWithSameChars(string) + cntSubstringsWithSameCharsExceptMiddle(string)

private fun cntSubstringsWithSameCharsExceptMiddle(string: String): Long {

    fun withinBounds(index: Int, offset: Int): Boolean =
        ((index - offset) >= 0) && ((index + offset) < string.length)

    fun substringIsValid(currChar: Char, index: Int, offset: Int): Boolean =
        if (withinBounds(index, offset)) {
            val lChar = string[index - offset]
            val rChar = string[index + offset]

            (lChar == currChar) && (rChar == currChar)
        } else false

    var substringCnt = 0L
    var index = 1
    while (index < string.length - 1) {

        val currChar = string[index - 1]
        if (string[index] == currChar) {
            index++
            continue
        }

        val offset = generateSequence(1) { it + 1 }
            .takeWhile { offset -> substringIsValid(currChar, index, offset) }
            .count()

        substringCnt += offset
        index += max(offset, 1)
    }

    return substringCnt
}

private fun cntSubstringsWithSameChars(string: String): Long =
    string.drop(1).fold(CharCounterHolder(string.first())) { counter, char ->
        if (char == counter.char) counter.increment()
        else counter.switchChar(char)
    }.countValue()

private data class CharCounterHolder(
    val char: Char,
    val currentCount: Long = 1L,
    val partialResult: Long = 0
) {
    fun increment(): CharCounterHolder =
        copy(currentCount = currentCount + 1)

    fun switchChar(char: Char) =
        CharCounterHolder(char = char, partialResult = countValue())

    fun countValue() = partialResult + (currentCount * (currentCount + 1) / 2)
}

fun main() {
    val scan = Scanner(System.`in`)

    scan.nextLine()
    val s = scan.nextLine()

    val result = subStrCount(s)
    println(result)
}

Compiled from "SubstrCount.kt"
public final class ru.amai.study.hackerrank.practice.interviewPreparationKit.strings.special.SubstrCountKt {
  public static final long subStrCount(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #9                  // String string
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #18                 // Method cntSubstringsWithSameChars:(Ljava/lang/String;)J
      10: aload_0
      11: invokestatic  #21                 // Method cntSubstringsWithSameCharsExceptMiddle:(Ljava/lang/String;)J
      14: ladd
      15: lreturn

  private static final long cntSubstringsWithSameCharsExceptMiddle(java.lang.String);
    Code:
       0: lconst_0
       1: lstore_1
       2: new           #24                 // class kotlin/jvm/internal/Ref$IntRef
       5: dup
       6: invokespecial #28                 // Method kotlin/jvm/internal/Ref$IntRef."<init>":()V
       9: astore_3
      10: aload_3
      11: iconst_1
      12: putfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      15: aload_3
      16: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      19: aload_0
      20: invokevirtual #38                 // Method java/lang/String.length:()I
      23: iconst_1
      24: isub
      25: if_icmpge     123
      28: aload_0
      29: aload_3
      30: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      33: iconst_1
      34: isub
      35: invokevirtual #42                 // Method java/lang/String.charAt:(I)C
      38: istore        4
      40: aload_0
      41: aload_3
      42: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      45: invokevirtual #42                 // Method java/lang/String.charAt:(I)C
      48: iload         4
      50: if_icmpne     70
      53: aload_3
      54: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      57: istore        5
      59: aload_3
      60: iload         5
      62: iconst_1
      63: iadd
      64: putfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
      67: goto          15
      70: iconst_1
      71: invokestatic  #48                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      74: invokedynamic #67,  0             // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
      79: invokestatic  #73                 // Method kotlin/sequences/SequencesKt.generateSequence:(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      82: iload         4
      84: aload_3
      85: aload_0
      86: invokedynamic #83,  0             // InvokeDynamic #1:invoke:(CLkotlin/jvm/internal/Ref$IntRef;Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
      91: invokestatic  #87                 // Method kotlin/sequences/SequencesKt.takeWhile:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      94: invokestatic  #91                 // Method kotlin/sequences/SequencesKt.count:(Lkotlin/sequences/Sequence;)I
      97: istore        5
      99: lload_1
     100: iload         5
     102: i2l
     103: ladd
     104: lstore_1
     105: aload_3
     106: aload_3
     107: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
     110: iload         5
     112: iconst_1
     113: invokestatic  #95                 // Method java/lang/Integer.max:(II)I
     116: iadd
     117: putfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
     120: goto          15
     123: lload_1
     124: lreturn

  private static final long cntSubstringsWithSameChars(java.lang.String);
    Code:
       0: aload_0
       1: iconst_1
       2: invokestatic  #108                // Method kotlin/text/StringsKt.drop:(Ljava/lang/String;I)Ljava/lang/String;
       5: checkcast     #110                // class java/lang/CharSequence
       8: astore_1
       9: new           #112                // class ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder
      12: dup
      13: aload_0
      14: checkcast     #110                // class java/lang/CharSequence
      17: invokestatic  #116                // Method kotlin/text/StringsKt.first:(Ljava/lang/CharSequence;)C
      20: lconst_0
      21: lconst_0
      22: bipush        6
      24: aconst_null
      25: invokespecial #119                // Method ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder."<init>":(CJJILkotlin/jvm/internal/DefaultConstructorMarker;)V
      28: astore_2
      29: iconst_0
      30: istore_3
      31: aload_2
      32: astore        4
      34: iconst_0
      35: istore        5
      37: iload         5
      39: aload_1
      40: invokeinterface #120,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      45: if_icmpge     102
      48: aload_1
      49: iload         5
      51: invokeinterface #121,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      56: istore        6
      58: aload         4
      60: iload         6
      62: istore        7
      64: astore        8
      66: iconst_0
      67: istore        9
      69: iload         7
      71: aload         8
      73: invokevirtual #125                // Method ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder.getChar:()C
      76: if_icmpne     87
      79: aload         8
      81: invokevirtual #129                // Method ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder.increment:()Lru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder;
      84: goto          94
      87: aload         8
      89: iload         7
      91: invokevirtual #133                // Method ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder.switchChar:(C)Lru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder;
      94: astore        4
      96: iinc          5, 1
      99: goto          37
     102: aload         4
     104: invokevirtual #137                // Method ru/amai/study/hackerrank/practice/interviewPreparationKit/strings/special/CharCounterHolder.countValue:()J
     107: lreturn

  public static final void main();
    Code:
       0: new           #151                // class java/util/Scanner
       3: dup
       4: getstatic     #157                // Field java/lang/System.in:Ljava/io/InputStream;
       7: invokespecial #160                // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
      10: astore_0
      11: aload_0
      12: invokevirtual #164                // Method java/util/Scanner.nextLine:()Ljava/lang/String;
      15: pop
      16: aload_0
      17: invokevirtual #164                // Method java/util/Scanner.nextLine:()Ljava/lang/String;
      20: astore_1
      21: aload_1
      22: invokestatic  #168                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      25: aload_1
      26: invokestatic  #170                // Method subStrCount:(Ljava/lang/String;)J
      29: lstore_2
      30: getstatic     #174                // Field java/lang/System.out:Ljava/io/PrintStream;
      33: lload_2
      34: invokevirtual #180                // Method java/io/PrintStream.println:(J)V
      37: return

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

  private static final boolean cntSubstringsWithSameCharsExceptMiddle$withinBounds(java.lang.String, int, int);
    Code:
       0: iload_1
       1: iload_2
       2: isub
       3: iflt          20
       6: iload_1
       7: iload_2
       8: iadd
       9: aload_0
      10: invokevirtual #38                 // Method java/lang/String.length:()I
      13: if_icmpge     20
      16: iconst_1
      17: goto          21
      20: iconst_0
      21: ireturn

  private static final boolean cntSubstringsWithSameCharsExceptMiddle$substringIsValid(java.lang.String, char, int, int);
    Code:
       0: aload_0
       1: iload_2
       2: iload_3
       3: invokestatic  #196                // Method cntSubstringsWithSameCharsExceptMiddle$withinBounds:(Ljava/lang/String;II)Z
       6: ifeq          47
       9: aload_0
      10: iload_2
      11: iload_3
      12: isub
      13: invokevirtual #42                 // Method java/lang/String.charAt:(I)C
      16: istore        4
      18: aload_0
      19: iload_2
      20: iload_3
      21: iadd
      22: invokevirtual #42                 // Method java/lang/String.charAt:(I)C
      25: istore        5
      27: iload         4
      29: iload_1
      30: if_icmpne     43
      33: iload         5
      35: iload_1
      36: if_icmpne     43
      39: iconst_1
      40: goto          48
      43: iconst_0
      44: goto          48
      47: iconst_0
      48: ireturn

  private static final java.lang.Integer cntSubstringsWithSameCharsExceptMiddle$lambda$0(int);
    Code:
       0: iload_0
       1: iconst_1
       2: iadd
       3: invokestatic  #48                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: areturn

  private static final boolean cntSubstringsWithSameCharsExceptMiddle$lambda$1(char, kotlin.jvm.internal.Ref$IntRef, java.lang.String, int);
    Code:
       0: aload_2
       1: iload_0
       2: aload_1
       3: getfield      #32                 // Field kotlin/jvm/internal/Ref$IntRef.element:I
       6: iload_3
       7: invokestatic  #201                // Method cntSubstringsWithSameCharsExceptMiddle$substringIsValid:(Ljava/lang/String;CII)Z
      10: ireturn
}