package problems.day8.part2

import java.io.File

//private const val test3 = "input/day8/test3.txt"
private const val inputFile = "input/day8/input.txt"

fun main() {
    val stepsCount = File(inputFile).bufferedReader().useLines { numSteps(it) }
    println("Number of steps $stepsCount")
}

private fun numSteps(lines: Sequence<String>): Long {
    val (instructions, rules) = lines.fold(RuleSetBuilder()) { builder, line -> builder.nextLine(line) }.build()
    val startingLocations = rules.keys.filter { it.endsWith("A") }
    val cycleLengths = startingLocations.map { cycleLength(it, instructions.copy(), rules) }.map { it.toLong() }
    return leastCommonMultiple(cycleLengths)
}

private fun cycleLength(startPos: String, instructions: Instructions, rules: Map<String, Rule>): Int {
    var currentLocation = startPos
    while (!currentLocation.endsWith("Z")) {
        val nextDirection = instructions.next()
        val nextRule = rules[currentLocation] ?: throw IllegalArgumentException("No such location: $currentLocation")
        currentLocation =
            if (nextDirection == 'L') {
                nextRule.left
            } else {
                nextRule.right
            }
    }

    return instructions.directionCount
}

private fun leastCommonMultiple(numbers: List<Long>): Long =
    numbers.reduce { a, b -> leastCommonMultipleOfPair(a, b) }

private fun leastCommonMultipleOfPair(a: Long, b: Long): Long =
    (a * b) / greatestCommonDivisor(a, b)

private fun greatestCommonDivisor(a: Long, b: Long): Long = when {
    a == 0L -> b
    b == 0L -> a
    a > b -> greatestCommonDivisor(a % b, b)
    else -> greatestCommonDivisor(a, b % a)
}

private class Instructions(val directions: String) : Iterator<Char> {
    var directionCount = 0
    override fun hasNext() = true

    override fun next(): Char {
        val next = directions[directionCount % directions.count()]
        directionCount++
        return next
    }

    fun copy() = Instructions(this.directions)
}

private data class Rule(val left: String, val right: String)

private fun String.toRule(): Rule {
    val left = this.substringBefore(", ").trimStart { it == '(' }
    val right = this.substringAfter(", ").trimEnd { it == ')' }
    return Rule(left, right)
}

private data class ParseResult(val instructions: Instructions, val rules: Map<String, Rule>)

private class RuleSetBuilder {
    private var state = State.INSTRUCTIONS
    private var instructions: Instructions? = null
    private val rules = mutableMapOf<String, Rule>()

    private enum class State {
        INSTRUCTIONS,
        BLANK,
        RULES,
    }

    fun nextLine(line: String): RuleSetBuilder {
        when (state) {
            State.INSTRUCTIONS -> {
                instructions = Instructions(line)
                state = State.BLANK
            }

            State.BLANK -> {
                state = State.RULES
            }

            State.RULES -> {
                rules[line.substringBefore(" =")] = line.substringAfter("= ").toRule()
            }

        }
        return this
    }

    fun build() = ParseResult(
        instructions ?: throw IllegalArgumentException("missing instructions"),
        rules
    )
}

Compiled from "part2.kt"
public final class problems.day8.part2.Part2Kt {
  private static final java.lang.String inputFile;

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day8/input.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_2
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_3
      14: sipush        8192
      17: istore        4
      19: aload_2
      20: astore        5
      22: new           #24                 // class java/io/InputStreamReader
      25: dup
      26: new           #26                 // class java/io/FileInputStream
      29: dup
      30: aload         5
      32: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      35: checkcast     #31                 // class java/io/InputStream
      38: aload_3
      39: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      42: checkcast     #36                 // class java/io/Reader
      45: astore        5
      47: aload         5
      49: instanceof    #38                 // class java/io/BufferedReader
      52: ifeq          63
      55: aload         5
      57: checkcast     #38                 // class java/io/BufferedReader
      60: goto          74
      63: new           #38                 // class java/io/BufferedReader
      66: dup
      67: aload         5
      69: iload         4
      71: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      74: checkcast     #36                 // class java/io/Reader
      77: astore_2
      78: nop
      79: iconst_0
      80: istore_3
      81: aload_2
      82: astore        4
      84: sipush        8192
      87: istore        5
      89: aload         4
      91: instanceof    #38                 // class java/io/BufferedReader
      94: ifeq          105
      97: aload         4
      99: checkcast     #38                 // class java/io/BufferedReader
     102: goto          116
     105: new           #38                 // class java/io/BufferedReader
     108: dup
     109: aload         4
     111: iload         5
     113: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     116: checkcast     #43                 // class java/io/Closeable
     119: astore        4
     121: aconst_null
     122: astore        5
     124: nop
     125: aload         4
     127: checkcast     #38                 // class java/io/BufferedReader
     130: astore        6
     132: iconst_0
     133: istore        8
     135: aload         6
     137: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     140: astore        9
     142: iconst_0
     143: istore        10
     145: aload         9
     147: invokestatic  #53                 // Method numSteps:(Lkotlin/sequences/Sequence;)J
     150: lstore        6
     152: aload         4
     154: aload         5
     156: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     159: lload         6
     161: goto          185
     164: astore        8
     166: aload         8
     168: astore        5
     170: aload         8
     172: athrow
     173: astore        8
     175: aload         4
     177: aload         5
     179: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     182: aload         8
     184: athrow
     185: nop
     186: lstore_0
     187: new           #61                 // class java/lang/StringBuilder
     190: dup
     191: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     194: ldc           #65                 // String Number of steps
     196: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     199: lload_0
     200: invokevirtual #72                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     203: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     206: getstatic     #82                 // Field java/lang/System.out:Ljava/io/PrintStream;
     209: swap
     210: invokevirtual #88                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     213: return
    Exception table:
       from    to  target type
         124   152   164   Class java/lang/Throwable
         124   152   173   any
         164   173   173   any
         173   175   173   any

