package day4

import java.io.File

class BingoBoard(private val numbers: List<List<Int>>) {
  private var visited = MutableList(numbers.size) { MutableList(numbers[0].size) { false } }

  fun visit(number: Int) {
    val traversingCellsIndices = visited.indices.flatMap { r -> visited[0].indices.map { c -> Pair(r, c) } }
    val maybeCell = traversingCellsIndices.firstOrNull { (r, c) -> numbers[r][c] == number }
    if (maybeCell != null) visited[maybeCell.first][maybeCell.second] = true
  }

  val isCompleted: Boolean
    get() = hasRowCompleted || hasColumnCompleted

  private val hasRowCompleted: Boolean
    get() = visited.any { row -> row.all { it /* it == true */ } }

  private val hasColumnCompleted: Boolean
    get() {
      val traversingColumnsIndices = visited[0].indices.map { c -> visited.indices.map { r -> Pair(r, c) } }
      return traversingColumnsIndices.any { column -> column.all { (r, c) -> visited[r][c] } }
    }

  fun sumUnvisited(): Int {
    val traversingCellsIndices = visited.indices.flatMap { r -> visited[0].indices.map { c -> Pair(r, c) } }
    return traversingCellsIndices
      .filterNot { (r, c) -> visited[r][c] }
      .sumOf { (r, c) -> numbers[r][c] }
  }
}

fun findWinnerBoardScore(drawNumbers: List<Int>, boards: List<BingoBoard>): Int {
  drawNumbers.forEach { number ->
    boards.forEach { board ->
      board.visit(number)
      if (board.isCompleted) return number * board.sumUnvisited()
    }
  }
  return 0 // should never reach this point
}

fun findLoserBoardScore(drawNumbers: List<Int>, boards: List<BingoBoard>): Int {
  val mutBoards = boards.toMutableList()
  drawNumbers.forEach { number ->
    mutBoards.forEach { board ->
      board.visit(number)
      if (mutBoards.size == 1 && board.isCompleted) return mutBoards.first().sumUnvisited() * number
    }
    mutBoards.removeAll { it.isCompleted }
  }
  return 0 // should never reach this point
}

fun parseBingoData(data: List<String>): Pair<List<Int>, List<BingoBoard>> {
  fun parseLine(line: String) = line.split(" ").filterNot(String::isEmpty).map(String::toInt)
  fun parseBoard(boardRaw: List<String>) = BingoBoard(boardRaw.map(::parseLine))

  val drawNumbers = data.first().split(",").map(String::toInt)
  val boards = data
    .drop(1) // remove draw numbers
    .filterNot(String::isBlank)
    .chunked(5)
    .map(::parseBoard)
  return Pair(drawNumbers, boards)
}

fun main() {
  File("./input/day4.txt").useLines { lines ->
    val data = lines.toList()
    val (drawNumbers, boards) = parseBingoData(data)

    println("First value: ${findWinnerBoardScore(drawNumbers, boards)}")
    println("Second value: ${findLoserBoardScore(drawNumbers, boards)}")
  }
}

Compiled from "Day4.kt"
public final class day4.Day4Kt {
  public static final int findWinnerBoardScore(java.util.List<java.lang.Integer>, java.util.List<day4.BingoBoard>);
    Code:
       0: aload_0
       1: ldc           #10                 // String drawNumbers
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #18                 // String boards
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: checkcast     #20                 // class java/lang/Iterable
      16: astore_2
      17: iconst_0
      18: istore_3
      19: aload_2
      20: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      25: astore        4
      27: aload         4
      29: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      34: ifeq          141
      37: aload         4
      39: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      44: astore        5
      46: aload         5
      48: checkcast     #36                 // class java/lang/Number
      51: invokevirtual #40                 // Method java/lang/Number.intValue:()I
      54: istore        6
      56: iconst_0
      57: istore        7
      59: aload_1
      60: checkcast     #20                 // class java/lang/Iterable
      63: astore        8
      65: iconst_0
      66: istore        9
      68: aload         8
      70: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      75: astore        10
      77: aload         10
      79: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      84: ifeq          135
      87: aload         10
      89: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      94: astore        11
      96: aload         11
      98: checkcast     #42                 // class day4/BingoBoard
     101: astore        12
     103: iconst_0
     104: istore        13
     106: aload         12
     108: iload         6
     110: invokevirtual #46                 // Method day4/BingoBoard.visit:(I)V
     113: aload         12
     115: invokevirtual #49                 // Method day4/BingoBoard.isCompleted:()Z
     118: ifeq          130
     121: iload         6
     123: aload         12
     125: invokevirtual #52                 // Method day4/BingoBoard.sumUnvisited:()I
     128: imul
     129: ireturn
     130: nop
     131: nop
     132: goto          77
     135: nop
     136: nop
     137: nop
     138: goto          27
     141: nop
     142: iconst_0
     143: ireturn

  public static final int findLoserBoardScore(java.util.List<java.lang.Integer>, java.util.List<day4.BingoBoard>);
    Code:
       0: aload_0
       1: ldc           #10                 // String drawNumbers
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #18                 // String boards
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: checkcast     #69                 // class java/util/Collection
      16: invokestatic  #75                 // Method kotlin/collections/CollectionsKt.toMutableList:(Ljava/util/Collection;)Ljava/util/List;
      19: astore_2
      20: aload_0
      21: checkcast     #20                 // class java/lang/Iterable
      24: astore_3
      25: iconst_0
      26: istore        4
      28: aload_3
      29: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      34: astore        5
      36: aload         5
      38: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      43: ifeq          175
      46: aload         5
      48: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      53: astore        6
      55: aload         6
      57: checkcast     #36                 // class java/lang/Number
      60: invokevirtual #40                 // Method java/lang/Number.intValue:()I
      63: istore        7
      65: iconst_0
      66: istore        8
      68: aload_2
      69: checkcast     #20                 // class java/lang/Iterable
      72: astore        9
      74: iconst_0
      75: istore        10
      77: aload         9
      79: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      84: astore        11
      86: aload         11
      88: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      93: ifeq          159
      96: aload         11
      98: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     103: astore        12
     105: aload         12
     107: checkcast     #42                 // class day4/BingoBoard
     110: astore        13
     112: iconst_0
     113: istore        14
     115: aload         13
     117: iload         7
     119: invokevirtual #46                 // Method day4/BingoBoard.visit:(I)V
     122: aload_2
     123: invokeinterface #78,  1           // InterfaceMethod java/util/List.size:()I
     128: iconst_1
     129: if_icmpne     154
     132: aload         13
     134: invokevirtual #49                 // Method day4/BingoBoard.isCompleted:()Z
     137: ifeq          154
     140: aload_2
     141: invokestatic  #82                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
     144: checkcast     #42                 // class day4/BingoBoard
     147: invokevirtual #52                 // Method day4/BingoBoard.sumUnvisited:()I
     150: iload         7
     152: imul
     153: ireturn
     154: nop
     155: nop
     156: goto          86
     159: nop
     160: aload_2
     161: invokedynamic #102,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
     166: invokestatic  #106                // Method kotlin/collections/CollectionsKt.removeAll:(Ljava/util/List;Lkotlin/jvm/functions/Function1;)Z
     169: pop
     170: nop
     171: nop
     172: goto          36
     175: nop
     176: iconst_0
     177: ireturn

