package problems.day4.part1

import java.io.File
import kotlin.math.pow

//private const val testFile = "input/day4/test.txt"
private const val cardsFile = "input/day4/cards.txt"

fun main() {
    val cardValueSum = File(cardsFile).bufferedReader().useLines { sumCardValues(it) }
    println("Card Values Sum: $cardValueSum")
}

private fun sumCardValues(lines: Sequence<String>) = lines.map { it.toCard() }.sumOf { it.value() }

private fun String.toCard() = Card(
    id = this.toCardID(),
    winningNumbers = this.toWinningNumbers(),
    possessedNumbers = this.toPossessedNumbers()
)

private fun String.toCardID(): Int = this.substringBefore(":").substringAfter(" ").trim().toInt()

private fun String.toWinningNumbers() =
    this.substringAfter(":").substringBefore("|").trim().split(" ").filter { it != "" }.map { it.toInt() }
        .toSet()

private fun String.toPossessedNumbers(): Set<Int> =
    this.substringAfter("|").trim().split(" ").filter { it != "" }.map { it.trim().toInt() }.toSet()

private data class Card(val id: Int, val winningNumbers: Set<Int>, val possessedNumbers: Set<Int>) {
    fun value(): Int = 2.0.pow(numMatching() - 1).toInt()
    fun numMatching() = winningNumbers.intersect(possessedNumbers).count()
}

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

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day4/cards.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 sumCardValues:(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 Card Values Sum:
     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 sumCardValues(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: invokedynamic #123,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
       6: invokestatic  #129                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
       9: astore_1
      10: iconst_0
      11: istore_2
      12: aload_1
      13: invokeinterface #133,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      18: astore_3
      19: aload_3
      20: invokeinterface #139,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      25: ifeq          65
      28: aload_3
      29: invokeinterface #143,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      34: astore        4
      36: iload_2
      37: aload         4
      39: checkcast     #145                // class problems/day4/part1/Card
      42: astore        5
      44: istore        7
      46: iconst_0
      47: istore        6
      49: aload         5
      51: invokevirtual #149                // Method problems/day4/part1/Card.value:()I
      54: istore        8
      56: iload         7
      58: iload         8
      60: iadd
      61: istore_2
      62: goto          19
      65: iload_2
      66: ireturn

  private static final problems.day4.part1.Card toCard(java.lang.String);
    Code:
       0: new           #145                // class problems/day4/part1/Card
       3: dup
       4: aload_0
       5: invokestatic  #157                // Method toCardID:(Ljava/lang/String;)I
       8: aload_0
       9: invokestatic  #161                // Method toWinningNumbers:(Ljava/lang/String;)Ljava/util/Set;
      12: aload_0
      13: invokestatic  #164                // Method toPossessedNumbers:(Ljava/lang/String;)Ljava/util/Set;
      16: invokespecial #167                // Method problems/day4/part1/Card."<init>":(ILjava/util/Set;Ljava/util/Set;)V
      19: areturn

  private static final int toCardID(java.lang.String);
    Code:
       0: nop
       1: aload_0
       2: ldc           #171                // String :
       4: aconst_null
       5: iconst_2
       6: aconst_null
       7: invokestatic  #177                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      10: ldc           #179                // String
      12: aconst_null
      13: iconst_2
      14: aconst_null
      15: invokestatic  #182                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      18: checkcast     #184                // class java/lang/CharSequence
      21: invokestatic  #188                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      24: invokevirtual #189                // Method java/lang/Object.toString:()Ljava/lang/String;
      27: invokestatic  #194                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      30: ireturn

  private static final java.util.Set<java.lang.Integer> toWinningNumbers(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #171                // String :
       3: aconst_null
       4: iconst_2
       5: aconst_null
       6: invokestatic  #182                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
       9: ldc           #198                // String |
      11: aconst_null
      12: iconst_2
      13: aconst_null
      14: invokestatic  #177                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      17: checkcast     #184                // class java/lang/CharSequence
      20: invokestatic  #188                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      23: invokevirtual #189                // Method java/lang/Object.toString:()Ljava/lang/String;
      26: checkcast     #184                // class java/lang/CharSequence
      29: iconst_1
      30: anewarray     #200                // class java/lang/String
      33: astore_1
      34: aload_1
      35: iconst_0
      36: ldc           #179                // String
      38: aastore
      39: aload_1
      40: iconst_0
      41: iconst_0
      42: bipush        6
      44: aconst_null
      45: invokestatic  #204                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      48: checkcast     #206                // class java/lang/Iterable
      51: astore_1
      52: iconst_0
      53: istore_2
      54: aload_1
      55: astore_3
      56: new           #208                // class java/util/ArrayList
      59: dup
      60: invokespecial #209                // Method java/util/ArrayList."<init>":()V
      63: checkcast     #211                // class java/util/Collection
      66: astore        4
      68: iconst_0
      69: istore        5
      71: aload_3
      72: invokeinterface #212,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      77: astore        6
      79: aload         6
      81: invokeinterface #139,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      86: ifeq          139
      89: aload         6
      91: invokeinterface #143,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      96: astore        7
      98: aload         7
     100: checkcast     #200                // class java/lang/String
     103: astore        8
     105: iconst_0
     106: istore        9
     108: aload         8
     110: ldc           #214                // String
     112: invokestatic  #220                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     115: ifne          122
     118: iconst_1
     119: goto          123
     122: iconst_0
     123: ifeq          79
     126: aload         4
     128: aload         7
     130: invokeinterface #224,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     135: pop
     136: goto          79
     139: aload         4
     141: checkcast     #226                // class java/util/List
     144: nop
     145: checkcast     #206                // class java/lang/Iterable
     148: astore_1
     149: nop
     150: iconst_0
     151: istore_2
     152: aload_1
     153: astore_3
     154: new           #208                // class java/util/ArrayList
     157: dup
     158: aload_1
     159: bipush        10
     161: invokestatic  #232                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     164: invokespecial #235                // Method java/util/ArrayList."<init>":(I)V
     167: checkcast     #211                // class java/util/Collection
     170: astore        4
     172: iconst_0
     173: istore        5
     175: aload_3
     176: invokeinterface #212,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     181: astore        6
     183: aload         6
     185: invokeinterface #139,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     190: ifeq          237
     193: aload         6
     195: invokeinterface #143,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     200: astore        7
     202: aload         4
     204: aload         7
     206: checkcast     #200                // class java/lang/String
     209: astore        8
     211: astore        10
     213: iconst_0
     214: istore        9
     216: aload         8
     218: invokestatic  #194                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     221: nop
     222: invokestatic  #239                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     225: aload         10
     227: swap
     228: invokeinterface #224,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     233: pop
     234: goto          183
     237: aload         4
     239: checkcast     #226                // class java/util/List
     242: nop
     243: checkcast     #206                // class java/lang/Iterable
     246: invokestatic  #243                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     249: areturn

  private static final java.util.Set<java.lang.Integer> toPossessedNumbers(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #198                // String |
       3: aconst_null
       4: iconst_2
       5: aconst_null
       6: invokestatic  #182                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
       9: checkcast     #184                // class java/lang/CharSequence
      12: invokestatic  #188                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      15: invokevirtual #189                // Method java/lang/Object.toString:()Ljava/lang/String;
      18: checkcast     #184                // class java/lang/CharSequence
      21: iconst_1
      22: anewarray     #200                // class java/lang/String
      25: astore_1
      26: aload_1
      27: iconst_0
      28: ldc           #179                // String
      30: aastore
      31: aload_1
      32: iconst_0
      33: iconst_0
      34: bipush        6
      36: aconst_null
      37: invokestatic  #204                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      40: checkcast     #206                // class java/lang/Iterable
      43: astore_1
      44: iconst_0
      45: istore_2
      46: aload_1
      47: astore_3
      48: new           #208                // class java/util/ArrayList
      51: dup
      52: invokespecial #209                // Method java/util/ArrayList."<init>":()V
      55: checkcast     #211                // class java/util/Collection
      58: astore        4
      60: iconst_0
      61: istore        5
      63: aload_3
      64: invokeinterface #212,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      69: astore        6
      71: aload         6
      73: invokeinterface #139,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      78: ifeq          131
      81: aload         6
      83: invokeinterface #143,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      88: astore        7
      90: aload         7
      92: checkcast     #200                // class java/lang/String
      95: astore        8
      97: iconst_0
      98: istore        9
     100: aload         8
     102: ldc           #214                // String
     104: invokestatic  #220                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     107: ifne          114
     110: iconst_1
     111: goto          115
     114: iconst_0
     115: ifeq          71
     118: aload         4
     120: aload         7
     122: invokeinterface #224,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     127: pop
     128: goto          71
     131: aload         4
     133: checkcast     #226                // class java/util/List
     136: nop
     137: checkcast     #206                // class java/lang/Iterable
     140: astore_1
     141: nop
     142: iconst_0
     143: istore_2
     144: aload_1
     145: astore_3
     146: new           #208                // class java/util/ArrayList
     149: dup
     150: aload_1
     151: bipush        10
     153: invokestatic  #232                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     156: invokespecial #235                // Method java/util/ArrayList."<init>":(I)V
     159: checkcast     #211                // class java/util/Collection
     162: astore        4
     164: iconst_0
     165: istore        5
     167: aload_3
     168: invokeinterface #212,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     173: astore        6
     175: aload         6
     177: invokeinterface #139,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     182: ifeq          239
     185: aload         6
     187: invokeinterface #143,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     192: astore        7
     194: aload         4
     196: aload         7
     198: checkcast     #200                // class java/lang/String
     201: astore        8
     203: astore        10
     205: iconst_0
     206: istore        9
     208: nop
     209: aload         8
     211: checkcast     #184                // class java/lang/CharSequence
     214: invokestatic  #188                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
     217: invokevirtual #189                // Method java/lang/Object.toString:()Ljava/lang/String;
     220: invokestatic  #194                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     223: nop
     224: invokestatic  #239                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     227: aload         10
     229: swap
     230: invokeinterface #224,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     235: pop
     236: goto          175
     239: aload         4
     241: checkcast     #226                // class java/util/List
     244: nop
     245: checkcast     #206                // class java/lang/Iterable
     248: invokestatic  #243                // Method kotlin/collections/CollectionsKt.toSet:(Ljava/lang/Iterable;)Ljava/util/Set;
     251: areturn

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

  private static final problems.day4.part1.Card sumCardValues$lambda$1(java.lang.String);
    Code:
       0: aload_0
       1: ldc_w         #269                // String it
       4: invokestatic  #273                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokestatic  #275                // Method toCard:(Ljava/lang/String;)Lproblems/day4/part1/Card;
      11: areturn
}


package problems.day3.part2

import java.io.File

//private const val testFile = "input/day3/test.txt"
private const val part_numbers = "input/day3/part_numbers.txt"

fun main() {
    val gearRatioSum = File(part_numbers).bufferedReader().useLines { sumGearRatios(it) }
    println("Part Number Sum: $gearRatioSum")
}

private fun sumGearRatios(lines: Sequence<String>): Int {
    val possibleGears = mutableMapOf<Int, Map<Int, Int>>()
    val stars = mutableMapOf<Int, Set<Int>>()
    lines.forEachIndexed {row, line ->
        val res = parseLine(line)
        possibleGears[row] = res.possibleGears
        stars[row] = res.stars
    }

    return stars.flatMap { it.value.toRowCols(it.key) }
        .mapNotNull { it.gearRatio(possibleGears) }
        .sum()
}

private fun parseLine(line: String) = LineResult(
    accumulateNumbers(line),
    recordStarts(line),
)

private data class LineResult(val possibleGears: Map<Int, Int>, val stars: Set<Int>)

private fun accumulateNumbers(line: String): Map<Int, Int> {
    val accumulator = PossibleGearAccumulator()
    line.forEach { accumulator.nextChar(it) }
    return accumulator.end()
}

private fun recordStarts(line: String): Set<Int> {
    val stars = mutableSetOf<Int>()
    line.forEachIndexed { index, c ->  if (c == '*') stars.add(index)}
    return stars
}

private fun Pair<Int, Int>.gearRatio(possibleGears: Map<Int, Map<Int, Int>>) : Int? {
    val adjacentNumbers = mutableSetOf<Int>()
    for (i in this.first-1..this.first+1) {
        for(j in this.second-1..this.second+1) {
            val number = possibleGears[i]?.get(j)
            if (number != null) {
                adjacentNumbers.add(number)
            }
        }
    }

    if (adjacentNumbers.count() != 2) {
        return null
    }

    return adjacentNumbers.fold(1) {acc, next -> acc * next}
}

private fun Set<Int>.toRowCols(row: Int): List<Pair<Int, Int>> = this.map {row to it}

private class PossibleGearAccumulator() {
    private val possibleGears = mutableMapOf<Int,Int>()
    private val currentNumber = StringBuilder()
    private var currentCol = 0
    private var currentStartCol = 0
    private var currentEndCol = 0
    private var currentState = State.OUT_NUMBER

    private enum class State {
        IN_NUMBER, OUT_NUMBER
    }

    fun nextChar(character: Char) {
        when {
            (character in '0'..'9') and (currentState == State.OUT_NUMBER) -> {
                currentState = State.IN_NUMBER
                currentNumber.append(character)
                currentStartCol = currentCol
                currentEndCol = currentCol
            }

            (character in '0'..'9') and (currentState == State.IN_NUMBER) -> {
                currentNumber.append(character)
                currentEndCol = currentCol
            }

            (character !in '0'..'9') and (currentState == State.IN_NUMBER) -> {
                currentState = State.OUT_NUMBER
                recordPossiblePN()
                currentNumber.clear()
            }
        }
        currentCol++
    }

    private fun recordPossiblePN() {
        val number = currentNumber.toString().toInt()
        for (i in currentStartCol..currentEndCol) {
           possibleGears[i] = number
        }
    }

    fun end(): Map<Int, Int> {
        if (currentState == State.IN_NUMBER) {
            recordPossiblePN()
        }
        return possibleGears
    }
}

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

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day3/part_numbers.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 sumGearRatios:(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 Part Number Sum:
     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 sumGearRatios(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: new           #106                // class java/util/LinkedHashMap
       3: dup
       4: invokespecial #107                // Method java/util/LinkedHashMap."<init>":()V
       7: checkcast     #109                // class java/util/Map
      10: astore_1
      11: new           #106                // class java/util/LinkedHashMap
      14: dup
      15: invokespecial #107                // Method java/util/LinkedHashMap."<init>":()V
      18: checkcast     #109                // class java/util/Map
      21: astore_2
      22: aload_0
      23: astore_3
      24: iconst_0
      25: istore        4
      27: iconst_0
      28: istore        5
      30: aload_3
      31: invokeinterface #113,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      36: astore        6
      38: aload         6
      40: invokeinterface #119,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      45: ifeq          140
      48: aload         6
      50: invokeinterface #123,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      55: astore        7
      57: iload         5
      59: iinc          5, 1
      62: istore        8
      64: iload         8
      66: ifge          72
      69: invokestatic  #128                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      72: iload         8
      74: aload         7
      76: checkcast     #130                // class java/lang/String
      79: astore        9
      81: istore        10
      83: iconst_0
      84: istore        11
      86: aload         9
      88: invokestatic  #134                // Method parseLine:(Ljava/lang/String;)Lproblems/day3/part2/LineResult;
      91: astore        12
      93: iload         10
      95: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      98: astore        13
     100: aload_1
     101: aload         13
     103: aload         12
     105: invokevirtual #146                // Method problems/day3/part2/LineResult.getPossibleGears:()Ljava/util/Map;
     108: invokeinterface #150,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     113: pop
     114: iload         10
     116: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     119: astore        13
     121: aload_2
     122: aload         13
     124: aload         12
     126: invokevirtual #154                // Method problems/day3/part2/LineResult.getStars:()Ljava/util/Set;
     129: invokeinterface #150,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     134: pop
     135: nop
     136: nop
     137: goto          38
     140: nop
     141: aload_2
     142: astore_3
     143: iconst_0
     144: istore        4
     146: aload_3
     147: astore        5
     149: new           #156                // class java/util/ArrayList
     152: dup
     153: invokespecial #157                // Method java/util/ArrayList."<init>":()V
     156: checkcast     #159                // class java/util/Collection
     159: astore        6
     161: iconst_0
     162: istore        7
     164: aload         5
     166: invokeinterface #162,  1          // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
     171: invokeinterface #165,  1          // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
     176: astore        8
     178: aload         8
     180: invokeinterface #119,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     185: ifeq          249
     188: aload         8
     190: invokeinterface #123,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     195: checkcast     #167                // class java/util/Map$Entry
     198: astore        9
     200: aload         9
     202: astore        10
     204: iconst_0
     205: istore        11
     207: aload         10
     209: invokeinterface #170,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     214: checkcast     #164                // class java/util/Set
     217: aload         10
     219: invokeinterface #173,  1          // InterfaceMethod java/util/Map$Entry.getKey:()Ljava/lang/Object;
     224: checkcast     #175                // class java/lang/Number
     227: invokevirtual #179                // Method java/lang/Number.intValue:()I
     230: invokestatic  #183                // Method toRowCols:(Ljava/util/Set;I)Ljava/util/List;
     233: checkcast     #185                // class java/lang/Iterable
     236: astore        10
     238: aload         6
     240: aload         10
     242: invokestatic  #189                // Method kotlin/collections/CollectionsKt.addAll:(Ljava/util/Collection;Ljava/lang/Iterable;)Z
     245: pop
     246: goto          178
     249: aload         6
     251: checkcast     #191                // class java/util/List
     254: nop
     255: checkcast     #185                // class java/lang/Iterable
     258: astore_3
     259: nop
     260: iconst_0
     261: istore        4
     263: aload_3
     264: astore        5
     266: new           #156                // class java/util/ArrayList
     269: dup
     270: invokespecial #157                // Method java/util/ArrayList."<init>":()V
     273: checkcast     #159                // class java/util/Collection
     276: astore        6
     278: iconst_0
     279: istore        7
     281: aload         5
     283: astore        8
     285: iconst_0
     286: istore        9
     288: aload         8
     290: invokeinterface #192,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     295: astore        10
     297: aload         10
     299: invokeinterface #119,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     304: ifeq          366
     307: aload         10
     309: invokeinterface #123,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     314: astore        11
     316: aload         11
     318: astore        12
     320: iconst_0
     321: istore        13
     323: aload         12
     325: checkcast     #194                // class kotlin/Pair
     328: astore        14
     330: iconst_0
     331: istore        15
     333: aload         14
     335: aload_1
     336: invokestatic  #198                // Method gearRatio:(Lkotlin/Pair;Ljava/util/Map;)Ljava/lang/Integer;
     339: dup
     340: ifnull        361
     343: astore        16
     345: iconst_0
     346: istore        17
     348: aload         6
     350: aload         16
     352: invokeinterface #202,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     357: pop
     358: goto          362
     361: pop
     362: nop
     363: goto          297
     366: nop
     367: aload         6
     369: checkcast     #191                // class java/util/List
     372: nop
     373: checkcast     #185                // class java/lang/Iterable
     376: invokestatic  #206                // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
     379: ireturn

  private static final problems.day3.part2.LineResult parseLine(java.lang.String);
    Code:
       0: new           #142                // class problems/day3/part2/LineResult
       3: dup
       4: aload_0
       5: invokestatic  #248                // Method accumulateNumbers:(Ljava/lang/String;)Ljava/util/Map;
       8: aload_0
       9: invokestatic  #252                // Method recordStarts:(Ljava/lang/String;)Ljava/util/Set;
      12: invokespecial #255                // Method problems/day3/part2/LineResult."<init>":(Ljava/util/Map;Ljava/util/Set;)V
      15: areturn

  private static final java.util.Map<java.lang.Integer, java.lang.Integer> accumulateNumbers(java.lang.String);
    Code:
       0: new           #258                // class problems/day3/part2/PossibleGearAccumulator
       3: dup
       4: invokespecial #259                // Method problems/day3/part2/PossibleGearAccumulator."<init>":()V
       7: astore_1
       8: aload_0
       9: checkcast     #261                // class java/lang/CharSequence
      12: astore_2
      13: iconst_0
      14: istore_3
      15: iconst_0
      16: istore        4
      18: iload         4
      20: aload_2
      21: invokeinterface #264,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      26: if_icmpge     59
      29: aload_2
      30: iload         4
      32: invokeinterface #268,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      37: istore        5
      39: iload         5
      41: istore        6
      43: iconst_0
      44: istore        7
      46: aload_1
      47: iload         6
      49: invokevirtual #272                // Method problems/day3/part2/PossibleGearAccumulator.nextChar:(C)V
      52: nop
      53: iinc          4, 1
      56: goto          18
      59: nop
      60: aload_1
      61: invokevirtual #275                // Method problems/day3/part2/PossibleGearAccumulator.end:()Ljava/util/Map;
      64: areturn

  private static final java.util.Set<java.lang.Integer> recordStarts(java.lang.String);
    Code:
       0: new           #285                // class java/util/LinkedHashSet
       3: dup
       4: invokespecial #286                // Method java/util/LinkedHashSet."<init>":()V
       7: checkcast     #164                // class java/util/Set
      10: astore_1
      11: aload_0
      12: checkcast     #261                // class java/lang/CharSequence
      15: astore_2
      16: iconst_0
      17: istore_3
      18: iconst_0
      19: istore        4
      21: iconst_0
      22: istore        5
      24: iload         5
      26: aload_2
      27: invokeinterface #264,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      32: if_icmpge     85
      35: aload_2
      36: iload         5
      38: invokeinterface #268,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      43: istore        6
      45: iload         4
      47: iinc          4, 1
      50: iload         6
      52: istore        7
      54: istore        8
      56: iconst_0
      57: istore        9
      59: iload         7
      61: bipush        42
      63: if_icmpne     78
      66: aload_1
      67: iload         8
      69: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      72: invokeinterface #287,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      77: pop
      78: nop
      79: iinc          5, 1
      82: goto          24
      85: nop
      86: aload_1
      87: areturn

  private static final java.lang.Integer gearRatio(kotlin.Pair<java.lang.Integer, java.lang.Integer>, java.util.Map<java.lang.Integer, ? extends java.util.Map<java.lang.Integer, java.lang.Integer>>);
    Code:
       0: new           #285                // class java/util/LinkedHashSet
       3: dup
       4: invokespecial #286                // Method java/util/LinkedHashSet."<init>":()V
       7: checkcast     #164                // class java/util/Set
      10: astore_2
      11: aload_0
      12: invokevirtual #295                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      15: checkcast     #175                // class java/lang/Number
      18: invokevirtual #179                // Method java/lang/Number.intValue:()I
      21: iconst_1
      22: isub
      23: istore_3
      24: aload_0
      25: invokevirtual #295                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      28: checkcast     #175                // class java/lang/Number
      31: invokevirtual #179                // Method java/lang/Number.intValue:()I
      34: iconst_1
      35: iadd
      36: istore        4
      38: iload_3
      39: iload         4
      41: if_icmpgt     155
      44: aload_0
      45: invokevirtual #298                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      48: checkcast     #175                // class java/lang/Number
      51: invokevirtual #179                // Method java/lang/Number.intValue:()I
      54: iconst_1
      55: isub
      56: istore        5
      58: aload_0
      59: invokevirtual #298                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      62: checkcast     #175                // class java/lang/Number
      65: invokevirtual #179                // Method java/lang/Number.intValue:()I
      68: iconst_1
      69: iadd
      70: istore        6
      72: iload         5
      74: iload         6
      76: if_icmpgt     143
      79: aload_1
      80: iload_3
      81: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      84: invokeinterface #302,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      89: checkcast     #109                // class java/util/Map
      92: dup
      93: ifnull        112
      96: iload         5
      98: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     101: invokeinterface #302,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     106: checkcast     #136                // class java/lang/Integer
     109: goto          114
     112: pop
     113: aconst_null
     114: astore        7
     116: aload         7
     118: ifnull        130
     121: aload_2
     122: aload         7
     124: invokeinterface #287,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
     129: pop
     130: iload         5
     132: iload         6
     134: if_icmpeq     143
     137: iinc          5, 1
     140: goto          79
     143: iload_3
     144: iload         4
     146: if_icmpeq     155
     149: iinc          3, 1
     152: goto          44
     155: aload_2
     156: checkcast     #159                // class java/util/Collection
     159: invokeinterface #305,  1          // InterfaceMethod java/util/Collection.size:()I
     164: iconst_2
     165: if_icmpeq     170
     168: aconst_null
     169: areturn
     170: aload_2
     171: checkcast     #185                // class java/lang/Iterable
     174: astore_3
     175: iconst_1
     176: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     179: astore        4
     181: iconst_0
     182: istore        5
     184: aload         4
     186: astore        6
     188: aload_3
     189: invokeinterface #192,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     194: astore        7
     196: aload         7
     198: invokeinterface #119,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     203: ifeq          251
     206: aload         7
     208: invokeinterface #123,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     213: astore        8
     215: aload         6
     217: aload         8
     219: checkcast     #175                // class java/lang/Number
     222: invokevirtual #179                // Method java/lang/Number.intValue:()I
     225: istore        9
     227: checkcast     #175                // class java/lang/Number
     230: invokevirtual #179                // Method java/lang/Number.intValue:()I
     233: istore        10
     235: iconst_0
     236: istore        11
     238: iload         10
     240: iload         9
     242: imul
     243: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     246: astore        6
     248: goto          196
     251: aload         6
     253: areturn

  private static final java.util.List<kotlin.Pair<java.lang.Integer, java.lang.Integer>> toRowCols(java.util.Set<java.lang.Integer>, int);
    Code:
       0: aload_0
       1: checkcast     #185                // class java/lang/Iterable
       4: astore_2
       5: iconst_0
       6: istore_3
       7: aload_2
       8: astore        4
      10: new           #156                // class java/util/ArrayList
      13: dup
      14: aload_2
      15: bipush        10
      17: invokestatic  #322                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      20: invokespecial #325                // Method java/util/ArrayList."<init>":(I)V
      23: checkcast     #159                // class java/util/Collection
      26: astore        5
      28: iconst_0
      29: istore        6
      31: aload         4
      33: invokeinterface #192,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      38: astore        7
      40: aload         7
      42: invokeinterface #119,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      47: ifeq          100
      50: aload         7
      52: invokeinterface #123,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      57: astore        8
      59: aload         5
      61: aload         8
      63: checkcast     #175                // class java/lang/Number
      66: invokevirtual #179                // Method java/lang/Number.intValue:()I
      69: istore        9
      71: astore        11
      73: iconst_0
      74: istore        10
      76: iload_1
      77: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      80: iload         9
      82: invokestatic  #140                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      85: invokestatic  #331                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      88: aload         11
      90: swap
      91: invokeinterface #202,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      96: pop
      97: goto          40
     100: aload         5
     102: checkcast     #191                // class java/util/List
     105: nop
     106: areturn

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


package problems.day3.part1

import java.io.File

//private const val testFile = "input/day3/test.txt"
private const val part_numbers = "input/day3/part_numbers.txt"

fun main() {
    val partNumberSum = File(part_numbers).bufferedReader().useLines { sumPartNumbers(it) }
    println("Part Number Sum: $partNumberSum")
}

private fun sumPartNumbers(lines: Sequence<String>): Int {
    val possiblePNs: MutableList<PossiblePN> = mutableListOf()
    val symbols: MutableMap<Int, Set<Int>> = mutableMapOf()
    lines.forEachIndexed {row, line ->
        val res = parseLine(line, row)
        possiblePNs.addAll(res.possiblePNs)
        symbols[row] = res.symbols
    }

    return possiblePNs.filter { it.adjacentToSymbol(symbols) }.sumOf { it.value }
}

private fun parseLine(line: String, row: Int) = LineResult(
    accumulateNumbers(line, row),
    recordSymbols(line),
)

private fun accumulateNumbers(line: String, row: Int): List<PossiblePN> {
    val accumulator = PossiblePNAccumulator(row)
    line.forEach { accumulator.nextChar(it) }
    return accumulator.end()
}

private fun recordSymbols(line: String): Set<Int> {
    val symbols = mutableSetOf<Int>()
    line.forEachIndexed { index, c ->  if (c.isSymbol()) symbols.add(index)}
    return symbols
}

private fun Char.isSymbol() = (this !in '0'..'9') and (this != '.')

private data class PossiblePN(val value: Int, val row: Int, val startCol: Int, val endCol: Int) {
    fun adjacentToSymbol(symbols: Map<Int, Set<Int>>): Boolean {
        return aboveRowContainsSymbol(symbols) or
                rowContainsSymbol(symbols) or
                belowRowContainsSymbols(symbols)
    }

    private fun aboveRowContainsSymbol(symbols: Map<Int, Set<Int>>) = checkRowSegment(symbols, row - 1)

    private fun rowContainsSymbol(symbols: Map<Int, Set<Int>>): Boolean {
        val targetRow = symbols[row] ?: return false
        return targetRow.contains(startCol - 1) or targetRow.contains(endCol + 1)
    }

    private fun belowRowContainsSymbols(symbols: Map<Int, Set<Int>>) = checkRowSegment(symbols, row + 1)

    private fun checkRowSegment(symbols: Map<Int, Set<Int>>, row: Int): Boolean {
        val targetRow = symbols[row] ?: return false
        for (col in startCol - 1..endCol + 1) {
            if (targetRow.contains(col)) return true
        }
        return false
    }
}

private data class LineResult(val possiblePNs: List<PossiblePN>, val symbols: Set<Int>)

private class PossiblePNAccumulator(private val row: Int) {
    private val possiblePNs = mutableListOf<PossiblePN>()
    private val currentNumber = StringBuilder()
    private var currentCol = 0
    private var currentStartCol = 0
    private var currentEndCol = 0
    private var currentState = State.OUT_NUMBER

    private enum class State {
        IN_NUMBER, OUT_NUMBER
    }

    fun nextChar(character: Char) {
        when {
            (character in '0'..'9') and (currentState == State.OUT_NUMBER) -> {
                currentState = State.IN_NUMBER
                currentNumber.append(character)
                currentStartCol = currentCol
                currentEndCol = currentCol
            }

            (character in '0'..'9') and (currentState == State.IN_NUMBER) -> {
                currentNumber.append(character)
                currentEndCol = currentCol
            }

            (character !in '0'..'9') and (currentState == State.IN_NUMBER) -> {
                currentState = State.OUT_NUMBER
                recordPossiblePN()
                currentNumber.clear()
            }
        }
        currentCol++
    }

    private fun recordPossiblePN() {
        possiblePNs.add(
            PossiblePN(
                value = currentNumber.toString().toInt(),
                row = row,
                startCol = currentStartCol,
                endCol = currentEndCol,
            )
        )
    }

    fun end(): List<PossiblePN> {
        if (currentState == State.IN_NUMBER) {
            recordPossiblePN()
        }
        return possiblePNs
    }
}

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

  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String input/day3/part_numbers.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 sumPartNumbers:(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 Part Number Sum:
     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 sumPartNumbers(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: new           #106                // class java/util/ArrayList
       3: dup
       4: invokespecial #107                // Method java/util/ArrayList."<init>":()V
       7: checkcast     #109                // class java/util/List
      10: astore_1
      11: new           #111                // class java/util/LinkedHashMap
      14: dup
      15: invokespecial #112                // Method java/util/LinkedHashMap."<init>":()V
      18: checkcast     #114                // class java/util/Map
      21: astore_2
      22: aload_0
      23: astore_3
      24: iconst_0
      25: istore        4
      27: iconst_0
      28: istore        5
      30: aload_3
      31: invokeinterface #118,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      36: astore        6
      38: aload         6
      40: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      45: ifeq          136
      48: aload         6
      50: invokeinterface #128,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      55: astore        7
      57: iload         5
      59: iinc          5, 1
      62: istore        8
      64: iload         8
      66: ifge          72
      69: invokestatic  #133                // Method kotlin/collections/CollectionsKt.throwIndexOverflow:()V
      72: iload         8
      74: aload         7
      76: checkcast     #135                // class java/lang/String
      79: astore        9
      81: istore        10
      83: iconst_0
      84: istore        11
      86: aload         9
      88: iload         10
      90: invokestatic  #139                // Method parseLine:(Ljava/lang/String;I)Lproblems/day3/part1/LineResult;
      93: astore        12
      95: aload_1
      96: aload         12
      98: invokevirtual #145                // Method problems/day3/part1/LineResult.getPossiblePNs:()Ljava/util/List;
     101: checkcast     #147                // class java/util/Collection
     104: invokeinterface #151,  2          // InterfaceMethod java/util/List.addAll:(Ljava/util/Collection;)Z
     109: pop
     110: iload         10
     112: invokestatic  #157                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     115: astore        13
     117: aload_2
     118: aload         13
     120: aload         12
     122: invokevirtual #161                // Method problems/day3/part1/LineResult.getSymbols:()Ljava/util/Set;
     125: invokeinterface #165,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     130: pop
     131: nop
     132: nop
     133: goto          38
     136: nop
     137: aload_1
     138: checkcast     #167                // class java/lang/Iterable
     141: astore_3
     142: iconst_0
     143: istore        4
     145: aload_3
     146: astore        5
     148: new           #106                // class java/util/ArrayList
     151: dup
     152: invokespecial #107                // Method java/util/ArrayList."<init>":()V
     155: checkcast     #147                // class java/util/Collection
     158: astore        6
     160: iconst_0
     161: istore        7
     163: aload         5
     165: invokeinterface #168,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     170: astore        8
     172: aload         8
     174: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     179: ifeq          223
     182: aload         8
     184: invokeinterface #128,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     189: astore        9
     191: aload         9
     193: checkcast     #170                // class problems/day3/part1/PossiblePN
     196: astore        10
     198: iconst_0
     199: istore        11
     201: aload         10
     203: aload_2
     204: invokevirtual #174                // Method problems/day3/part1/PossiblePN.adjacentToSymbol:(Ljava/util/Map;)Z
     207: ifeq          172
     210: aload         6
     212: aload         9
     214: invokeinterface #178,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     219: pop
     220: goto          172
     223: aload         6
     225: checkcast     #109                // class java/util/List
     228: nop
     229: checkcast     #167                // class java/lang/Iterable
     232: astore_3
     233: iconst_0
     234: istore        4
     236: aload_3
     237: invokeinterface #168,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     242: astore        5
     244: aload         5
     246: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     251: ifeq          294
     254: aload         5
     256: invokeinterface #128,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     261: astore        6
     263: iload         4
     265: aload         6
     267: checkcast     #170                // class problems/day3/part1/PossiblePN
     270: astore        7
     272: istore        14
     274: iconst_0
     275: istore        8
     277: aload         7
     279: invokevirtual #182                // Method problems/day3/part1/PossiblePN.getValue:()I
     282: istore        15
     284: iload         14
     286: iload         15
     288: iadd
     289: istore        4
     291: goto          244
     294: iload         4
     296: ireturn

  private static final problems.day3.part1.LineResult parseLine(java.lang.String, int);
    Code:
       0: new           #141                // class problems/day3/part1/LineResult
       3: dup
       4: aload_0
       5: iload_1
       6: invokestatic  #213                // Method accumulateNumbers:(Ljava/lang/String;I)Ljava/util/List;
       9: aload_0
      10: invokestatic  #217                // Method recordSymbols:(Ljava/lang/String;)Ljava/util/Set;
      13: invokespecial #220                // Method problems/day3/part1/LineResult."<init>":(Ljava/util/List;Ljava/util/Set;)V
      16: areturn

  private static final java.util.List<problems.day3.part1.PossiblePN> accumulateNumbers(java.lang.String, int);
    Code:
       0: new           #223                // class problems/day3/part1/PossiblePNAccumulator
       3: dup
       4: iload_1
       5: invokespecial #226                // Method problems/day3/part1/PossiblePNAccumulator."<init>":(I)V
       8: astore_2
       9: aload_0
      10: checkcast     #228                // class java/lang/CharSequence
      13: astore_3
      14: iconst_0
      15: istore        4
      17: iconst_0
      18: istore        5
      20: iload         5
      22: aload_3
      23: invokeinterface #231,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      28: if_icmpge     61
      31: aload_3
      32: iload         5
      34: invokeinterface #235,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      39: istore        6
      41: iload         6
      43: istore        7
      45: iconst_0
      46: istore        8
      48: aload_2
      49: iload         7
      51: invokevirtual #239                // Method problems/day3/part1/PossiblePNAccumulator.nextChar:(C)V
      54: nop
      55: iinc          5, 1
      58: goto          20
      61: nop
      62: aload_2
      63: invokevirtual #242                // Method problems/day3/part1/PossiblePNAccumulator.end:()Ljava/util/List;
      66: areturn

  private static final java.util.Set<java.lang.Integer> recordSymbols(java.lang.String);
    Code:
       0: new           #253                // class java/util/LinkedHashSet
       3: dup
       4: invokespecial #254                // Method java/util/LinkedHashSet."<init>":()V
       7: checkcast     #256                // class java/util/Set
      10: astore_1
      11: aload_0
      12: checkcast     #228                // class java/lang/CharSequence
      15: astore_2
      16: iconst_0
      17: istore_3
      18: iconst_0
      19: istore        4
      21: iconst_0
      22: istore        5
      24: iload         5
      26: aload_2
      27: invokeinterface #231,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      32: if_icmpge     86
      35: aload_2
      36: iload         5
      38: invokeinterface #235,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      43: istore        6
      45: iload         4
      47: iinc          4, 1
      50: iload         6
      52: istore        7
      54: istore        8
      56: iconst_0
      57: istore        9
      59: iload         7
      61: invokestatic  #260                // Method isSymbol:(C)Z
      64: ifeq          79
      67: aload_1
      68: iload         8
      70: invokestatic  #157                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      73: invokeinterface #261,  2          // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
      78: pop
      79: nop
      80: iinc          5, 1
      83: goto          24
      86: nop
      87: aload_1
      88: areturn

  private static final boolean isSymbol(char);
    Code:
       0: bipush        48
       2: iload_0
       3: if_icmpgt     20
       6: iload_0
       7: bipush        58
       9: if_icmpge     16
      12: iconst_1
      13: goto          21
      16: iconst_0
      17: goto          21
      20: iconst_0
      21: ifne          28
      24: iconst_1
      25: goto          29
      28: iconst_0
      29: iload_0
      30: bipush        46
      32: if_icmpeq     39
      35: iconst_1
      36: goto          40
      39: iconst_0
      40: iand
      41: ireturn

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


package problems.day5.part2

import java.io.File
import java.util.*

//const val testFile = "input/day5/test.txt"
const val inputFile = "input/day5/input.txt"

fun main() {
    val lowestLocationNum = File(inputFile).bufferedReader().useLines { lowestLocationNumber(it) }
    println("Lowest Location Num: $lowestLocationNum")
}

private fun lowestLocationNumber(lines: Sequence<String>): Long? {
    val almanac = lines.fold(AlmanacBuilder()) { builder, line -> builder.nextLine(line) }.build()
    for (i in 0..<Long.MAX_VALUE) {
        if (almanac.locationHasSeed(i)) {
            return i
        }
    }
    return null
}

private class Almanac(val seeds: TreeMap<Long,Long>, val reverseMaps: Map<String, OverrideMap>) {
    fun locationHasSeed(location: Long): Boolean {
        val humidity = reverseMaps["humidity-to-location"]?.get(location) ?: return false
        val temperature = reverseMaps["temperature-to-humidity"]?.get(humidity) ?: return false
        val light = reverseMaps["light-to-temperature"]?.get(temperature) ?: return false
        val water = reverseMaps["water-to-light"]?.get(light) ?: return false
        val fertilizer = reverseMaps["fertilizer-to-water"]?.get(water) ?: return false
        val soil = reverseMaps["soil-to-fertilizer"]?.get(fertilizer) ?: return false
        val seed = reverseMaps["seed-to-soil"]?.get(soil) ?: return false
        val floorSeed = seeds.floorEntry(seed) ?: return false
        return floorSeed.key <= seed && seed <= floorSeed.value
    }
}

private class AlmanacBuilder {
    private var state = State.SEEDS
    private var currentMapName = ""
    private var currentMap = TreeMap<Long, Override>()
    private val maps = mutableMapOf<String, OverrideMap>()
    private val seeds = TreeMap<Long, Long>()

    fun nextLine(line: String): AlmanacBuilder {
        when (state) {
            State.SEEDS -> {
                seeds.putAll(line.toSeeds())
                state = State.SEEDS_BLANK
            }

            State.SEEDS_BLANK -> state = State.HEADER
            State.HEADER -> {
                currentMapName = line.substringBefore(" ")
                currentMap = TreeMap<Long, Override>()
                state = State.MAP
            }

            State.MAP -> {
                if (line != "") {
                    addOverride(line)
                } else {
                    recordMap()
                    state = State.HEADER
                }
            }
        }
        return this
    }

    fun addOverride(line: String) {
        val overrides = line.split(" ").map { it.toLong() }
        val dstStart = overrides[0]
        val dstEnd = overrides[0] + overrides[2] - 1
        val srcStart = overrides[1]
        currentMap[dstStart] = Override(dstStart, dstEnd, srcStart)
    }

    fun recordMap() {
        maps[currentMapName] = OverrideMap(currentMap)
    }

    fun build(): Almanac {
        if (state == State.MAP) {
            recordMap()
        }
        return Almanac(seeds, maps)
    }

    private enum class State {
        SEEDS,
        SEEDS_BLANK,
        HEADER,
        MAP,
    }
}

private fun String.toSeeds(): TreeMap<Long, Long> {
    val seedRanges = TreeMap<Long,Long>()
    val pairs = this.substringAfter(":").trim().split(" ").iterator()
    while (pairs.hasNext()) {
        val start = pairs.next().toLong()
        val length = pairs.next().toLong()
        seedRanges[start] = start+length-1
    }
    return seedRanges
}

private class OverrideMap(val overrides: TreeMap<Long, Override>) {
    operator fun get(key: Long): Long {
        val possibleOverride = overrides.headMap(key, true).lastEntry()?.value ?: return key
        if (key <= possibleOverride.dstEnd) {
            return possibleOverride.srcStart + (key - possibleOverride.dstStart)
        }
        return key
    }
}

private data class Override(val dstStart: Long, val dstEnd: Long, val srcStart: Long)

Compiled from "part2.kt"
public final class problems.day5.part2.Part2Kt {
  public 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/day5/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 lowestLocationNumber:(Lkotlin/sequences/Sequence;)Ljava/lang/Long;
     142: astore        5
     144: aload_3
     145: aload         4
     147: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     150: aload         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: astore_0
     177: new           #61                 // class java/lang/StringBuilder
     180: dup
     181: invokespecial #63                 // Method java/lang/StringBuilder."<init>":()V
     184: ldc           #65                 // String Lowest Location Num:
     186: invokevirtual #69                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     189: aload_0
     190: invokevirtual #72                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)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 java.lang.Long lowestLocationNumber(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: astore_2
       2: new           #109                // class problems/day5/part2/AlmanacBuilder
       5: dup
       6: invokespecial #110                // Method problems/day5/part2/AlmanacBuilder."<init>":()V
       9: astore_3
      10: iconst_0
      11: istore        4
      13: aload_3
      14: astore        5
      16: aload_2
      17: invokeinterface #114,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      22: astore        6
      24: aload         6
      26: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      31: ifeq          69
      34: aload         6
      36: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      41: astore        7
      43: aload         5
      45: aload         7
      47: checkcast     #126                // class java/lang/String
      50: astore        8
      52: astore        9
      54: iconst_0
      55: istore        10
      57: aload         9
      59: aload         8
      61: invokevirtual #130                // Method problems/day5/part2/AlmanacBuilder.nextLine:(Ljava/lang/String;)Lproblems/day5/part2/AlmanacBuilder;
      64: astore        5
      66: goto          24
      69: aload         5
      71: invokevirtual #134                // Method problems/day5/part2/AlmanacBuilder.build:()Lproblems/day5/part2/Almanac;
      74: astore_1
      75: lconst_0
      76: lstore_2
      77: lload_2
      78: ldc2_w        #135                // long 9223372036854775807l
      81: lcmp
      82: ifge          105
      85: aload_1
      86: lload_2
      87: invokevirtual #142                // Method problems/day5/part2/Almanac.locationHasSeed:(J)Z
      90: ifeq          98
      93: lload_2
      94: invokestatic  #146                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      97: areturn
      98: lload_2
      99: lconst_1
     100: ladd
     101: lstore_2
     102: goto          77
     105: aconst_null
     106: areturn

  private static final java.util.TreeMap<java.lang.Long, java.lang.Long> toSeeds(java.lang.String);
    Code:
       0: new           #167                // class java/util/TreeMap
       3: dup
       4: invokespecial #168                // Method java/util/TreeMap."<init>":()V
       7: astore_1
       8: aload_0
       9: ldc           #170                // String :
      11: aconst_null
      12: iconst_2
      13: aconst_null
      14: invokestatic  #176                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      17: checkcast     #178                // class java/lang/CharSequence
      20: invokestatic  #182                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      23: invokevirtual #183                // Method java/lang/Object.toString:()Ljava/lang/String;
      26: checkcast     #178                // class java/lang/CharSequence
      29: iconst_1
      30: anewarray     #126                // class java/lang/String
      33: astore_3
      34: aload_3
      35: iconst_0
      36: ldc           #185                // String
      38: aastore
      39: aload_3
      40: iconst_0
      41: iconst_0
      42: bipush        6
      44: aconst_null
      45: invokestatic  #189                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      48: invokeinterface #192,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      53: astore_2
      54: aload_2
      55: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      60: ifeq          120
      63: aload_2
      64: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      69: checkcast     #126                // class java/lang/String
      72: invokestatic  #196                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
      75: lstore_3
      76: aload_2
      77: invokeinterface #124,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      82: checkcast     #126                // class java/lang/String
      85: invokestatic  #196                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
      88: lstore        5
      90: lload_3
      91: invokestatic  #146                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      94: astore        7
      96: aload_1
      97: checkcast     #198                // class java/util/Map
     100: aload         7
     102: lload_3
     103: lload         5
     105: ladd
     106: lconst_1
     107: lsub
     108: invokestatic  #146                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     111: invokeinterface #202,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     116: pop
     117: goto          54
     120: aload_1
     121: areturn

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

  public static final java.util.TreeMap access$toSeeds(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #217                // Method toSeeds:(Ljava/lang/String;)Ljava/util/TreeMap;
       4: areturn
}


package problems.day5.part1

import java.io.File
import java.util.*

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

fun main() {
    val lowestLocationNum = File(inputFile).bufferedReader().useLines { lowestLocationNumber(it) }
    println("Lowest Location Num: $lowestLocationNum")
}

private fun lowestLocationNumber(lines: Sequence<String>): Long {
    val almanac = lines.fold(AlmanacBuilder()) { builder, line -> builder.nextLine(line) }.build()
    return almanac.seeds.mapNotNull { almanac.seedLocation(it) }.min()
}

private class Almanac(val seeds: List<Long>, val maps: Map<String, OverrideMap>) {
    fun seedLocation(seed: Long): Long? {
        val soil = maps["seed-to-soil"]?.get(seed) ?: return null
        val fertilizer = maps["soil-to-fertilizer"]?.get(soil) ?: return null
        val water = maps["fertilizer-to-water"]?.get(fertilizer) ?: return null
        val light = maps["water-to-light"]?.get(water) ?: return null
        val temperature = maps["light-to-temperature"]?.get(light) ?: return null
        val humidity = maps["temperature-to-humidity"]?.get(temperature) ?: return null
        val location = maps["humidity-to-location"]?.get(humidity) ?: return null
        return location
    }
}

private class AlmanacBuilder {
    private var state = State.SEEDS
    private var currentMapName = ""
    private var currentMap = TreeMap<Long, Override>()
    private val maps = mutableMapOf<String, OverrideMap>()
    private val seeds = mutableListOf<Long>()

    fun nextLine(line: String): AlmanacBuilder {
        when (state) {
            State.SEEDS -> {
                seeds.addAll(line.toSeeds())
                state = State.SEEDS_BLANK
            }

            State.SEEDS_BLANK -> state = State.HEADER
            State.HEADER -> {
                currentMapName = line.substringBefore(" ")
                currentMap = TreeMap<Long, Override>()
                state = State.MAP
            }

            State.MAP -> {
                if (line != "") {
                    addOverride(line)
                } else {
                    recordMap()
                    state = State.HEADER
                }
            }
        }
        return this
    }

    fun addOverride(line: String) {
        val overrides = line.split(" ").map { it.toLong() }
        val srcStart = overrides[1]
        val srcEnd = overrides[1] + overrides[2] - 1
        val dstStart = overrides[0]
        currentMap[srcStart] = Override(srcStart, srcEnd, dstStart)
    }

    fun recordMap() {
        maps[currentMapName] = OverrideMap(currentMap)
    }

    fun build(): Almanac {
        if (state == State.MAP) {
            recordMap()
        }
        return Almanac(seeds, maps)
    }

    private enum class State {
        SEEDS,
        SEEDS_BLANK,
        HEADER,
        MAP,
    }
}

private fun String.toSeeds() = this.substringAfter(":").trim().split(" ").map { it.toLong() }

private class OverrideMap(val overrides: TreeMap<Long, Override>) {
    operator fun get(key: Long): Long {
        val possibleOverride = overrides.headMap(key, true).lastEntry()?.value ?: return key
        if (key <= possibleOverride.srcEnd) {
            return possibleOverride.dstStart + (key - possibleOverride.srcStart)
        }
        return key
    }
}

private data class Override(val srcStart: Long, val srcEnd: Long, val dstStart: Long)

Compiled from "part1.kt"
public final class problems.day5.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/day5/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 lowestLocationNumber:(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 Lowest Location Num:
     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 lowestLocationNumber(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: astore_2
       2: new           #107                // class problems/day5/part1/AlmanacBuilder
       5: dup
       6: invokespecial #108                // Method problems/day5/part1/AlmanacBuilder."<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/day5/part1/AlmanacBuilder.nextLine:(Ljava/lang/String;)Lproblems/day5/part1/AlmanacBuilder;
      64: astore        5
      66: goto          24
      69: aload         5
      71: invokevirtual #132                // Method problems/day5/part1/AlmanacBuilder.build:()Lproblems/day5/part1/Almanac;
      74: astore_1
      75: aload_1
      76: invokevirtual #138                // Method problems/day5/part1/Almanac.getSeeds:()Ljava/util/List;
      79: checkcast     #140                // class java/lang/Iterable
      82: astore_2
      83: iconst_0
      84: istore_3
      85: aload_2
      86: astore        4
      88: new           #142                // class java/util/ArrayList
      91: dup
      92: invokespecial #143                // Method java/util/ArrayList."<init>":()V
      95: checkcast     #145                // class java/util/Collection
      98: astore        5
     100: iconst_0
     101: istore        6
     103: aload         4
     105: astore        7
     107: iconst_0
     108: istore        8
     110: aload         7
     112: invokeinterface #146,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     117: astore        9
     119: aload         9
     121: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     126: ifeq          191
     129: aload         9
     131: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     136: astore        10
     138: aload         10
     140: astore        11
     142: iconst_0
     143: istore        12
     145: aload         11
     147: checkcast     #148                // class java/lang/Number
     150: invokevirtual #152                // Method java/lang/Number.longValue:()J
     153: lstore        13
     155: iconst_0
     156: istore        15
     158: aload_1
     159: lload         13
     161: invokevirtual #156                // Method problems/day5/part1/Almanac.seedLocation:(J)Ljava/lang/Long;
     164: dup
     165: ifnull        186
     168: astore        16
     170: iconst_0
     171: istore        17
     173: aload         5
     175: aload         16
     177: invokeinterface #160,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     182: pop
     183: goto          187
     186: pop
     187: nop
     188: goto          119
     191: nop
     192: aload         5
     194: checkcast     #162                // class java/util/List
     197: nop
     198: checkcast     #140                // class java/lang/Iterable
     201: invokestatic  #168                // Method kotlin/collections/CollectionsKt.minOrThrow:(Ljava/lang/Iterable;)Ljava/lang/Comparable;
     204: checkcast     #148                // class java/lang/Number
     207: invokevirtual #152                // Method java/lang/Number.longValue:()J
     210: lreturn

  private static final java.util.List<java.lang.Long> toSeeds(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #204                // String :
       3: aconst_null
       4: iconst_2
       5: aconst_null
       6: invokestatic  #210                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
       9: checkcast     #212                // class java/lang/CharSequence
      12: invokestatic  #216                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      15: invokevirtual #217                // Method java/lang/Object.toString:()Ljava/lang/String;
      18: checkcast     #212                // class java/lang/CharSequence
      21: iconst_1
      22: anewarray     #124                // class java/lang/String
      25: astore_1
      26: aload_1
      27: iconst_0
      28: ldc           #219                // String
      30: aastore
      31: aload_1
      32: iconst_0
      33: iconst_0
      34: bipush        6
      36: aconst_null
      37: invokestatic  #223                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      40: checkcast     #140                // class java/lang/Iterable
      43: astore_1
      44: iconst_0
      45: istore_2
      46: aload_1
      47: astore_3
      48: new           #142                // class java/util/ArrayList
      51: dup
      52: aload_1
      53: bipush        10
      55: invokestatic  #227                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      58: invokespecial #230                // Method java/util/ArrayList."<init>":(I)V
      61: checkcast     #145                // class java/util/Collection
      64: astore        4
      66: iconst_0
      67: istore        5
      69: aload_3
      70: invokeinterface #146,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      75: astore        6
      77: aload         6
      79: invokeinterface #118,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      84: ifeq          131
      87: aload         6
      89: invokeinterface #122,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      94: astore        7
      96: aload         4
      98: aload         7
     100: checkcast     #124                // class java/lang/String
     103: astore        8
     105: astore        10
     107: iconst_0
     108: istore        9
     110: aload         8
     112: invokestatic  #234                // Method java/lang/Long.parseLong:(Ljava/lang/String;)J
     115: nop
     116: invokestatic  #237                // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
     119: aload         10
     121: swap
     122: invokeinterface #160,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     127: pop
     128: goto          77
     131: aload         4
     133: checkcast     #162                // class java/util/List
     136: nop
     137: areturn

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

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