  private static final long numSteps(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: astore_2
       2: new           #107                // class problems/day8/part2/RuleSetBuilder
       5: dup
       6: invokespecial #108                // Method problems/day8/part2/RuleSetBuilder."<init>":()V
       9: astore_3
      10: iconst_0
      11: istore        4
      13: aload_3
      14: astore        5
      16: aload_2
      17: invokeinterface #112,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      22: astore        6
      24: aload         6
      26: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      31: ifeq          69
      34: aload         6
      36: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      41: astore        7
      43: aload         5
      45: aload         7
      47: checkcast     #124                // class java/lang/String
      50: astore        8
      52: astore        9
      54: iconst_0
      55: istore        10
      57: aload         9
      59: aload         8
      61: invokevirtual #128                // Method problems/day8/part2/RuleSetBuilder.nextLine:(Ljava/lang/String;)Lproblems/day8/part2/RuleSetBuilder;
      64: astore        5
      66: goto          24
      69: aload         5
      71: invokevirtual #132                // Method problems/day8/part2/RuleSetBuilder.build:()Lproblems/day8/part2/ParseResult;
      74: astore_1
      75: aload_1
      76: invokevirtual #138                // Method problems/day8/part2/ParseResult.component1:()Lproblems/day8/part2/Instructions;
      79: astore_2
      80: aload_1
      81: invokevirtual #142                // Method problems/day8/part2/ParseResult.component2:()Ljava/util/Map;
      84: astore_3
      85: aload_3
      86: invokeinterface #148,  1          // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set;
      91: checkcast     #150                // class java/lang/Iterable
      94: astore        5
      96: iconst_0
      97: istore        6
      99: aload         5
     101: astore        7
     103: new           #152                // class java/util/ArrayList
     106: dup
     107: invokespecial #153                // Method java/util/ArrayList."<init>":()V
     110: checkcast     #155                // class java/util/Collection
     113: astore        8
     115: iconst_0
     116: istore        9
     118: aload         7
     120: invokeinterface #156,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     125: astore        10
     127: aload         10
     129: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     134: ifeq          182
     137: aload         10
     139: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     144: astore        11
     146: aload         11
     148: checkcast     #124                // class java/lang/String
     151: astore        12
     153: iconst_0
     154: istore        13
     156: aload         12
     158: ldc           #158                // String A
     160: iconst_0
     161: iconst_2
     162: aconst_null
     163: invokestatic  #164                // Method kotlin/text/StringsKt.endsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
     166: ifeq          127
     169: aload         8
     171: aload         11
     173: invokeinterface #168,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     178: pop
     179: goto          127
     182: aload         8
     184: checkcast     #170                // class java/util/List
     187: nop
     188: astore        4
     190: aload         4
     192: checkcast     #150                // class java/lang/Iterable
     195: astore        6
     197: iconst_0
     198: istore        7
     200: aload         6
     202: astore        8
     204: new           #152                // class java/util/ArrayList
     207: dup
     208: aload         6
     210: bipush        10
     212: invokestatic  #176                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     215: invokespecial #179                // Method java/util/ArrayList."<init>":(I)V
     218: checkcast     #155                // class java/util/Collection
     221: astore        9
     223: iconst_0
     224: istore        10
     226: aload         8
     228: invokeinterface #156,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     233: astore        11
     235: aload         11
     237: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     242: ifeq          293
     245: aload         11
     247: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     252: astore        12
     254: aload         9
     256: aload         12
     258: checkcast     #124                // class java/lang/String
     261: astore        13
     263: astore        15
     265: iconst_0
     266: istore        14
     268: aload         13
     270: aload_2
     271: invokevirtual #184                // Method problems/day8/part2/Instructions.copy:()Lproblems/day8/part2/Instructions;
     274: aload_3
     275: invokestatic  #188                // Method cycleLength:(Ljava/lang/String;Lproblems/day8/part2/Instructions;Ljava/util/Map;)I
     278: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     281: aload         15
     283: swap
     284: invokeinterface #168,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     289: pop
     290: goto          235
     293: aload         9
     295: checkcast     #170                // class java/util/List
     298: nop
     299: checkcast     #150                // class java/lang/Iterable
     302: astore        6
     304: nop
     305: iconst_0
     306: istore        7
     308: aload         6
     310: astore        8
     312: new           #152                // class java/util/ArrayList
     315: dup
     316: aload         6
     318: bipush        10
     320: invokestatic  #176                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     323: invokespecial #179                // Method java/util/ArrayList."<init>":(I)V
     326: checkcast     #155                // class java/util/Collection
     329: astore        9
     331: iconst_0
     332: istore        10
     334: aload         8
     336: invokeinterface #156,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     341: astore        11
     343: aload         11
     345: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     350: ifeq          397
     353: aload         11
     355: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     360: astore        12
     362: aload         9
     364: aload         12
     366: checkcast     #196                // class java/lang/Number
     369: invokevirtual #200                // Method java/lang/Number.intValue:()I
     372: istore        13
     374: astore        15
     376: iconst_0
     377: istore        14
     379: iload         13
     381: i2l
     382: invokestatic  #205                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     385: aload         15
     387: swap
     388: invokeinterface #168,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     393: pop
     394: goto          343
     397: aload         9
     399: checkcast     #170                // class java/util/List
     402: nop
     403: astore        5
     405: aload         5
     407: invokestatic  #209                // Method leastCommonMultiple:(Ljava/util/List;)J
     410: lreturn

  private static final int cycleLength(java.lang.String, problems.day8.part2.Instructions, java.util.Map<java.lang.String, problems.day8.part2.Rule>);
    Code:
       0: aload_0
       1: astore_3
       2: aload_3
       3: ldc           #247                // String Z
       5: iconst_0
       6: iconst_2
       7: aconst_null
       8: invokestatic  #164                // Method kotlin/text/StringsKt.endsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
      11: ifne          92
      14: aload_1
      15: invokevirtual #250                // Method problems/day8/part2/Instructions.next:()Ljava/lang/Character;
      18: invokevirtual #256                // Method java/lang/Character.charValue:()C
      21: istore        4
      23: aload_2
      24: aload_3
      25: invokeinterface #260,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      30: checkcast     #262                // class problems/day8/part2/Rule
      33: dup
      34: ifnonnull     66
      37: pop
      38: new           #264                // class java/lang/IllegalArgumentException
      41: dup
      42: new           #61                 // class java/lang/StringBuilder
      45: dup
      46: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
      49: ldc_w         #266                // String No such location:
      52: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      55: aload_3
      56: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      59: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      62: invokespecial #267                // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      65: athrow
      66: astore        5
      68: iload         4
      70: bipush        76
      72: if_icmpne     83
      75: aload         5
      77: invokevirtual #270                // Method problems/day8/part2/Rule.getLeft:()Ljava/lang/String;
      80: goto          88
      83: aload         5
      85: invokevirtual #273                // Method problems/day8/part2/Rule.getRight:()Ljava/lang/String;
      88: astore_3
      89: goto          2
      92: aload_1
      93: invokevirtual #276                // Method problems/day8/part2/Instructions.getDirectionCount:()I
      96: ireturn

  private static final long leastCommonMultiple(java.util.List<java.lang.Long>);
    Code:
       0: aload_0
       1: checkcast     #150                // class java/lang/Iterable
       4: astore_1
       5: iconst_0
       6: istore_2
       7: aload_1
       8: invokeinterface #156,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      13: astore_3
      14: aload_3
      15: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      20: ifne          34
      23: new           #285                // class java/lang/UnsupportedOperationException
      26: dup
      27: ldc_w         #287                // String Empty collection can\'t be reduced.
      30: invokespecial #288                // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V
      33: athrow
      34: aload_3
      35: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      40: astore        4
      42: aload_3
      43: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      48: ifeq          93
      51: aload         4
      53: aload_3
      54: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      59: checkcast     #196                // class java/lang/Number
      62: invokevirtual #292                // Method java/lang/Number.longValue:()J
      65: lstore        5
      67: checkcast     #196                // class java/lang/Number
      70: invokevirtual #292                // Method java/lang/Number.longValue:()J
      73: lstore        7
      75: iconst_0
      76: istore        9
      78: lload         7
      80: lload         5
      82: invokestatic  #296                // Method leastCommonMultipleOfPair:(JJ)J
      85: invokestatic  #205                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      88: astore        4
      90: goto          42
      93: aload         4
      95: checkcast     #196                // class java/lang/Number
      98: invokevirtual #292                // Method java/lang/Number.longValue:()J
     101: lreturn

  private static final long leastCommonMultipleOfPair(long, long);
    Code:
       0: lload_0
       1: lload_2
       2: lmul
       3: lload_0
       4: lload_2
       5: invokestatic  #307                // Method greatestCommonDivisor:(JJ)J
       8: ldiv
       9: lreturn

  private static final long greatestCommonDivisor(long, long);
    Code:
       0: nop
       1: lload_0
       2: lconst_0
       3: lcmp
       4: ifne          11
       7: lload_2
       8: goto          44
      11: lload_2
      12: lconst_0
      13: lcmp
      14: ifne          21
      17: lload_0
      18: goto          44
      21: lload_0
      22: lload_2
      23: lcmp
      24: ifle          37
      27: lload_0
      28: lload_2
      29: lrem
      30: lload_2
      31: invokestatic  #307                // Method greatestCommonDivisor:(JJ)J
      34: goto          44
      37: lload_0
      38: lload_2
      39: lload_0
      40: lrem
      41: invokestatic  #307                // Method greatestCommonDivisor:(JJ)J
      44: lreturn

  private static final problems.day8.part2.Rule toRule(java.lang.String);
    Code:
       0: aload_0
       1: ldc_w         #311                // String ,
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #315                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: astore_2
      11: iconst_0
      12: istore_3
      13: aload_2
      14: checkcast     #317                // class java/lang/CharSequence
      17: astore        4
      19: iconst_0
      20: istore        5
      22: iconst_0
      23: istore        6
      25: aload         4
      27: invokeinterface #320,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      32: istore        7
      34: iload         6
      36: iload         7
      38: if_icmpge     95
      41: aload         4
      43: iload         6
      45: invokeinterface #324,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      50: istore        8
      52: iconst_0
      53: istore        9
      55: iload         8
      57: bipush        40
      59: if_icmpne     66
      62: iconst_1
      63: goto          67
      66: iconst_0
      67: ifne          89
      70: aload         4
      72: iload         6
      74: aload         4
      76: invokeinterface #320,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      81: invokeinterface #328,  3          // InterfaceMethod java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
      86: goto          101
      89: iinc          6, 1
      92: goto          34
      95: ldc_w         #330                // String
      98: checkcast     #317                // class java/lang/CharSequence
     101: invokevirtual #331                // Method java/lang/Object.toString:()Ljava/lang/String;
     104: astore_1
     105: aload_0
     106: ldc_w         #311                // String ,
     109: aconst_null
     110: iconst_2
     111: aconst_null
     112: invokestatic  #334                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     115: astore_3
     116: iconst_0
     117: istore        4
     119: aload_3
     120: checkcast     #317                // class java/lang/CharSequence
     123: astore        5
     125: iconst_0
     126: istore        6
     128: aload         5
     130: invokeinterface #320,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     135: iconst_m1
     136: iadd
     137: istore        7
     139: iconst_0
     140: iload         7
     142: if_icmpgt     202
     145: iload         7
     147: istore        8
     149: iinc          7, -1
     152: aload         5
     154: iload         8
     156: invokeinterface #324,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     161: istore        9
     163: iconst_0
     164: istore        10
     166: iload         9
     168: bipush        41
     170: if_icmpne     177
     173: iconst_1
     174: goto          178
     177: iconst_0
     178: ifne          196
     181: aload         5
     183: iconst_0
     184: iload         8
     186: iconst_1
     187: iadd
     188: invokeinterface #328,  3          // InterfaceMethod java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
     193: goto          208
     196: iconst_0
     197: iload         7
     199: if_icmple     145
     202: ldc_w         #330                // String
     205: checkcast     #317                // class java/lang/CharSequence
     208: invokevirtual #331                // Method java/lang/Object.toString:()Ljava/lang/String;
     211: astore_2
     212: new           #262                // class problems/day8/part2/Rule
     215: dup
     216: aload_1
     217: aload_2
     218: invokespecial #337                // Method problems/day8/part2/Rule."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     221: areturn

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

  public static final problems.day8.part2.Rule access$toRule(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #358                // Method toRule:(Ljava/lang/String;)Lproblems/day8/part2/Rule;
       4: areturn
}


package problems.day8.part1

import java.io.File

//private const val test1file = "input/day8/test1.txt"
//private const val test2file = "input/day8/test2.txt"
private const val inputFile = "input/day8/input.txt"

fun main() {
    val stepsCount = File(inputFile).bufferedReader().useLines { numSteps(it) }
    println("Number of steps $stepsCount")
}

private fun numSteps(lines: Sequence<String>): Int {
    val (instructions, rules) = lines.fold(RuleSetBuilder()) { builder, line -> builder.nextLine(line) }.build()
    var currentLocation = "AAA"
    while (currentLocation != "ZZZ") {
        val nextDirection = instructions.next()
        val nextRule = rules[currentLocation] ?: throw IllegalArgumentException("No such location: $currentLocation")
        currentLocation = if (nextDirection == 'L') {
            nextRule.left
        } else {
            nextRule.right
        }
    }

    return instructions.directionCount
}

private class Instructions(val directions: String) : Iterator<Char> {
    var directionCount = 0
    override fun hasNext() = true

    override fun next(): Char {
        val next = directions[directionCount % directions.count()]
        directionCount++
        return next
    }

}

private data class Rule(val left: String, val right: String)

private fun String.toRule(): Rule {
    val left = this.substringBefore(", ").trimStart { it == '(' }
    val right = this.substringAfter(", ").trimEnd { it == ')' }
    return Rule(left, right)
}

private data class ParseResult(val instructions: Instructions, val rules: Map<String, Rule>)

private class RuleSetBuilder {
    private var state = State.INSTRUCTIONS
    private var instructions: Instructions? = null
    private val rules = mutableMapOf<String, Rule>()

    private enum class State {
        INSTRUCTIONS,
        BLANK,
        RULES,
    }

    fun nextLine(line: String): RuleSetBuilder {
        when (state) {
            State.INSTRUCTIONS -> {
                instructions = Instructions(line)
                state = State.BLANK
            }

            State.BLANK -> {
                state = State.RULES
            }

            State.RULES -> {
                rules[line.substringBefore(" =")] = line.substringAfter("= ").toRule()
            }

        }
        return this
    }

    fun build() = ParseResult(
        instructions ?: throw IllegalArgumentException("missing instructions"),
        rules
    )
}

Compiled from "part1.kt"
public final class problems.day8.part1.Part1Kt {
  private static final java.lang.String inputFile;

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day8/input.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: sipush        8192
      17: istore_3
      18: aload_1
      19: astore        4
      21: new           #24                 // class java/io/InputStreamReader
      24: dup
      25: new           #26                 // class java/io/FileInputStream
      28: dup
      29: aload         4
      31: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      34: checkcast     #31                 // class java/io/InputStream
      37: aload_2
      38: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      41: checkcast     #36                 // class java/io/Reader
      44: astore        4
      46: aload         4
      48: instanceof    #38                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         4
      56: checkcast     #38                 // class java/io/BufferedReader
      59: goto          72
      62: new           #38                 // class java/io/BufferedReader
      65: dup
      66: aload         4
      68: iload_3
      69: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      72: checkcast     #36                 // class java/io/Reader
      75: astore_1
      76: nop
      77: iconst_0
      78: istore_2
      79: aload_1
      80: astore_3
      81: sipush        8192
      84: istore        4
      86: aload_3
      87: instanceof    #38                 // class java/io/BufferedReader
      90: ifeq          100
      93: aload_3
      94: checkcast     #38                 // class java/io/BufferedReader
      97: goto          110
     100: new           #38                 // class java/io/BufferedReader
     103: dup
     104: aload_3
     105: iload         4
     107: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     110: checkcast     #43                 // class java/io/Closeable
     113: astore_3
     114: aconst_null
     115: astore        4
     117: nop
     118: aload_3
     119: checkcast     #38                 // class java/io/BufferedReader
     122: astore        5
     124: iconst_0
     125: istore        6
     127: aload         5
     129: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     132: astore        7
     134: iconst_0
     135: istore        8
     137: aload         7
     139: invokestatic  #53                 // Method numSteps:(Lkotlin/sequences/Sequence;)I
     142: istore        5
     144: aload_3
     145: aload         4
     147: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     150: iload         5
     152: goto          175
     155: astore        6
     157: aload         6
     159: astore        4
     161: aload         6
     163: athrow
     164: astore        6
     166: aload_3
     167: aload         4
     169: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     172: aload         6
     174: athrow
     175: nop
     176: istore_0
     177: new           #61                 // class java/lang/StringBuilder
     180: dup
     181: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     184: ldc           #65                 // String Number of steps
     186: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     189: iload_0
     190: invokevirtual #72                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     193: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     196: getstatic     #82                 // Field java/lang/System.out:Ljava/io/PrintStream;
     199: swap
     200: invokevirtual #88                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     203: return
    Exception table:
       from    to  target type
         117   144   155   Class java/lang/Throwable
         117   144   164   any
         155   164   164   any
         164   166   164   any

  private static final int numSteps(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: astore_2
       2: new           #106                // class problems/day8/part1/RuleSetBuilder
       5: dup
       6: invokespecial #107                // Method problems/day8/part1/RuleSetBuilder."<init>":()V
       9: astore_3
      10: iconst_0
      11: istore        4
      13: aload_3
      14: astore        5
      16: aload_2
      17: invokeinterface #111,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      22: astore        6
      24: aload         6
      26: invokeinterface #117,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      31: ifeq          69
      34: aload         6
      36: invokeinterface #121,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      41: astore        7
      43: aload         5
      45: aload         7
      47: checkcast     #123                // class java/lang/String
      50: astore        8
      52: astore        9
      54: iconst_0
      55: istore        10
      57: aload         9
      59: aload         8
      61: invokevirtual #127                // Method problems/day8/part1/RuleSetBuilder.nextLine:(Ljava/lang/String;)Lproblems/day8/part1/RuleSetBuilder;
      64: astore        5
      66: goto          24
      69: aload         5
      71: invokevirtual #131                // Method problems/day8/part1/RuleSetBuilder.build:()Lproblems/day8/part1/ParseResult;
      74: astore_1
      75: aload_1
      76: invokevirtual #137                // Method problems/day8/part1/ParseResult.component1:()Lproblems/day8/part1/Instructions;
      79: astore_2
      80: aload_1
      81: invokevirtual #141                // Method problems/day8/part1/ParseResult.component2:()Ljava/util/Map;
      84: astore_3
      85: ldc           #143                // String AAA
      87: astore        4
      89: aload         4
      91: ldc           #145                // String ZZZ
      93: invokestatic  #151                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      96: ifne          179
      99: aload_2
     100: invokevirtual #156                // Method problems/day8/part1/Instructions.next:()Ljava/lang/Character;
     103: invokevirtual #162                // Method java/lang/Character.charValue:()C
     106: istore        5
     108: aload_3
     109: aload         4
     111: invokeinterface #168,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     116: checkcast     #170                // class problems/day8/part1/Rule
     119: dup
     120: ifnonnull     152
     123: pop
     124: new           #172                // class java/lang/IllegalArgumentException
     127: dup
     128: new           #61                 // class java/lang/StringBuilder
     131: dup
     132: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     135: ldc           #174                // String No such location:
     137: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     140: aload         4
     142: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     145: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     148: invokespecial #175                // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
     151: athrow
     152: astore        6
     154: iload         5
     156: bipush        76
     158: if_icmpne     169
     161: aload         6
     163: invokevirtual #178                // Method problems/day8/part1/Rule.getLeft:()Ljava/lang/String;
     166: goto          174
     169: aload         6
     171: invokevirtual #181                // Method problems/day8/part1/Rule.getRight:()Ljava/lang/String;
     174: astore        4
     176: goto          89
     179: aload_2
     180: invokevirtual #185                // Method problems/day8/part1/Instructions.getDirectionCount:()I
     183: ireturn

  private static final problems.day8.part1.Rule toRule(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #210                // String ,
       3: aconst_null
       4: iconst_2
       5: aconst_null
       6: invokestatic  #216                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
       9: astore_2
      10: iconst_0
      11: istore_3
      12: aload_2
      13: checkcast     #218                // class java/lang/CharSequence
      16: astore        4
      18: iconst_0
      19: istore        5
      21: iconst_0
      22: istore        6
      24: aload         4
      26: invokeinterface #221,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      31: istore        7
      33: iload         6
      35: iload         7
      37: if_icmpge     94
      40: aload         4
      42: iload         6
      44: invokeinterface #225,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      49: istore        8
      51: iconst_0
      52: istore        9
      54: iload         8
      56: bipush        40
      58: if_icmpne     65
      61: iconst_1
      62: goto          66
      65: iconst_0
      66: ifne          88
      69: aload         4
      71: iload         6
      73: aload         4
      75: invokeinterface #221,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      80: invokeinterface #229,  3          // InterfaceMethod java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
      85: goto          99
      88: iinc          6, 1
      91: goto          33
      94: ldc           #231                // String
      96: checkcast     #218                // class java/lang/CharSequence
      99: invokevirtual #232                // Method java/lang/Object.toString:()Ljava/lang/String;
     102: astore_1
     103: aload_0
     104: ldc           #210                // String ,
     106: aconst_null
     107: iconst_2
     108: aconst_null
     109: invokestatic  #235                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
     112: astore_3
     113: iconst_0
     114: istore        4
     116: aload_3
     117: checkcast     #218                // class java/lang/CharSequence
     120: astore        5
     122: iconst_0
     123: istore        6
     125: aload         5
     127: invokeinterface #221,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     132: iconst_m1
     133: iadd
     134: istore        7
     136: iconst_0
     137: iload         7
     139: if_icmpgt     199
     142: iload         7
     144: istore        8
     146: iinc          7, -1
     149: aload         5
     151: iload         8
     153: invokeinterface #225,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     158: istore        9
     160: iconst_0
     161: istore        10
     163: iload         9
     165: bipush        41
     167: if_icmpne     174
     170: iconst_1
     171: goto          175
     174: iconst_0
     175: ifne          193
     178: aload         5
     180: iconst_0
     181: iload         8
     183: iconst_1
     184: iadd
     185: invokeinterface #229,  3          // InterfaceMethod java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
     190: goto          204
     193: iconst_0
     194: iload         7
     196: if_icmple     142
     199: ldc           #231                // String
     201: checkcast     #218                // class java/lang/CharSequence
     204: invokevirtual #232                // Method java/lang/Object.toString:()Ljava/lang/String;
     207: astore_2
     208: new           #170                // class problems/day8/part1/Rule
     211: dup
     212: aload_1
     213: aload_2
     214: invokespecial #238                // Method problems/day8/part1/Rule."<init>":(Ljava/lang/String;Ljava/lang/String;)V
     217: areturn

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

  public static final problems.day8.part1.Rule access$toRule(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #259                // Method toRule:(Ljava/lang/String;)Lproblems/day8/part1/Rule;
       4: areturn
}


package problems.day6.part2

import java.io.File
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.sqrt

private const val inputFile = "input/day6/input.txt"
//const val testFile = "input/day6/test.txt"

fun main() {
    val numberOfBeats = File(inputFile).bufferedReader().useLines { multiplyNumBeats(it) }
    println("The number of ways to be the current max is: $numberOfBeats")
}

private fun multiplyNumBeats(lines: Sequence<String>): Long {
    val iterator = lines.iterator()
    val time = iterator.next().toTime()
    val maxes = iterator.next().toMax()
    return Race(time, maxes).numBeats()
}

private fun String.toTime(): Long {
    return this.substringAfter("Time: ")
        .replace(" ","")
        .toLong()
}

private fun String.toMax(): Long {
    return this.substringAfter("Distance: ")
        .replace(" ","")
        .toLong()
}

private data class Race(val time: Long, val currentMax: Long) {
    fun numBeats(): Long {
        val a = -1
        val b = time
        val c = -currentMax

        val discriminant = sqrt(((b * b) - (4.0 * a * c)))
        val low = (-b + discriminant) / (2 * a)
        val high = (-b - discriminant) / (2 * a)
        val flooredHigh = floor(high)
        val ceiledLow = ceil(low)
        var numBeats = (flooredHigh - ceiledLow).toLong() + 1
        if (flooredHigh == high) {
            numBeats--
        }
        if (ceiledLow == low) {
            numBeats--
        }
        return numBeats
    }
}

Compiled from "part2.kt"
public final class problems.day6.part2.Part2Kt {
  private static final java.lang.String inputFile;

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day6/input.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_2
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_3
      14: sipush        8192
      17: istore        4
      19: aload_2
      20: astore        5
      22: new           #24                 // class java/io/InputStreamReader
      25: dup
      26: new           #26                 // class java/io/FileInputStream
      29: dup
      30: aload         5
      32: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      35: checkcast     #31                 // class java/io/InputStream
      38: aload_3
      39: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      42: checkcast     #36                 // class java/io/Reader
      45: astore        5
      47: aload         5
      49: instanceof    #38                 // class java/io/BufferedReader
      52: ifeq          63
      55: aload         5
      57: checkcast     #38                 // class java/io/BufferedReader
      60: goto          74
      63: new           #38                 // class java/io/BufferedReader
      66: dup
      67: aload         5
      69: iload         4
      71: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      74: checkcast     #36                 // class java/io/Reader
      77: astore_2
      78: nop
      79: iconst_0
      80: istore_3
      81: aload_2
      82: astore        4
      84: sipush        8192
      87: istore        5
      89: aload         4
      91: instanceof    #38                 // class java/io/BufferedReader
      94: ifeq          105
      97: aload         4
      99: checkcast     #38                 // class java/io/BufferedReader
     102: goto          116
     105: new           #38                 // class java/io/BufferedReader
     108: dup
     109: aload         4
     111: iload         5
     113: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     116: checkcast     #43                 // class java/io/Closeable
     119: astore        4
     121: aconst_null
     122: astore        5
     124: nop
     125: aload         4
     127: checkcast     #38                 // class java/io/BufferedReader
     130: astore        6
     132: iconst_0
     133: istore        8
     135: aload         6
     137: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     140: astore        9
     142: iconst_0
     143: istore        10
     145: aload         9
     147: invokestatic  #53                 // Method multiplyNumBeats:(Lkotlin/sequences/Sequence;)J
     150: lstore        6
     152: aload         4
     154: aload         5
     156: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     159: lload         6
     161: goto          185
     164: astore        8
     166: aload         8
     168: astore        5
     170: aload         8
     172: athrow
     173: astore        8
     175: aload         4
     177: aload         5
     179: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     182: aload         8
     184: athrow
     185: nop
     186: lstore_0
     187: new           #61                 // class java/lang/StringBuilder
     190: dup
     191: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     194: ldc           #65                 // String The number of ways to be the current max is:
     196: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     199: lload_0
     200: invokevirtual #72                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     203: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     206: getstatic     #82                 // Field java/lang/System.out:Ljava/io/PrintStream;
     209: swap
     210: invokevirtual #88                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     213: return
    Exception table:
       from    to  target type
         124   152   164   Class java/lang/Throwable
         124   152   173   any
         164   173   173   any
         173   175   173   any

  private static final long multiplyNumBeats(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: invokeinterface #109,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
       6: astore_1
       7: aload_1
       8: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      13: checkcast     #117                // class java/lang/String
      16: invokestatic  #121                // Method toTime:(Ljava/lang/String;)J
      19: lstore_2
      20: aload_1
      21: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      26: checkcast     #117                // class java/lang/String
      29: invokestatic  #124                // Method toMax:(Ljava/lang/String;)J
      32: lstore        4
      34: new           #126                // class problems/day6/part2/Race
      37: dup
      38: lload_2
      39: lload         4
      41: invokespecial #129                // Method problems/day6/part2/Race."<init>":(JJ)V
      44: invokevirtual #133                // Method problems/day6/part2/Race.numBeats:()J
      47: lreturn

  private static final long toTime(java.lang.String);
    Code:
       0: nop
       1: aload_0
       2: ldc           #139                // String Time:
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #145                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: ldc           #147                // String
      12: ldc           #149                // String
      14: iconst_0
      15: iconst_4
      16: aconst_null
      17: invokestatic  #153                // Method kotlin/text/StringsKt.replace$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/String;
      20: invokestatic  #158                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
      23: lreturn

  private static final long toMax(java.lang.String);
    Code:
       0: nop
       1: aload_0
       2: ldc           #162                // String Distance:
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #145                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: ldc           #147                // String
      12: ldc           #149                // String
      14: iconst_0
      15: iconst_4
      16: aconst_null
      17: invokestatic  #153                // Method kotlin/text/StringsKt.replace$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/String;
      20: invokestatic  #158                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
      23: lreturn

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


package problems.day6.part1

import java.io.File
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.sqrt

private const val inputFile = "input/day6/input.txt"
//private const val testFile = "input/day6/test.txt"

fun main() {
    val productOfNumBeats = File(inputFile).bufferedReader().useLines { multiplyNumBeats(it) }
    println("Product of number of ways to beat all races: $productOfNumBeats")
}

private fun multiplyNumBeats(lines: Sequence<String>): Int {
    val iterator = lines.iterator()
    val times = iterator.next().toTimes()
    val maxes = iterator.next().toMaxes()
    val races = times.zip(maxes) { time, max -> Race(time, max) }
    return races.map { it.numBeats() }.fold(1) { acc, next -> next * acc }
}

private fun String.toTimes(): List<Int> {
    return this.substringAfter("Time: ")
        .trim()
        .split("\\s+".toRegex())
        .map { it.toInt() }
}

private fun String.toMaxes(): List<Int> {
    return this.substringAfter("Distance: ")
        .trim()
        .split("\\s+".toRegex())
        .map { it.toInt() }
}

private data class Race(val time: Int, val currentMax: Int) {
    fun numBeats(): Int {
        val a = -1
        val b = time
        val c = -currentMax

        val discriminant = sqrt(((b * b) - (4.0 * a * c)))
        val low = (-b + discriminant) / (2 * a)
        val high = (-b - discriminant) / (2 * a)
        val flooredHigh = floor(high)
        val ceiledLow = ceil(low)
        var numBeats = (flooredHigh - ceiledLow).toInt() + 1
        if (flooredHigh == high) {
            numBeats--
        }
        if (ceiledLow == low) {
            numBeats--
        }
        return numBeats
    }
}

Compiled from "part1.kt"
public final class problems.day6.part1.Part1Kt {
  private static final java.lang.String inputFile;

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day6/input.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: sipush        8192
      17: istore_3
      18: aload_1
      19: astore        4
      21: new           #24                 // class java/io/InputStreamReader
      24: dup
      25: new           #26                 // class java/io/FileInputStream
      28: dup
      29: aload         4
      31: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      34: checkcast     #31                 // class java/io/InputStream
      37: aload_2
      38: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      41: checkcast     #36                 // class java/io/Reader
      44: astore        4
      46: aload         4
      48: instanceof    #38                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         4
      56: checkcast     #38                 // class java/io/BufferedReader
      59: goto          72
      62: new           #38                 // class java/io/BufferedReader
      65: dup
      66: aload         4
      68: iload_3
      69: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      72: checkcast     #36                 // class java/io/Reader
      75: astore_1
      76: nop
      77: iconst_0
      78: istore_2
      79: aload_1
      80: astore_3
      81: sipush        8192
      84: istore        4
      86: aload_3
      87: instanceof    #38                 // class java/io/BufferedReader
      90: ifeq          100
      93: aload_3
      94: checkcast     #38                 // class java/io/BufferedReader
      97: goto          110
     100: new           #38                 // class java/io/BufferedReader
     103: dup
     104: aload_3
     105: iload         4
     107: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     110: checkcast     #43                 // class java/io/Closeable
     113: astore_3
     114: aconst_null
     115: astore        4
     117: nop
     118: aload_3
     119: checkcast     #38                 // class java/io/BufferedReader
     122: astore        5
     124: iconst_0
     125: istore        6
     127: aload         5
     129: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     132: astore        7
     134: iconst_0
     135: istore        8
     137: aload         7
     139: invokestatic  #53                 // Method multiplyNumBeats:(Lkotlin/sequences/Sequence;)I
     142: istore        5
     144: aload_3
     145: aload         4
     147: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     150: iload         5
     152: goto          175
     155: astore        6
     157: aload         6
     159: astore        4
     161: aload         6
     163: athrow
     164: astore        6
     166: aload_3
     167: aload         4
     169: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     172: aload         6
     174: athrow
     175: nop
     176: istore_0
     177: new           #61                 // class java/lang/StringBuilder
     180: dup
     181: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     184: ldc           #65                 // String Product of number of ways to beat all races:
     186: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     189: iload_0
     190: invokevirtual #72                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     193: invokevirtual #76                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     196: getstatic     #82                 // Field java/lang/System.out:Ljava/io/PrintStream;
     199: swap
     200: invokevirtual #88                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     203: return
    Exception table:
       from    to  target type
         117   144   155   Class java/lang/Throwable
         117   144   164   any
         155   164   164   any
         164   166   164   any

  private static final int multiplyNumBeats(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: invokeinterface #108,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
       6: astore_1
       7: aload_1
       8: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      13: checkcast     #116                // class java/lang/String
      16: invokestatic  #120                // Method toTimes:(Ljava/lang/String;)Ljava/util/List;
      19: astore_2
      20: aload_1
      21: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      26: checkcast     #116                // class java/lang/String
      29: invokestatic  #123                // Method toMaxes:(Ljava/lang/String;)Ljava/util/List;
      32: astore_3
      33: aload_2
      34: checkcast     #125                // class java/lang/Iterable
      37: astore        5
      39: iconst_0
      40: istore        6
      42: aload         5
      44: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      49: astore        7
      51: aload_3
      52: checkcast     #125                // class java/lang/Iterable
      55: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      60: astore        8
      62: new           #128                // class java/util/ArrayList
      65: dup
      66: aload         5
      68: bipush        10
      70: invokestatic  #134                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      73: aload_3
      74: checkcast     #125                // class java/lang/Iterable
      77: bipush        10
      79: invokestatic  #134                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      82: invokestatic  #140                // Method java/lang/Math.min:(II)I
      85: invokespecial #143                // Method java/util/ArrayList."<init>":(I)V
      88: astore        9
      90: aload         7
      92: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      97: ifeq          168
     100: aload         8
     102: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     107: ifeq          168
     110: aload         9
     112: aload         7
     114: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     119: aload         8
     121: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     126: checkcast     #149                // class java/lang/Number
     129: invokevirtual #153                // Method java/lang/Number.intValue:()I
     132: istore        10
     134: checkcast     #149                // class java/lang/Number
     137: invokevirtual #153                // Method java/lang/Number.intValue:()I
     140: istore        11
     142: astore        14
     144: iconst_0
     145: istore        12
     147: new           #155                // class problems/day6/part1/Race
     150: dup
     151: iload         11
     153: iload         10
     155: invokespecial #158                // Method problems/day6/part1/Race."<init>":(II)V
     158: aload         14
     160: swap
     161: invokevirtual #162                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     164: pop
     165: goto          90
     168: aload         9
     170: checkcast     #164                // class java/util/List
     173: astore        4
     175: aload         4
     177: checkcast     #125                // class java/lang/Iterable
     180: astore        5
     182: iconst_0
     183: istore        6
     185: aload         5
     187: astore        7
     189: new           #128                // class java/util/ArrayList
     192: dup
     193: aload         5
     195: bipush        10
     197: invokestatic  #134                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     200: invokespecial #143                // Method java/util/ArrayList."<init>":(I)V
     203: checkcast     #166                // class java/util/Collection
     206: astore        8
     208: iconst_0
     209: istore        9
     211: aload         7
     213: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     218: astore        10
     220: aload         10
     222: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     227: ifeq          273
     230: aload         10
     232: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     237: astore        11
     239: aload         8
     241: aload         11
     243: checkcast     #155                // class problems/day6/part1/Race
     246: astore        12
     248: astore        14
     250: iconst_0
     251: istore        13
     253: aload         12
     255: invokevirtual #169                // Method problems/day6/part1/Race.numBeats:()I
     258: invokestatic  #175                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     261: aload         14
     263: swap
     264: invokeinterface #176,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     269: pop
     270: goto          220
     273: aload         8
     275: checkcast     #164                // class java/util/List
     278: nop
     279: checkcast     #125                // class java/lang/Iterable
     282: astore        5
     284: iconst_1
     285: istore        6
     287: iconst_0
     288: istore        7
     290: iload         6
     292: istore        8
     294: aload         5
     296: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     301: astore        9
     303: aload         9
     305: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     310: ifeq          349
     313: aload         9
     315: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     320: astore        10
     322: iload         8
     324: aload         10
     326: checkcast     #149                // class java/lang/Number
     329: invokevirtual #153                // Method java/lang/Number.intValue:()I
     332: istore        11
     334: istore        12
     336: iconst_0
     337: istore        13
     339: iload         11
     341: iload         12
     343: imul
     344: istore        8
     346: goto          303
     349: iload         8
     351: ireturn

  private static final java.util.List<java.lang.Integer> toTimes(java.lang.String);
    Code:
       0: nop
       1: aload_0
       2: ldc           #212                // String Time:
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #218                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: checkcast     #220                // class java/lang/CharSequence
      13: invokestatic  #224                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      16: invokevirtual #225                // Method java/lang/Object.toString:()Ljava/lang/String;
      19: checkcast     #220                // class java/lang/CharSequence
      22: astore_1
      23: new           #227                // class kotlin/text/Regex
      26: dup
      27: ldc           #229                // String \\s+
      29: invokespecial #230                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      32: astore_2
      33: iconst_0
      34: istore_3
      35: aload_2
      36: aload_1
      37: iload_3
      38: invokevirtual #234                // Method kotlin/text/Regex.split:(Ljava/lang/CharSequence;I)Ljava/util/List;
      41: checkcast     #125                // class java/lang/Iterable
      44: astore_1
      45: nop
      46: iconst_0
      47: istore_2
      48: aload_1
      49: astore_3
      50: new           #128                // class java/util/ArrayList
      53: dup
      54: aload_1
      55: bipush        10
      57: invokestatic  #134                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      60: invokespecial #143                // Method java/util/ArrayList."<init>":(I)V
      63: checkcast     #166                // class java/util/Collection
      66: astore        4
      68: iconst_0
      69: istore        5
      71: aload_3
      72: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      77: astore        6
      79: aload         6
      81: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      86: ifeq          133
      89: aload         6
      91: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      96: astore        7
      98: aload         4
     100: aload         7
     102: checkcast     #116                // class java/lang/String
     105: astore        8
     107: astore        10
     109: iconst_0
     110: istore        9
     112: aload         8
     114: invokestatic  #238                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     117: nop
     118: invokestatic  #175                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     121: aload         10
     123: swap
     124: invokeinterface #176,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     129: pop
     130: goto          79
     133: aload         4
     135: checkcast     #164                // class java/util/List
     138: nop
     139: areturn

  private static final java.util.List<java.lang.Integer> toMaxes(java.lang.String);
    Code:
       0: nop
       1: aload_0
       2: ldc           #243                // String Distance:
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #218                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: checkcast     #220                // class java/lang/CharSequence
      13: invokestatic  #224                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      16: invokevirtual #225                // Method java/lang/Object.toString:()Ljava/lang/String;
      19: checkcast     #220                // class java/lang/CharSequence
      22: astore_1
      23: new           #227                // class kotlin/text/Regex
      26: dup
      27: ldc           #229                // String \\s+
      29: invokespecial #230                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      32: astore_2
      33: iconst_0
      34: istore_3
      35: aload_2
      36: aload_1
      37: iload_3
      38: invokevirtual #234                // Method kotlin/text/Regex.split:(Ljava/lang/CharSequence;I)Ljava/util/List;
      41: checkcast     #125                // class java/lang/Iterable
      44: astore_1
      45: nop
      46: iconst_0
      47: istore_2
      48: aload_1
      49: astore_3
      50: new           #128                // class java/util/ArrayList
      53: dup
      54: aload_1
      55: bipush        10
      57: invokestatic  #134                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      60: invokespecial #143                // Method java/util/ArrayList."<init>":(I)V
      63: checkcast     #166                // class java/util/Collection
      66: astore        4
      68: iconst_0
      69: istore        5
      71: aload_3
      72: invokeinterface #126,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      77: astore        6
      79: aload         6
      81: invokeinterface #147,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      86: ifeq          133
      89: aload         6
      91: invokeinterface #114,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      96: astore        7
      98: aload         4
     100: aload         7
     102: checkcast     #116                // class java/lang/String
     105: astore        8
     107: astore        10
     109: iconst_0
     110: istore        9
     112: aload         8
     114: invokestatic  #238                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     117: nop
     118: invokestatic  #175                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     121: aload         10
     123: swap
     124: invokeinterface #176,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     129: pop
     130: goto          79
     133: aload         4
     135: checkcast     #164                // class java/util/List
     138: nop
     139: areturn

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


package problems.day10.part1

import java.io.File

private const val testFile1 = "input/day10/test1.txt"
private const val inputFile = "input/day10/input.txt"

fun main() {
    val farthestTileDistance = File(inputFile).bufferedReader().useLines { farthestTileDistance(it) }
    println("The tile farthest from start is $farthestTileDistance tiles away")
}

fun farthestTileDistance(it: Sequence<String>): Int {
    val board = it.fold(BoardBuilder()) { builder, line -> builder.nextLine(line) }.build()
//    println("Board: ${board.tiles}")
//    println("start: ${board.startRow} ${board.startCol}")

    val totalDistance = board.totalPipeDistance()
    return totalDistance / 2
}

private class BoardBuilder {
    private val tiles = mutableMapOf<Location, Tile>()
    private var start: Location? = null
    private var rowIndex = 0

    fun nextLine(line: String): BoardBuilder {
        line.forEachIndexed { colIndex, c ->
            val tile = c.toTile()
            val location = Location(rowIndex, colIndex)
            if (tile is Tile.Start) {
                start = location
            }
            tiles[location] = tile
        }

        rowIndex++
        return this
    }

    fun build() = Board(
        tiles,
        start ?: throw IllegalArgumentException("No location found for start"),
    )
}

private class Board(val tiles: Map<Location, Tile>, val start: Location) {
    fun totalPipeDistance(): Int {
        var previousLocation = start
        var (currentLocation, currentTile) = nextFromStart()
        var distance = 1
        while (currentLocation != start) {
            val (nextLocation, nextTile) = nextTile(previousLocation, currentLocation, currentTile)
            previousLocation = currentLocation
            currentLocation = nextLocation
            currentTile = nextTile
            distance++
        }
        return distance
    }

    private fun nextFromStart(): Pair<Location, Tile> {
        val northernLocation = start.toNorth()
        val northernTile = tiles[northernLocation]
        if (northernTile?.opensOn(Direction.SOUTH) == true) {
            return Pair(northernLocation, northernTile)
        }

        val southernLocation = start.toSouth()
        val southernTile = tiles[southernLocation]
        if (southernTile?.opensOn(Direction.NORTH) == true) {
            return Pair(southernLocation, southernTile)
        }

        val westernLocation = start.toWest()
        val westernTile = tiles[westernLocation]
        if (westernTile?.opensOn(Direction.EAST) == true) {
            return Pair(westernLocation, westernTile)
        }

        val easternLocation = start.toEast()
        val easternTile = tiles[easternLocation]
        if (easternTile?.opensOn(Direction.WEST) == true) {
            return Pair(easternLocation, easternTile)
        }

        throw IllegalArgumentException("No tile accessible from start")
    }

    private fun nextTile(
        previousLocation: Location,
        currentLocation: Location,
        currentTile: Tile
    ): Pair<Location, Tile> {
        if (currentTile.opensOn(Direction.NORTH)) {
            val northernLocation = currentLocation.toNorth()
            val northernTile = tiles[northernLocation]
            if (northernTile?.opensOn(Direction.SOUTH) == true && northernLocation != previousLocation) {
                return Pair(northernLocation, northernTile)
            }
        }

        if (currentTile.opensOn(Direction.SOUTH)) {
            val southernLocation = currentLocation.toSouth()
            val southernTile = tiles[southernLocation]
            if (southernTile?.opensOn(Direction.NORTH) == true && southernLocation != previousLocation) {
                return Pair(southernLocation, southernTile)
            }
        }

        if (currentTile.opensOn(Direction.WEST)) {
            val westernLocation = currentLocation.toWest()
            val westernTile = tiles[westernLocation]
            if (westernTile?.opensOn(Direction.EAST) == true && westernLocation != previousLocation) {
                return Pair(westernLocation, westernTile)
            }
        }

        if (currentTile.opensOn(Direction.EAST)) {
            val easternLocation = currentLocation.toEast()
            val easternTile = tiles[easternLocation]
            if (easternTile?.opensOn(Direction.WEST) == true && easternLocation != previousLocation) {
                return Pair(easternLocation, easternTile)
            }
        }

        throw IllegalArgumentException("No next tile from $currentLocation")
    }
}

private data class Location(val row: Int, val col: Int) {
    fun toNorth(): Location = Location(row - 1, col)
    fun toSouth(): Location = Location(row + 1, col)
    fun toWest(): Location = Location(row, col - 1)
    fun toEast(): Location = Location(row, col + 1)
}

private sealed class Tile {
    data class Pipe(val first: Direction, val second: Direction) : Tile()
    data object Ground : Tile()
    data object Start : Tile()

    fun opensOn(direction: Direction) = when (this) {
        is Pipe -> this.first == direction || this.second == direction
        is Start -> true
        else -> false
    }
}

private fun Char.toTile(): Tile = when (this) {
    '|' -> Tile.Pipe(Direction.NORTH, Direction.SOUTH)
    '-' -> Tile.Pipe(Direction.EAST, Direction.WEST)
    'L' -> Tile.Pipe(Direction.NORTH, Direction.EAST)
    'J' -> Tile.Pipe(Direction.NORTH, Direction.WEST)
    '7' -> Tile.Pipe(Direction.SOUTH, Direction.WEST)
    'F' -> Tile.Pipe(Direction.SOUTH, Direction.EAST)
    'S' -> Tile.Start
    else -> Tile.Ground
}

private enum class Direction {
    NORTH,
    SOUTH,
    EAST,
    WEST,
}

Compiled from "part1.kt"
public final class problems.day10.part1.Part1Kt {
  private static final java.lang.String testFile1;

  private static final java.lang.String inputFile;

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day10/input.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: sipush        8192
      17: istore_3
      18: aload_1
      19: astore        4
      21: new           #24                 // class java/io/InputStreamReader
      24: dup
      25: new           #26                 // class java/io/FileInputStream
      28: dup
      29: aload         4
      31: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      34: checkcast     #31                 // class java/io/InputStream
      37: aload_2
      38: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      41: checkcast     #36                 // class java/io/Reader
      44: astore        4
      46: aload         4
      48: instanceof    #38                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         4
      56: checkcast     #38                 // class java/io/BufferedReader
      59: goto          72
      62: new           #38                 // class java/io/BufferedReader
      65: dup
      66: aload         4
      68: iload_3
      69: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      72: checkcast     #36                 // class java/io/Reader
      75: astore_1
      76: nop
      77: iconst_0
      78: istore_2
      79: aload_1
      80: astore_3
      81: sipush        8192
      84: istore        4
      86: aload_3
      87: instanceof    #38                 // class java/io/BufferedReader
      90: ifeq          100
      93: aload_3
      94: checkcast     #38                 // class java/io/BufferedReader
      97: goto          110
     100: new           #38                 // class java/io/BufferedReader
     103: dup
     104: aload_3
     105: iload         4
     107: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     110: checkcast     #43                 // class java/io/Closeable
     113: astore_3
     114: aconst_null
     115: astore        4
     117: nop
     118: aload_3
     119: checkcast     #38                 // class java/io/BufferedReader
     122: astore        5
     124: iconst_0
     125: istore        6
     127: aload         5
     129: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     132: astore        7
     134: iconst_0
     135: istore        8
     137: aload         7
     139: invokestatic  #53                 // Method farthestTileDistance:(Lkotlin/sequences/Sequence;)I
     142: istore        5
     144: aload_3
     145: aload         4
     147: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     150: iload         5
     152: goto          175
     155: astore        6
     157: aload         6
     159: astore        4
     161: aload         6
     163: athrow
     164: astore        6
     166: aload_3
     167: aload         4
     169: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     172: aload         6
     174: athrow
     175: nop
     176: istore_0
     177: new           #61                 // class java/lang/StringBuilder
     180: dup
     181: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     184: ldc           #65                 // String The tile farthest from start is
     186: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     189: iload_0
     190: invokevirtual #72                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     193: ldc           #74                 // String  tiles away
     195: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     198: invokevirtual #78                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     201: getstatic     #84                 // Field java/lang/System.out:Ljava/io/PrintStream;
     204: swap
     205: invokevirtual #90                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     208: return
    Exception table:
       from    to  target type
         117   144   155   Class java/lang/Throwable
         117   144   164   any
         155   164   164   any
         164   166   164   any

  public static final int farthestTileDistance(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #107                // String it
       3: invokestatic  #113                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: astore_2
       8: new           #115                // class problems/day10/part1/BoardBuilder
      11: dup
      12: invokespecial #116                // Method problems/day10/part1/BoardBuilder."<init>":()V
      15: astore_3
      16: iconst_0
      17: istore        4
      19: aload_3
      20: astore        5
      22: aload_2
      23: invokeinterface #120,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      28: astore        6
      30: aload         6
      32: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      37: ifeq          75
      40: aload         6
      42: invokeinterface #130,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      47: astore        7
      49: aload         5
      51: aload         7
      53: checkcast     #132                // class java/lang/String
      56: astore        8
      58: astore        9
      60: iconst_0
      61: istore        10
      63: aload         9
      65: aload         8
      67: invokevirtual #136                // Method problems/day10/part1/BoardBuilder.nextLine:(Ljava/lang/String;)Lproblems/day10/part1/BoardBuilder;
      70: astore        5
      72: goto          30
      75: aload         5
      77: invokevirtual #140                // Method problems/day10/part1/BoardBuilder.build:()Lproblems/day10/part1/Board;
      80: astore_1
      81: aload_1
      82: invokevirtual #146                // Method problems/day10/part1/Board.totalPipeDistance:()I
      85: istore_2
      86: iload_2
      87: iconst_2
      88: idiv
      89: ireturn

  private static final problems.day10.part1.Tile toTile(char);
    Code:
       0: iload_0
       1: lookupswitch  { // 7
                    45: 87
                    55: 144
                    70: 163
                    74: 125
                    76: 106
                    83: 182
                   124: 68
               default: 191
          }
      68: new           #164                // class problems/day10/part1/Tile$Pipe
      71: dup
      72: getstatic     #170                // Field problems/day10/part1/Direction.NORTH:Lproblems/day10/part1/Direction;
      75: getstatic     #173                // Field problems/day10/part1/Direction.SOUTH:Lproblems/day10/part1/Direction;
      78: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
      81: checkcast     #178                // class problems/day10/part1/Tile
      84: goto          197
      87: new           #164                // class problems/day10/part1/Tile$Pipe
      90: dup
      91: getstatic     #181                // Field problems/day10/part1/Direction.EAST:Lproblems/day10/part1/Direction;
      94: getstatic     #184                // Field problems/day10/part1/Direction.WEST:Lproblems/day10/part1/Direction;
      97: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
     100: checkcast     #178                // class problems/day10/part1/Tile
     103: goto          197
     106: new           #164                // class problems/day10/part1/Tile$Pipe
     109: dup
     110: getstatic     #170                // Field problems/day10/part1/Direction.NORTH:Lproblems/day10/part1/Direction;
     113: getstatic     #181                // Field problems/day10/part1/Direction.EAST:Lproblems/day10/part1/Direction;
     116: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
     119: checkcast     #178                // class problems/day10/part1/Tile
     122: goto          197
     125: new           #164                // class problems/day10/part1/Tile$Pipe
     128: dup
     129: getstatic     #170                // Field problems/day10/part1/Direction.NORTH:Lproblems/day10/part1/Direction;
     132: getstatic     #184                // Field problems/day10/part1/Direction.WEST:Lproblems/day10/part1/Direction;
     135: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
     138: checkcast     #178                // class problems/day10/part1/Tile
     141: goto          197
     144: new           #164                // class problems/day10/part1/Tile$Pipe
     147: dup
     148: getstatic     #173                // Field problems/day10/part1/Direction.SOUTH:Lproblems/day10/part1/Direction;
     151: getstatic     #184                // Field problems/day10/part1/Direction.WEST:Lproblems/day10/part1/Direction;
     154: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
     157: checkcast     #178                // class problems/day10/part1/Tile
     160: goto          197
     163: new           #164                // class problems/day10/part1/Tile$Pipe
     166: dup
     167: getstatic     #173                // Field problems/day10/part1/Direction.SOUTH:Lproblems/day10/part1/Direction;
     170: getstatic     #181                // Field problems/day10/part1/Direction.EAST:Lproblems/day10/part1/Direction;
     173: invokespecial #176                // Method problems/day10/part1/Tile$Pipe."<init>":(Lproblems/day10/part1/Direction;Lproblems/day10/part1/Direction;)V
     176: checkcast     #178                // class problems/day10/part1/Tile
     179: goto          197
     182: getstatic     #190                // Field problems/day10/part1/Tile$Start.INSTANCE:Lproblems/day10/part1/Tile$Start;
     185: checkcast     #178                // class problems/day10/part1/Tile
     188: goto          197
     191: getstatic     #195                // Field problems/day10/part1/Tile$Ground.INSTANCE:Lproblems/day10/part1/Tile$Ground;
     194: checkcast     #178                // class problems/day10/part1/Tile
     197: areturn

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

  public static final problems.day10.part1.Tile access$toTile(char);
    Code:
       0: iload_0
       1: invokestatic  #205                // Method toTile:(C)Lproblems/day10/part1/Tile;
       4: areturn
}