  public static final kotlin.Pair<java.util.List<java.lang.Integer>, java.util.List<day4.BingoBoard>> parseBingoData(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #114                // String data
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #82                 // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      10: checkcast     #116                // class java/lang/CharSequence
      13: iconst_1
      14: anewarray     #118                // class java/lang/String
      17: astore_2
      18: aload_2
      19: iconst_0
      20: ldc           #120                // String ,
      22: aastore
      23: aload_2
      24: iconst_0
      25: iconst_0
      26: bipush        6
      28: aconst_null
      29: invokestatic  #126                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      32: checkcast     #20                 // class java/lang/Iterable
      35: astore_2
      36: iconst_0
      37: istore_3
      38: aload_2
      39: astore        4
      41: new           #128                // class java/util/ArrayList
      44: dup
      45: aload_2
      46: bipush        10
      48: invokestatic  #132                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      51: invokespecial #135                // Method java/util/ArrayList."<init>":(I)V
      54: checkcast     #69                 // class java/util/Collection
      57: astore        5
      59: iconst_0
      60: istore        6
      62: aload         4
      64: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      69: astore        7
      71: aload         7
      73: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      78: ifeq          125
      81: aload         7
      83: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      88: astore        8
      90: aload         5
      92: aload         8
      94: checkcast     #118                // class java/lang/String
      97: astore        9
      99: astore        12
     101: iconst_0
     102: istore        10
     104: aload         9
     106: invokestatic  #141                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     109: nop
     110: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     113: aload         12
     115: swap
     116: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     121: pop
     122: goto          71
     125: aload         5
     127: checkcast     #66                 // class java/util/List
     130: nop
     131: astore_1
     132: aload_0
     133: checkcast     #20                 // class java/lang/Iterable
     136: iconst_1
     137: invokestatic  #153                // Method kotlin/collections/CollectionsKt.drop:(Ljava/lang/Iterable;I)Ljava/util/List;
     140: checkcast     #20                 // class java/lang/Iterable
     143: astore_3
     144: nop
     145: iconst_0
     146: istore        4
     148: aload_3
     149: astore        5
     151: new           #128                // class java/util/ArrayList
     154: dup
     155: invokespecial #156                // Method java/util/ArrayList."<init>":()V
     158: checkcast     #69                 // class java/util/Collection
     161: astore        6
     163: iconst_0
     164: istore        7
     166: aload         5
     168: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     173: astore        8
     175: aload         8
     177: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     182: ifeq          228
     185: aload         8
     187: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     192: astore        9
     194: aload         9
     196: checkcast     #118                // class java/lang/String
     199: astore        10
     201: iconst_0
     202: istore        11
     204: aload         10
     206: checkcast     #116                // class java/lang/CharSequence
     209: invokestatic  #160                // Method kotlin/text/StringsKt.isBlank:(Ljava/lang/CharSequence;)Z
     212: ifne          175
     215: aload         6
     217: aload         9
     219: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     224: pop
     225: goto          175
     228: aload         6
     230: checkcast     #66                 // class java/util/List
     233: nop
     234: checkcast     #20                 // class java/lang/Iterable
     237: iconst_5
     238: invokestatic  #163                // Method kotlin/collections/CollectionsKt.chunked:(Ljava/lang/Iterable;I)Ljava/util/List;
     241: checkcast     #20                 // class java/lang/Iterable
     244: astore_3
     245: nop
     246: iconst_0
     247: istore        4
     249: aload_3
     250: astore        5
     252: new           #128                // class java/util/ArrayList
     255: dup
     256: aload_3
     257: bipush        10
     259: invokestatic  #132                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     262: invokespecial #135                // Method java/util/ArrayList."<init>":(I)V
     265: checkcast     #69                 // class java/util/Collection
     268: astore        6
     270: iconst_0
     271: istore        7
     273: aload         5
     275: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     280: astore        8
     282: aload         8
     284: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     289: ifeq          332
     292: aload         8
     294: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     299: astore        9
     301: aload         6
     303: aload         9
     305: checkcast     #66                 // class java/util/List
     308: astore        10
     310: astore        12
     312: iconst_0
     313: istore        11
     315: aload         10
     317: invokestatic  #167                // Method parseBingoData$parseBoard:(Ljava/util/List;)Lday4/BingoBoard;
     320: aload         12
     322: swap
     323: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     328: pop
     329: goto          282
     332: aload         6
     334: checkcast     #66                 // class java/util/List
     337: nop
     338: astore_2
     339: new           #169                // class kotlin/Pair
     342: dup
     343: aload_1
     344: aload_2
     345: invokespecial #172                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     348: areturn

  public static final void main();
    Code:
       0: new           #194                // class java/io/File
       3: dup
       4: ldc           #196                // String ./input/day4.txt
       6: invokespecial #199                // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_0
      10: getstatic     #205                // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_1
      14: iconst_0
      15: istore_2
      16: aload_0
      17: astore_3
      18: sipush        8192
      21: istore        4
      23: aload_3
      24: astore        5
      26: new           #207                // class java/io/InputStreamReader
      29: dup
      30: new           #209                // class java/io/FileInputStream
      33: dup
      34: aload         5
      36: invokespecial #212                // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      39: checkcast     #214                // class java/io/InputStream
      42: aload_1
      43: invokespecial #217                // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      46: checkcast     #219                // class java/io/Reader
      49: astore        5
      51: aload         5
      53: instanceof    #221                // class java/io/BufferedReader
      56: ifeq          67
      59: aload         5
      61: checkcast     #221                // class java/io/BufferedReader
      64: goto          78
      67: new           #221                // class java/io/BufferedReader
      70: dup
      71: aload         5
      73: iload         4
      75: invokespecial #224                // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      78: checkcast     #226                // class java/io/Closeable
      81: astore_3
      82: aconst_null
      83: astore        4
      85: nop
      86: aload_3
      87: checkcast     #221                // class java/io/BufferedReader
      90: astore        5
      92: iconst_0
      93: istore        6
      95: aload         5
      97: invokestatic  #232                // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     100: astore        7
     102: iconst_0
     103: istore        8
     105: aload         7
     107: invokestatic  #238                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
     110: astore        9
     112: aload         9
     114: invokestatic  #240                // Method parseBingoData:(Ljava/util/List;)Lkotlin/Pair;
     117: astore        10
     119: aload         10
     121: invokevirtual #243                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     124: checkcast     #66                 // class java/util/List
     127: astore        11
     129: aload         10
     131: invokevirtual #246                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     134: checkcast     #66                 // class java/util/List
     137: astore        12
     139: new           #248                // class java/lang/StringBuilder
     142: dup
     143: invokespecial #249                // Method java/lang/StringBuilder."<init>":()V
     146: ldc           #251                // String First value:
     148: invokevirtual #255                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     151: aload         11
     153: aload         12
     155: invokestatic  #257                // Method findWinnerBoardScore:(Ljava/util/List;Ljava/util/List;)I
     158: invokevirtual #260                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     161: invokevirtual #264                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     164: getstatic     #270                // Field java/lang/System.out:Ljava/io/PrintStream;
     167: swap
     168: invokevirtual #276                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     171: new           #248                // class java/lang/StringBuilder
     174: dup
     175: invokespecial #249                // Method java/lang/StringBuilder."<init>":()V
     178: ldc_w         #278                // String Second value:
     181: invokevirtual #255                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     184: aload         11
     186: aload         12
     188: invokestatic  #280                // Method findLoserBoardScore:(Ljava/util/List;Ljava/util/List;)I
     191: invokevirtual #260                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     194: invokevirtual #264                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     197: getstatic     #270                // Field java/lang/System.out:Ljava/io/PrintStream;
     200: swap
     201: invokevirtual #276                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     204: nop
     205: getstatic     #286                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     208: astore        5
     210: aload_3
     211: aload         4
     213: invokestatic  #292                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     216: goto          239
     219: astore        6
     221: aload         6
     223: astore        4
     225: aload         6
     227: athrow
     228: astore        6
     230: aload_3
     231: aload         4
     233: invokestatic  #292                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     236: aload         6
     238: athrow
     239: nop
     240: return
    Exception table:
       from    to  target type
          85   210   219   Class java/lang/Throwable
          85   210   228   any
         219   228   228   any
         228   230   228   any

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

  private static final boolean findLoserBoardScore$lambda$4$lambda$3(day4.BingoBoard);
    Code:
       0: aload_0
       1: ldc_w         #313                // String it
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #49                 // Method day4/BingoBoard.isCompleted:()Z
      11: ireturn

  private static final java.util.List<java.lang.Integer> parseBingoData$parseLine(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #116                // class java/lang/CharSequence
       4: iconst_1
       5: anewarray     #118                // class java/lang/String
       8: astore_1
       9: aload_1
      10: iconst_0
      11: ldc_w         #318                // String
      14: aastore
      15: aload_1
      16: iconst_0
      17: iconst_0
      18: bipush        6
      20: aconst_null
      21: invokestatic  #126                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      24: checkcast     #20                 // class java/lang/Iterable
      27: astore_1
      28: iconst_0
      29: istore_2
      30: aload_1
      31: astore_3
      32: new           #128                // class java/util/ArrayList
      35: dup
      36: invokespecial #156                // Method java/util/ArrayList."<init>":()V
      39: checkcast     #69                 // class java/util/Collection
      42: astore        4
      44: iconst_0
      45: istore        5
      47: aload_3
      48: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      53: astore        6
      55: aload         6
      57: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      62: ifeq          119
      65: aload         6
      67: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      72: astore        7
      74: aload         7
      76: checkcast     #118                // class java/lang/String
      79: astore        8
      81: iconst_0
      82: istore        9
      84: aload         8
      86: checkcast     #116                // class java/lang/CharSequence
      89: invokeinterface #321,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      94: ifne          101
      97: iconst_1
      98: goto          102
     101: iconst_0
     102: nop
     103: ifne          55
     106: aload         4
     108: aload         7
     110: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     115: pop
     116: goto          55
     119: aload         4
     121: checkcast     #66                 // class java/util/List
     124: nop
     125: checkcast     #20                 // class java/lang/Iterable
     128: astore_1
     129: nop
     130: iconst_0
     131: istore_2
     132: aload_1
     133: astore_3
     134: new           #128                // class java/util/ArrayList
     137: dup
     138: aload_1
     139: bipush        10
     141: invokestatic  #132                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     144: invokespecial #135                // Method java/util/ArrayList."<init>":(I)V
     147: checkcast     #69                 // class java/util/Collection
     150: astore        4
     152: iconst_0
     153: istore        5
     155: aload_3
     156: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     161: astore        6
     163: aload         6
     165: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     170: ifeq          217
     173: aload         6
     175: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     180: astore        7
     182: aload         4
     184: aload         7
     186: checkcast     #118                // class java/lang/String
     189: astore        8
     191: astore        10
     193: iconst_0
     194: istore        9
     196: aload         8
     198: invokestatic  #141                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     201: nop
     202: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     205: aload         10
     207: swap
     208: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     213: pop
     214: goto          163
     217: aload         4
     219: checkcast     #66                 // class java/util/List
     222: nop
     223: areturn

  private static final day4.BingoBoard parseBingoData$parseBoard(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: checkcast     #20                 // class java/lang/Iterable
       4: astore_1
       5: iconst_0
       6: istore_2
       7: aload_1
       8: astore_3
       9: new           #128                // class java/util/ArrayList
      12: dup
      13: aload_1
      14: bipush        10
      16: invokestatic  #132                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      19: invokespecial #135                // Method java/util/ArrayList."<init>":(I)V
      22: checkcast     #69                 // class java/util/Collection
      25: astore        4
      27: iconst_0
      28: istore        5
      30: aload_3
      31: invokeinterface #24,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      36: astore        6
      38: aload         6
      40: invokeinterface #30,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      45: ifeq          88
      48: aload         6
      50: invokeinterface #34,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      55: astore        7
      57: aload         4
      59: aload         7
      61: checkcast     #118                // class java/lang/String
      64: astore        8
      66: astore        10
      68: iconst_0
      69: istore        9
      71: aload         8
      73: invokestatic  #327                // Method parseBingoData$parseLine:(Ljava/lang/String;)Ljava/util/List;
      76: aload         10
      78: swap
      79: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      84: pop
      85: goto          38
      88: aload         4
      90: checkcast     #66                 // class java/util/List
      93: nop
      94: astore        11
      96: new           #42                 // class day4/BingoBoard
      99: dup
     100: aload         11
     102: invokespecial #330                // Method day4/BingoBoard."<init>":(Ljava/util/List;)V
     105: areturn
}


package day3

import java.io.File

fun computeGammaAndEpsilon(diagnosticReport: List<String>): Pair<Int, Int> {
  val p = List(diagnosticReport[0].length) { -diagnosticReport.size / 2 }
  val sums = diagnosticReport.fold(p) { acc, s -> s.map { it - '0' }.zip(acc){ a, b -> a + b } }
  val (gammaRaw, epsilonRaw) = sums
    .map { if (it >= 0) 1 else 0 }
    .fold(Pair("", "")) { acc, d -> Pair(acc.first + d, acc.second + (1 - d)) }
  return Pair(gammaRaw.toInt(2), epsilonRaw.toInt(2))
}

fun computeOxygenGenerator(diagnosticReport: List<String>): Int {
  tailrec fun rec(remaining: List<String>, bitPosition: Int): String {
    // assuming input has always a single answer although after processing last bit
    // the remaining values are the same
    return if (remaining.size == 1) remaining.first()
    else {
      val (ones, zeros) = remaining.partition { it[bitPosition] == '1' } // assuming it's either 0 or 1)
      rec(if (ones.size >= zeros.size) ones else zeros, bitPosition + 1)
    }
  }
  return rec(diagnosticReport, 0).toInt(2)
}

fun computeCO2Scrubber(diagnosticReport: List<String>): Int {
  tailrec fun rec(remaining: List<String>, bitPosition: Int): String {
    // assuming input has always a single answer although after processing last bit
    // the remaining values are the same
    return if (remaining.size == 1) remaining.first()
    else {
      val (ones, zeros) = remaining.partition { it[bitPosition] == '1' } // assuming it's either 0 or 1)
      rec(if (ones.size < zeros.size) ones else zeros, bitPosition + 1)
    }
  }
  return rec(diagnosticReport, 0).toInt(2)
}

fun printProduct(pair: Pair<Int, Int>): Int = pair.first * pair.second

fun main() {
  File("./input/day3.txt").useLines { lines ->
    val diagnosticReport = lines.toList()
    println("First value: ${printProduct(computeGammaAndEpsilon(diagnosticReport))}")
    println("Second value: ${computeOxygenGenerator(diagnosticReport) * computeCO2Scrubber(diagnosticReport)}")
  }
}

Compiled from "Day3.kt"
public final class day3.Day3Kt {
  public static final kotlin.Pair<java.lang.Integer, java.lang.Integer> computeGammaAndEpsilon(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String diagnosticReport
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iconst_0
       8: invokeinterface #22,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      13: checkcast     #24                 // class java/lang/String
      16: invokevirtual #28                 // Method java/lang/String.length:()I
      19: istore_2
      20: new           #30                 // class java/util/ArrayList
      23: dup
      24: iload_2
      25: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
      28: astore_3
      29: iconst_0
      30: istore        4
      32: iload         4
      34: iload_2
      35: if_icmpge     77
      38: iload         4
      40: istore        5
      42: aload_3
      43: iload         5
      45: istore        6
      47: astore        21
      49: iconst_0
      50: istore        7
      52: aload_0
      53: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
      58: ineg
      59: iconst_2
      60: idiv
      61: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      64: aload         21
      66: swap
      67: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      70: pop
      71: iinc          4, 1
      74: goto          32
      77: aload_3
      78: checkcast     #18                 // class java/util/List
      81: astore_1
      82: aload_0
      83: checkcast     #49                 // class java/lang/Iterable
      86: astore_3
      87: iconst_0
      88: istore        4
      90: aload_1
      91: astore        5
      93: aload_3
      94: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      99: astore        6
     101: aload         6
     103: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     108: ifeq          381
     111: aload         6
     113: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     118: astore        7
     120: aload         5
     122: aload         7
     124: checkcast     #24                 // class java/lang/String
     127: astore        8
     129: astore        9
     131: iconst_0
     132: istore        10
     134: aload         8
     136: checkcast     #65                 // class java/lang/CharSequence
     139: astore        11
     141: iconst_0
     142: istore        12
     144: aload         11
     146: astore        13
     148: new           #30                 // class java/util/ArrayList
     151: dup
     152: aload         11
     154: invokeinterface #66,  1           // InterfaceMethod java/lang/CharSequence.length:()I
     159: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
     162: checkcast     #68                 // class java/util/Collection
     165: astore        14
     167: iconst_0
     168: istore        15
     170: iconst_0
     171: istore        16
     173: iload         16
     175: aload         13
     177: invokeinterface #66,  1           // InterfaceMethod java/lang/CharSequence.length:()I
     182: if_icmpge     230
     185: aload         13
     187: iload         16
     189: invokeinterface #72,  2           // InterfaceMethod java/lang/CharSequence.charAt:(I)C
     194: istore        17
     196: aload         14
     198: iload         17
     200: istore        18
     202: astore        19
     204: iconst_0
     205: istore        20
     207: iload         18
     209: bipush        48
     211: isub
     212: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     215: aload         19
     217: swap
     218: invokeinterface #73,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     223: pop
     224: iinc          16, 1
     227: goto          173
     230: aload         14
     232: checkcast     #18                 // class java/util/List
     235: nop
     236: checkcast     #49                 // class java/lang/Iterable
     239: astore        11
     241: nop
     242: iconst_0
     243: istore        12
     245: aload         11
     247: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     252: astore        13
     254: aload         9
     256: checkcast     #49                 // class java/lang/Iterable
     259: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     264: astore        14
     266: new           #30                 // class java/util/ArrayList
     269: dup
     270: aload         11
     272: bipush        10
     274: invokestatic  #79                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     277: aload         9
     279: checkcast     #49                 // class java/lang/Iterable
     282: bipush        10
     284: invokestatic  #79                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     287: invokestatic  #85                 // Method java/lang/Math.min:(II)I
     290: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
     293: astore        15
     295: aload         13
     297: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     302: ifeq          370
     305: aload         14
     307: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     312: ifeq          370
     315: aload         15
     317: aload         13
     319: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     324: aload         14
     326: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     331: checkcast     #87                 // class java/lang/Number
     334: invokevirtual #90                 // Method java/lang/Number.intValue:()I
     337: istore        16
     339: checkcast     #87                 // class java/lang/Number
     342: invokevirtual #90                 // Method java/lang/Number.intValue:()I
     345: istore        17
     347: astore        19
     349: iconst_0
     350: istore        18
     352: iload         17
     354: iload         16
     356: iadd
     357: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     360: aload         19
     362: swap
     363: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     366: pop
     367: goto          295
     370: aload         15
     372: checkcast     #18                 // class java/util/List
     375: nop
     376: astore        5
     378: goto          101
     381: aload         5
     383: astore_2
     384: aload_2
     385: checkcast     #49                 // class java/lang/Iterable
     388: astore        4
     390: nop
     391: iconst_0
     392: istore        5
     394: aload         4
     396: astore        6
     398: new           #30                 // class java/util/ArrayList
     401: dup
     402: aload         4
     404: bipush        10
     406: invokestatic  #79                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     409: invokespecial #34                 // Method java/util/ArrayList."<init>":(I)V
     412: checkcast     #68                 // class java/util/Collection
     415: astore        7
     417: iconst_0
     418: istore        8
     420: aload         6
     422: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     427: astore        9
     429: aload         9
     431: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     436: ifeq          490
     439: aload         9
     441: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     446: astore        10
     448: aload         7
     450: aload         10
     452: checkcast     #87                 // class java/lang/Number
     455: invokevirtual #90                 // Method java/lang/Number.intValue:()I
     458: istore        11
     460: astore        21
     462: iconst_0
     463: istore        12
     465: iload         11
     467: iflt          474
     470: iconst_1
     471: goto          475
     474: iconst_0
     475: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     478: aload         21
     480: swap
     481: invokeinterface #73,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     486: pop
     487: goto          429
     490: aload         7
     492: checkcast     #18                 // class java/util/List
     495: nop
     496: checkcast     #49                 // class java/lang/Iterable
     499: astore        4
     501: new           #92                 // class kotlin/Pair
     504: dup
     505: ldc           #94                 // String
     507: ldc           #94                 // String
     509: invokespecial #97                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     512: astore        5
     514: iconst_0
     515: istore        6
     517: aload         5
     519: astore        7
     521: aload         4
     523: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     528: astore        8
     530: aload         8
     532: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     537: ifeq          632
     540: aload         8
     542: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     547: astore        9
     549: aload         7
     551: aload         9
     553: checkcast     #87                 // class java/lang/Number
     556: invokevirtual #90                 // Method java/lang/Number.intValue:()I
     559: istore        10
     561: astore        11
     563: iconst_0
     564: istore        12
     566: new           #92                 // class kotlin/Pair
     569: dup
     570: new           #99                 // class java/lang/StringBuilder
     573: dup
     574: invokespecial #102                // Method java/lang/StringBuilder."<init>":()V
     577: aload         11
     579: invokevirtual #105                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     582: checkcast     #24                 // class java/lang/String
     585: invokevirtual #109                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     588: iload         10
     590: invokevirtual #112                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     593: invokevirtual #116                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     596: new           #99                 // class java/lang/StringBuilder
     599: dup
     600: invokespecial #102                // Method java/lang/StringBuilder."<init>":()V
     603: aload         11
     605: invokevirtual #119                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     608: checkcast     #24                 // class java/lang/String
     611: invokevirtual #109                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     614: iconst_1
     615: iload         10
     617: isub
     618: invokevirtual #112                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     621: invokevirtual #116                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     624: invokespecial #97                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     627: astore        7
     629: goto          530
     632: aload         7
     634: astore_3
     635: aload_3
     636: invokevirtual #122                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     639: checkcast     #24                 // class java/lang/String
     642: astore        4
     644: aload_3
     645: invokevirtual #125                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     648: checkcast     #24                 // class java/lang/String
     651: astore        5
     653: new           #92                 // class kotlin/Pair
     656: dup
     657: aload         4
     659: iconst_2
     660: invokestatic  #131                // Method kotlin/text/CharsKt.checkRadix:(I)I
     663: invokestatic  #135                // Method java/lang/Integer.parseInt:(Ljava/lang/String;I)I
     666: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     669: aload         5
     671: iconst_2
     672: invokestatic  #131                // Method kotlin/text/CharsKt.checkRadix:(I)I
     675: invokestatic  #135                // Method java/lang/Integer.parseInt:(Ljava/lang/String;I)I
     678: invokestatic  #43                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     681: invokespecial #97                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     684: areturn

  public static final int computeOxygenGenerator(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String diagnosticReport
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iconst_0
       8: invokestatic  #185                // Method computeOxygenGenerator$rec:(Ljava/util/List;I)Ljava/lang/String;
      11: iconst_2
      12: invokestatic  #131                // Method kotlin/text/CharsKt.checkRadix:(I)I
      15: invokestatic  #135                // Method java/lang/Integer.parseInt:(Ljava/lang/String;I)I
      18: ireturn

  public static final int computeCO2Scrubber(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String diagnosticReport
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iconst_0
       8: invokestatic  #189                // Method computeCO2Scrubber$rec$8:(Ljava/util/List;I)Ljava/lang/String;
      11: iconst_2
      12: invokestatic  #131                // Method kotlin/text/CharsKt.checkRadix:(I)I
      15: invokestatic  #135                // Method java/lang/Integer.parseInt:(Ljava/lang/String;I)I
      18: ireturn

  public static final int printProduct(kotlin.Pair<java.lang.Integer, java.lang.Integer>);
    Code:
       0: aload_0
       1: ldc           #194                // String pair
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #105                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      10: checkcast     #87                 // class java/lang/Number
      13: invokevirtual #90                 // Method java/lang/Number.intValue:()I
      16: aload_0
      17: invokevirtual #119                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      20: checkcast     #87                 // class java/lang/Number
      23: invokevirtual #90                 // Method java/lang/Number.intValue:()I
      26: imul
      27: ireturn

  public static final void main();
    Code:
       0: new           #199                // class java/io/File
       3: dup
       4: ldc           #201                // String ./input/day3.txt
       6: invokespecial #204                // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_0
      10: getstatic     #210                // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_1
      14: iconst_0
      15: istore_2
      16: aload_0
      17: astore_3
      18: sipush        8192
      21: istore        4
      23: aload_3
      24: astore        5
      26: new           #212                // class java/io/InputStreamReader
      29: dup
      30: new           #214                // class java/io/FileInputStream
      33: dup
      34: aload         5
      36: invokespecial #217                // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      39: checkcast     #219                // class java/io/InputStream
      42: aload_1
      43: invokespecial #222                // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      46: checkcast     #224                // class java/io/Reader
      49: astore        5
      51: aload         5
      53: instanceof    #226                // class java/io/BufferedReader
      56: ifeq          67
      59: aload         5
      61: checkcast     #226                // class java/io/BufferedReader
      64: goto          78
      67: new           #226                // class java/io/BufferedReader
      70: dup
      71: aload         5
      73: iload         4
      75: invokespecial #229                // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      78: checkcast     #231                // class java/io/Closeable
      81: astore_3
      82: aconst_null
      83: astore        4
      85: nop
      86: aload_3
      87: checkcast     #226                // class java/io/BufferedReader
      90: astore        5
      92: iconst_0
      93: istore        6
      95: aload         5
      97: invokestatic  #237                // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     100: astore        7
     102: iconst_0
     103: istore        8
     105: aload         7
     107: invokestatic  #243                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
     110: astore        9
     112: new           #99                 // class java/lang/StringBuilder
     115: dup
     116: invokespecial #102                // Method java/lang/StringBuilder."<init>":()V
     119: ldc           #245                // String First value:
     121: invokevirtual #109                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     124: aload         9
     126: invokestatic  #247                // Method computeGammaAndEpsilon:(Ljava/util/List;)Lkotlin/Pair;
     129: invokestatic  #249                // Method printProduct:(Lkotlin/Pair;)I
     132: invokevirtual #112                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     135: invokevirtual #116                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     138: getstatic     #255                // Field java/lang/System.out:Ljava/io/PrintStream;
     141: swap
     142: invokevirtual #261                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     145: new           #99                 // class java/lang/StringBuilder
     148: dup
     149: invokespecial #102                // Method java/lang/StringBuilder."<init>":()V
     152: ldc_w         #263                // String Second value:
     155: invokevirtual #109                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     158: aload         9
     160: invokestatic  #265                // Method computeOxygenGenerator:(Ljava/util/List;)I
     163: aload         9
     165: invokestatic  #267                // Method computeCO2Scrubber:(Ljava/util/List;)I
     168: imul
     169: invokevirtual #112                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     172: invokevirtual #116                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     175: getstatic     #255                // Field java/lang/System.out:Ljava/io/PrintStream;
     178: swap
     179: invokevirtual #261                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     182: nop
     183: getstatic     #273                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     186: astore        5
     188: aload_3
     189: aload         4
     191: invokestatic  #279                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     194: goto          217
     197: astore        6
     199: aload         6
     201: astore        4
     203: aload         6
     205: athrow
     206: astore        6
     208: aload_3
     209: aload         4
     211: invokestatic  #279                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     214: aload         6
     216: athrow
     217: nop
     218: return
    Exception table:
       from    to  target type
          85   188   197   Class java/lang/Throwable
          85   188   206   any
         197   206   206   any
         206   208   206   any

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

  private static final java.lang.String computeOxygenGenerator$rec(java.util.List<java.lang.String>, int);
    Code:
       0: aload_0
       1: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
       6: iconst_1
       7: if_icmpne     20
      10: aload_0
      11: invokestatic  #303                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      14: checkcast     #24                 // class java/lang/String
      17: goto          190
      20: aload_0
      21: checkcast     #49                 // class java/lang/Iterable
      24: astore_3
      25: iconst_0
      26: istore        4
      28: new           #30                 // class java/util/ArrayList
      31: dup
      32: invokespecial #304                // Method java/util/ArrayList."<init>":()V
      35: astore        5
      37: new           #30                 // class java/util/ArrayList
      40: dup
      41: invokespecial #304                // Method java/util/ArrayList."<init>":()V
      44: astore        6
      46: aload_3
      47: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      52: astore        7
      54: aload         7
      56: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      61: ifeq          123
      64: aload         7
      66: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      71: astore        8
      73: aload         8
      75: checkcast     #24                 // class java/lang/String
      78: astore        9
      80: iconst_0
      81: istore        10
      83: aload         9
      85: iload_1
      86: invokevirtual #305                // Method java/lang/String.charAt:(I)C
      89: bipush        49
      91: if_icmpne     98
      94: iconst_1
      95: goto          99
      98: iconst_0
      99: ifeq          112
     102: aload         5
     104: aload         8
     106: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     109: goto          119
     112: aload         6
     114: aload         8
     116: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     119: pop
     120: goto          54
     123: new           #92                 // class kotlin/Pair
     126: dup
     127: aload         5
     129: aload         6
     131: invokespecial #97                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     134: astore_2
     135: aload_2
     136: invokevirtual #122                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     139: checkcast     #18                 // class java/util/List
     142: astore_3
     143: aload_2
     144: invokevirtual #125                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     147: checkcast     #18                 // class java/util/List
     150: astore        4
     152: aload_3
     153: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
     158: aload         4
     160: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
     165: if_icmplt     172
     168: aload_3
     169: goto          174
     172: aload         4
     174: astore        5
     176: iload_1
     177: iconst_1
     178: iadd
     179: istore        6
     181: aload         5
     183: astore_0
     184: iload         6
     186: istore_1
     187: goto          0
     190: areturn

  private static final java.lang.String computeCO2Scrubber$rec$8(java.util.List<java.lang.String>, int);
    Code:
       0: aload_0
       1: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
       6: iconst_1
       7: if_icmpne     20
      10: aload_0
      11: invokestatic  #303                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      14: checkcast     #24                 // class java/lang/String
      17: goto          190
      20: aload_0
      21: checkcast     #49                 // class java/lang/Iterable
      24: astore_3
      25: iconst_0
      26: istore        4
      28: new           #30                 // class java/util/ArrayList
      31: dup
      32: invokespecial #304                // Method java/util/ArrayList."<init>":()V
      35: astore        5
      37: new           #30                 // class java/util/ArrayList
      40: dup
      41: invokespecial #304                // Method java/util/ArrayList."<init>":()V
      44: astore        6
      46: aload_3
      47: invokeinterface #53,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      52: astore        7
      54: aload         7
      56: invokeinterface #59,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      61: ifeq          123
      64: aload         7
      66: invokeinterface #63,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      71: astore        8
      73: aload         8
      75: checkcast     #24                 // class java/lang/String
      78: astore        9
      80: iconst_0
      81: istore        10
      83: aload         9
      85: iload_1
      86: invokevirtual #305                // Method java/lang/String.charAt:(I)C
      89: bipush        49
      91: if_icmpne     98
      94: iconst_1
      95: goto          99
      98: iconst_0
      99: ifeq          112
     102: aload         5
     104: aload         8
     106: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     109: goto          119
     112: aload         6
     114: aload         8
     116: invokevirtual #47                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     119: pop
     120: goto          54
     123: new           #92                 // class kotlin/Pair
     126: dup
     127: aload         5
     129: aload         6
     131: invokespecial #97                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     134: astore_2
     135: aload_2
     136: invokevirtual #122                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     139: checkcast     #18                 // class java/util/List
     142: astore_3
     143: aload_2
     144: invokevirtual #125                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     147: checkcast     #18                 // class java/util/List
     150: astore        4
     152: aload_3
     153: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
     158: aload         4
     160: invokeinterface #37,  1           // InterfaceMethod java/util/List.size:()I
     165: if_icmpge     172
     168: aload_3
     169: goto          174
     172: aload         4
     174: astore        5
     176: iload_1
     177: iconst_1
     178: iadd
     179: istore        6
     181: aload         5
     183: astore_0
     184: iload         6
     186: istore_1
     187: goto          0
     190: areturn
}


package day2

import java.io.File

sealed interface SubmarineActions<out S : SubmarineActions<S>> {
  fun moveForward(delta: Int): S
  fun goUp(delta: Int): S
  fun goDown(delta: Int): S = goUp(-delta)
}

data class Submarine1(val horizontal: Int, val depth: Int): SubmarineActions<Submarine1> {
  companion object {
    val fromStart: Submarine1
      get() = Submarine1(0, 0)
  }
  override fun moveForward(delta: Int) = this.copy(horizontal = horizontal + delta)
  override fun goUp(delta: Int) = this.copy(depth = depth - delta)
}

data class Submarine2(val horizontal: Int, val depth: Int, val aim: Int): SubmarineActions<Submarine2> {
  companion object {
    val fromStart: Submarine2
      get() = Submarine2(0, 0, 0)
  }
  override fun moveForward(delta: Int) = this.copy(horizontal = horizontal + delta, depth = depth + aim * delta)
  override fun goUp(delta: Int) = this.copy(aim = aim - delta)
}

fun <S : SubmarineActions<S>> processInstruction(current: S, instruction: String): S {
  val (word, number) = instruction.split(" ")
  val delta = number.toInt()
  return when (word) {
    "forward" -> current.moveForward(delta)
    "up" -> current.goUp(delta)
    "down" -> current.goDown(delta)
    else -> current // ignore unrecognized command
  }
}

fun computeFinalHorizontalPositionAndDepthProduct(instructions: List<String>): Int {
  val s = instructions.fold(Submarine1.fromStart, ::processInstruction)
  return s.horizontal * s.depth
}

fun computeFinalHorizontalPositionAndDepthProduct2(instructions: List<String>): Int {
  val s = instructions.fold(Submarine2.fromStart, ::processInstruction)
  return s.horizontal * s.depth
}

fun main() {
  File("./input/day2.txt").useLines { lines ->
    val instructions = lines.toList()
    println("First value: ${computeFinalHorizontalPositionAndDepthProduct(instructions)}")
    println("Second value: ${computeFinalHorizontalPositionAndDepthProduct2(instructions)}")
  }
}

Compiled from "Day2.kt"
public final class day2.Day2Kt {
  public static final <S extends day2.SubmarineActions<? extends S>> S processInstruction(S, java.lang.String);
    Code:
       0: aload_0
       1: ldc           #10                 // String current
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #18                 // String instruction
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: checkcast     #20                 // class java/lang/CharSequence
      16: iconst_1
      17: anewarray     #22                 // class java/lang/String
      20: astore_3
      21: aload_3
      22: iconst_0
      23: ldc           #24                 // String
      25: aastore
      26: aload_3
      27: iconst_0
      28: iconst_0
      29: bipush        6
      31: aconst_null
      32: invokestatic  #30                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      35: astore_2
      36: aload_2
      37: iconst_0
      38: invokeinterface #36,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      43: checkcast     #22                 // class java/lang/String
      46: astore_3
      47: aload_2
      48: iconst_1
      49: invokeinterface #36,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      54: checkcast     #22                 // class java/lang/String
      57: astore        4
      59: aload         4
      61: invokestatic  #42                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      64: istore        5
      66: aload_3
      67: astore        6
      69: aload         6
      71: invokevirtual #46                 // Method java/lang/String.hashCode:()I
      74: lookupswitch  { // 3
            -677145915: 108
                  3739: 121
               3089570: 134
               default: 180
          }
     108: aload         6
     110: ldc           #48                 // String forward
     112: invokevirtual #52                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     115: ifne          147
     118: goto          180
     121: aload         6
     123: ldc           #54                 // String up
     125: invokevirtual #52                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     128: ifne          158
     131: goto          180
     134: aload         6
     136: ldc           #56                 // String down
     138: invokevirtual #52                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     141: ifne          169
     144: goto          180
     147: aload_0
     148: iload         5
     150: invokeinterface #62,  2           // InterfaceMethod day2/SubmarineActions.moveForward:(I)Lday2/SubmarineActions;
     155: goto          181
     158: aload_0
     159: iload         5
     161: invokeinterface #65,  2           // InterfaceMethod day2/SubmarineActions.goUp:(I)Lday2/SubmarineActions;
     166: goto          181
     169: aload_0
     170: iload         5
     172: invokeinterface #68,  2           // InterfaceMethod day2/SubmarineActions.goDown:(I)Lday2/SubmarineActions;
     177: goto          181
     180: aload_0
     181: areturn

  public static final int computeFinalHorizontalPositionAndDepthProduct(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #79                 // String instructions
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #81                 // class java/lang/Iterable
      10: astore_2
      11: getstatic     #87                 // Field day2/Submarine1.Companion:Lday2/Submarine1$Companion;
      14: invokevirtual #93                 // Method day2/Submarine1$Companion.getFromStart:()Lday2/Submarine1;
      17: astore_3
      18: iconst_0
      19: istore        4
      21: aload_3
      22: astore        5
      24: aload_2
      25: invokeinterface #97,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      30: astore        6
      32: aload         6
      34: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      39: ifeq          83
      42: aload         6
      44: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      49: astore        7
      51: aload         5
      53: aload         7
      55: checkcast     #22                 // class java/lang/String
      58: astore        8
      60: astore        9
      62: iconst_0
      63: istore        10
      65: aload         9
      67: checkcast     #58                 // class day2/SubmarineActions
      70: aload         8
      72: invokestatic  #109                // Method processInstruction:(Lday2/SubmarineActions;Ljava/lang/String;)Lday2/SubmarineActions;
      75: checkcast     #83                 // class day2/Submarine1
      78: astore        5
      80: goto          32
      83: aload         5
      85: astore_1
      86: aload_1
      87: invokevirtual #112                // Method day2/Submarine1.getHorizontal:()I
      90: aload_1
      91: invokevirtual #115                // Method day2/Submarine1.getDepth:()I
      94: imul
      95: ireturn

  public static final int computeFinalHorizontalPositionAndDepthProduct2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #79                 // String instructions
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #81                 // class java/lang/Iterable
      10: astore_2
      11: getstatic     #134                // Field day2/Submarine2.Companion:Lday2/Submarine2$Companion;
      14: invokevirtual #139                // Method day2/Submarine2$Companion.getFromStart:()Lday2/Submarine2;
      17: astore_3
      18: iconst_0
      19: istore        4
      21: aload_3
      22: astore        5
      24: aload_2
      25: invokeinterface #97,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      30: astore        6
      32: aload         6
      34: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      39: ifeq          83
      42: aload         6
      44: invokeinterface #107,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      49: astore        7
      51: aload         5
      53: aload         7
      55: checkcast     #22                 // class java/lang/String
      58: astore        8
      60: astore        9
      62: iconst_0
      63: istore        10
      65: aload         9
      67: checkcast     #58                 // class day2/SubmarineActions
      70: aload         8
      72: invokestatic  #109                // Method processInstruction:(Lday2/SubmarineActions;Ljava/lang/String;)Lday2/SubmarineActions;
      75: checkcast     #131                // class day2/Submarine2
      78: astore        5
      80: goto          32
      83: aload         5
      85: astore_1
      86: aload_1
      87: invokevirtual #140                // Method day2/Submarine2.getHorizontal:()I
      90: aload_1
      91: invokevirtual #141                // Method day2/Submarine2.getDepth:()I
      94: imul
      95: ireturn

  public static final void main();
    Code:
       0: new           #149                // class java/io/File
       3: dup
       4: ldc           #151                // String ./input/day2.txt
       6: invokespecial #155                // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_0
      10: getstatic     #161                // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_1
      14: iconst_0
      15: istore_2
      16: aload_0
      17: astore_3
      18: sipush        8192
      21: istore        4
      23: aload_3
      24: astore        5
      26: new           #163                // class java/io/InputStreamReader
      29: dup
      30: new           #165                // class java/io/FileInputStream
      33: dup
      34: aload         5
      36: invokespecial #168                // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      39: checkcast     #170                // class java/io/InputStream
      42: aload_1
      43: invokespecial #173                // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      46: checkcast     #175                // class java/io/Reader
      49: astore        5
      51: aload         5
      53: instanceof    #177                // class java/io/BufferedReader
      56: ifeq          67
      59: aload         5
      61: checkcast     #177                // class java/io/BufferedReader
      64: goto          78
      67: new           #177                // class java/io/BufferedReader
      70: dup
      71: aload         5
      73: iload         4
      75: invokespecial #180                // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      78: checkcast     #182                // class java/io/Closeable
      81: astore_3
      82: aconst_null
      83: astore        4
      85: nop
      86: aload_3
      87: checkcast     #177                // class java/io/BufferedReader
      90: astore        5
      92: iconst_0
      93: istore        6
      95: aload         5
      97: invokestatic  #188                // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     100: astore        7
     102: iconst_0
     103: istore        8
     105: aload         7
     107: invokestatic  #194                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
     110: astore        9
     112: new           #196                // class java/lang/StringBuilder
     115: dup
     116: invokespecial #198                // Method java/lang/StringBuilder."<init>":()V
     119: ldc           #200                // String First value:
     121: invokevirtual #204                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     124: aload         9
     126: invokestatic  #206                // Method computeFinalHorizontalPositionAndDepthProduct:(Ljava/util/List;)I
     129: invokevirtual #209                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     132: invokevirtual #213                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     135: getstatic     #219                // Field java/lang/System.out:Ljava/io/PrintStream;
     138: swap
     139: invokevirtual #225                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     142: new           #196                // class java/lang/StringBuilder
     145: dup
     146: invokespecial #198                // Method java/lang/StringBuilder."<init>":()V
     149: ldc           #227                // String Second value:
     151: invokevirtual #204                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     154: aload         9
     156: invokestatic  #229                // Method computeFinalHorizontalPositionAndDepthProduct2:(Ljava/util/List;)I
     159: invokevirtual #209                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     162: invokevirtual #213                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     165: getstatic     #219                // Field java/lang/System.out:Ljava/io/PrintStream;
     168: swap
     169: invokevirtual #225                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     172: nop
     173: getstatic     #235                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     176: astore        5
     178: aload_3
     179: aload         4
     181: invokestatic  #241                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     184: goto          207
     187: astore        6
     189: aload         6
     191: astore        4
     193: aload         6
     195: athrow
     196: astore        6
     198: aload_3
     199: aload         4
     201: invokestatic  #241                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     204: aload         6
     206: athrow
     207: nop
     208: return
    Exception table:
       from    to  target type
          85   178   187   Class java/lang/Throwable
          85   178   196   any
         187   196   196   any
         196   198   196   any

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