package day04

import java.io.File

fun main() {
    val (numbers, boards) = parse("src/main/kotlin/day04/Day04.txt")

    val answer1 = part1(numbers, boards.map(List<Int>::toMutableList))
    val answer2 = part2(numbers, boards.map(List<Int>::toMutableList))

    println("🎄 Day 04 🎄")

    println()

    println("[Part 1]")
    println("Answer: $answer1")

    println()

    println("[Part 2]")
    println("Answer: $answer2")
}

private fun parse(path: String): Pair<List<Int>, List<List<Int>>> {
    val entries = File(path)
        .readText()
        .trim()
        .split("""\s+""".toRegex())

    val numbers = entries.first()
        .split(",")
        .map(String::toInt)

    val boards = entries.subList(1, entries.size)
        .map(String::toInt)
        .chunked(25)

    return Pair(numbers, boards)
}

// We need to keep track of each board's state as the game progresses.
// The simplest and most effective approach would be to mutate the board itself.
private typealias Board = MutableList<Int>

// Boards have a sense of dimensionality, but all numbers are stored as flat lists.
// This structure allows us to fully describe a given number's position.
private data class Position(
    val col: Int,
    val row: Int,
    val idx: Int,
)

// It is important to remember that a number is not guaranteed to appear on every
// board, therefore it may not always have a position.
private fun Board.findPosition(number: Int): Position? =
    (0 until 5).firstNotNullOfOrNull { row ->
        (0 until 5).firstNotNullOfOrNull { col ->
            val index = row * 5 + col
            if (this[index] == number)
                Position(col, row, index)
            else
                null
        }
    }

// There are several approaches we could use to signify that a given number was
// marked, here's one of them: all numbers that appear on boards are always positive;
// therefore, we can use the sign of the number as the "marked" flag.
//
// Since a marked number is never needed again, we are free to discard it during
// the calculations and replace it with something completely different. This may
// not be the cleanest approach, but it lets us reuse space efficiently, avoid
// introducing extra data classes, etc.
private fun Board.mark(idx: Int) {
    this[idx] = -1
}

// Naturally, the board may be put into a winning position only after a number
// was marked, and the number can only affect one row and one column. It's enough
// to just check these two, without bothering the rest of the board.
private fun Board.hasWon(col: Int, row: Int) =
    (0 until 5).all { i -> this[row * 5 + i] < 0 } ||
    (0 until 5).all { i -> this[i * 5 + col] < 0 }

// For the first part of the problem, the algorithm is straightforward:
// we mark each number, in turn, on each board, until we encounter a winning
// position, in which case the result is directly returned.

private fun part1(numbers: List<Int>, boards: List<Board>) =
    numbers.firstNotNullOf { number ->
        boards.firstNotNullOfOrNull { board ->
            board.findPosition(number)?.let { (col, row, idx) ->
                board.mark(idx)
                if (board.hasWon(col, row))
                    number * board.sumOf { i -> if (i >= 0) i else 0 }
                else
                    null
            }
        }
    }

// For the second part, the approach is a little more involved: we go through
// each board and find the first winning turn (each board is guaranteed to win
// at some point); we then find the victory that happened on the latest turn
// and use it to calculate the final result.

private data class Victory(
    val turn: Int,
    val number: Int,
    val board: Board
)

private fun part2(numbers: List<Int>, boards: List<Board>) =
    boards.map { board ->
        numbers.indexOfFirst { number ->
            board.findPosition(number)?.let { (col, row, idx) ->
                board.mark(idx)
                board.hasWon(col, row)
            } ?: false
        }
        .let { turn -> Victory(turn, numbers[turn], board) }
    }
    .maxByOrNull(Victory::turn)!!
    .let { (_, number, board) ->
        number * board.sumOf { i -> if (i >= 0) i else 0 }
    }

Compiled from "Day04.kt"
public final class day04.Day04Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String src/main/kotlin/day04/Day04.txt
       2: invokestatic  #12                 // Method parse:(Ljava/lang/String;)Lkotlin/Pair;
       5: astore_0
       6: aload_0
       7: invokevirtual #18                 // Method kotlin/Pair.component1:()Ljava/lang/Object;
      10: checkcast     #20                 // class java/util/List
      13: astore_1
      14: aload_0
      15: invokevirtual #23                 // Method kotlin/Pair.component2:()Ljava/lang/Object;
      18: checkcast     #20                 // class java/util/List
      21: astore_2
      22: aload_1
      23: aload_2
      24: checkcast     #25                 // class java/lang/Iterable
      27: astore        4
      29: astore        14
      31: iconst_0
      32: istore        5
      34: aload         4
      36: astore        6
      38: new           #27                 // class java/util/ArrayList
      41: dup
      42: aload         4
      44: bipush        10
      46: invokestatic  #33                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      49: invokespecial #37                 // Method java/util/ArrayList."<init>":(I)V
      52: checkcast     #39                 // class java/util/Collection
      55: astore        7
      57: iconst_0
      58: istore        8
      60: aload         6
      62: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      67: astore        9
      69: aload         9
      71: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      76: ifeq          122
      79: aload         9
      81: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      86: astore        10
      88: aload         7
      90: aload         10
      92: checkcast     #20                 // class java/util/List
      95: astore        11
      97: astore        15
      99: iconst_0
     100: istore        12
     102: aload         11
     104: checkcast     #39                 // class java/util/Collection
     107: invokestatic  #56                 // Method kotlin/collections/CollectionsKt.toMutableList:(Ljava/util/Collection;)Ljava/util/List;
     110: aload         15
     112: swap
     113: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     118: pop
     119: goto          69
     122: aload         7
     124: checkcast     #20                 // class java/util/List
     127: nop
     128: aload         14
     130: swap
     131: invokestatic  #64                 // Method part1:(Ljava/util/List;Ljava/util/List;)I
     134: istore_3
     135: aload_1
     136: aload_2
     137: checkcast     #25                 // class java/lang/Iterable
     140: astore        5
     142: astore        14
     144: iconst_0
     145: istore        6
     147: aload         5
     149: astore        7
     151: new           #27                 // class java/util/ArrayList
     154: dup
     155: aload         5
     157: bipush        10
     159: invokestatic  #33                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     162: invokespecial #37                 // Method java/util/ArrayList."<init>":(I)V
     165: checkcast     #39                 // class java/util/Collection
     168: astore        8
     170: iconst_0
     171: istore        9
     173: aload         7
     175: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     180: astore        10
     182: aload         10
     184: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     189: ifeq          235
     192: aload         10
     194: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     199: astore        11
     201: aload         8
     203: aload         11
     205: checkcast     #20                 // class java/util/List
     208: astore        12
     210: astore        15
     212: iconst_0
     213: istore        13
     215: aload         12
     217: checkcast     #39                 // class java/util/Collection
     220: invokestatic  #56                 // Method kotlin/collections/CollectionsKt.toMutableList:(Ljava/util/Collection;)Ljava/util/List;
     223: aload         15
     225: swap
     226: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     231: pop
     232: goto          182
     235: aload         8
     237: checkcast     #20                 // class java/util/List
     240: nop
     241: aload         14
     243: swap
     244: invokestatic  #67                 // Method part2:(Ljava/util/List;Ljava/util/List;)I
     247: istore        4
     249: ldc           #69                 // String 🎄 Day 04 🎄
     251: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     254: swap
     255: invokevirtual #81                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     258: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     261: invokevirtual #83                 // Method java/io/PrintStream.println:()V
     264: ldc           #85                 // String [Part 1]
     266: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     269: swap
     270: invokevirtual #81                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     273: new           #87                 // class java/lang/StringBuilder
     276: dup
     277: invokespecial #89                 // Method java/lang/StringBuilder."<init>":()V
     280: ldc           #91                 // String Answer:
     282: invokevirtual #95                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     285: iload_3
     286: invokevirtual #98                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     289: invokevirtual #102                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     292: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     295: swap
     296: invokevirtual #81                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     299: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     302: invokevirtual #83                 // Method java/io/PrintStream.println:()V
     305: ldc           #104                // String [Part 2]
     307: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     310: swap
     311: invokevirtual #81                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     314: new           #87                 // class java/lang/StringBuilder
     317: dup
     318: invokespecial #89                 // Method java/lang/StringBuilder."<init>":()V
     321: ldc           #91                 // String Answer:
     323: invokevirtual #95                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     326: iload         4
     328: invokevirtual #98                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     331: invokevirtual #102                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     334: getstatic     #75                 // Field java/lang/System.out:Ljava/io/PrintStream;
     337: swap
     338: invokevirtual #81                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     341: return

  private static final kotlin.Pair<java.util.List<java.lang.Integer>, java.util.List<java.util.List<java.lang.Integer>>> parse(java.lang.String);
    Code:
       0: nop
       1: new           #125                // class java/io/File
       4: dup
       5: aload_0
       6: invokespecial #128                // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #134                // Method kotlin/io/FilesKt.readText$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/lang/String;
      15: checkcast     #136                // class java/lang/CharSequence
      18: invokestatic  #142                // Method kotlin/text/StringsKt.trim:(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
      21: invokevirtual #143                // Method java/lang/Object.toString:()Ljava/lang/String;
      24: checkcast     #136                // class java/lang/CharSequence
      27: astore_2
      28: new           #145                // class kotlin/text/Regex
      31: dup
      32: ldc           #147                // String \\s+
      34: invokespecial #148                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
      37: astore_3
      38: iconst_0
      39: istore        4
      41: aload_3
      42: aload_2
      43: iload         4
      45: invokevirtual #152                // Method kotlin/text/Regex.split:(Ljava/lang/CharSequence;I)Ljava/util/List;
      48: astore_1
      49: aload_1
      50: invokestatic  #156                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      53: checkcast     #136                // class java/lang/CharSequence
      56: iconst_1
      57: anewarray     #158                // class java/lang/String
      60: astore_3
      61: aload_3
      62: iconst_0
      63: ldc           #160                // String ,
      65: aastore
      66: aload_3
      67: iconst_0
      68: iconst_0
      69: bipush        6
      71: aconst_null
      72: invokestatic  #164                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      75: checkcast     #25                 // class java/lang/Iterable
      78: astore_3
      79: nop
      80: iconst_0
      81: istore        4
      83: aload_3
      84: astore        5
      86: new           #27                 // class java/util/ArrayList
      89: dup
      90: aload_3
      91: bipush        10
      93: invokestatic  #33                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      96: invokespecial #37                 // Method java/util/ArrayList."<init>":(I)V
      99: checkcast     #39                 // class java/util/Collection
     102: astore        6
     104: iconst_0
     105: istore        7
     107: aload         5
     109: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     114: astore        8
     116: aload         8
     118: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     123: ifeq          170
     126: aload         8
     128: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     133: astore        9
     135: aload         6
     137: aload         9
     139: checkcast     #158                // class java/lang/String
     142: astore        10
     144: astore        13
     146: iconst_0
     147: istore        11
     149: aload         10
     151: invokestatic  #170                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     154: nop
     155: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     158: aload         13
     160: swap
     161: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     166: pop
     167: goto          116
     170: aload         6
     172: checkcast     #20                 // class java/util/List
     175: nop
     176: astore_2
     177: aload_1
     178: iconst_1
     179: aload_1
     180: invokeinterface #178,  1          // InterfaceMethod java/util/List.size:()I
     185: invokeinterface #182,  3          // InterfaceMethod java/util/List.subList:(II)Ljava/util/List;
     190: checkcast     #25                 // class java/lang/Iterable
     193: astore        4
     195: nop
     196: iconst_0
     197: istore        5
     199: aload         4
     201: astore        6
     203: new           #27                 // class java/util/ArrayList
     206: dup
     207: aload         4
     209: bipush        10
     211: invokestatic  #33                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     214: invokespecial #37                 // Method java/util/ArrayList."<init>":(I)V
     217: checkcast     #39                 // class java/util/Collection
     220: astore        7
     222: iconst_0
     223: istore        8
     225: aload         6
     227: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     232: astore        9
     234: aload         9
     236: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     241: ifeq          288
     244: aload         9
     246: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     251: astore        10
     253: aload         7
     255: aload         10
     257: checkcast     #158                // class java/lang/String
     260: astore        11
     262: astore        13
     264: iconst_0
     265: istore        12
     267: aload         11
     269: invokestatic  #170                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     272: nop
     273: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     276: aload         13
     278: swap
     279: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     284: pop
     285: goto          234
     288: aload         7
     290: checkcast     #20                 // class java/util/List
     293: nop
     294: checkcast     #25                 // class java/lang/Iterable
     297: bipush        25
     299: invokestatic  #186                // Method kotlin/collections/CollectionsKt.chunked:(Ljava/lang/Iterable;I)Ljava/util/List;
     302: astore_3
     303: new           #14                 // class kotlin/Pair
     306: dup
     307: aload_2
     308: aload_3
     309: invokespecial #189                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     312: areturn

  private static final day04.Position findPosition(java.util.List<java.lang.Integer>, int);
    Code:
       0: iconst_0
       1: iconst_5
       2: invokestatic  #203                // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
       5: checkcast     #25                 // class java/lang/Iterable
       8: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      13: astore_2
      14: aload_2
      15: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      20: ifeq          137
      23: aload_2
      24: checkcast     #205                // class kotlin/collections/IntIterator
      27: invokevirtual #208                // Method kotlin/collections/IntIterator.nextInt:()I
      30: istore_3
      31: iconst_0
      32: istore        4
      34: iconst_0
      35: iconst_5
      36: invokestatic  #203                // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
      39: checkcast     #25                 // class java/lang/Iterable
      42: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      47: astore        5
      49: aload         5
      51: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      56: ifeq          126
      59: aload         5
      61: checkcast     #205                // class kotlin/collections/IntIterator
      64: invokevirtual #208                // Method kotlin/collections/IntIterator.nextInt:()I
      67: istore        6
      69: iconst_0
      70: istore        7
      72: iload_3
      73: iconst_5
      74: imul
      75: iload         6
      77: iadd
      78: istore        8
      80: aload_0
      81: iload         8
      83: invokeinterface #212,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      88: checkcast     #214                // class java/lang/Number
      91: invokevirtual #217                // Method java/lang/Number.intValue:()I
      94: iload_1
      95: if_icmpne     113
      98: new           #219                // class day04/Position
     101: dup
     102: iload         6
     104: iload_3
     105: iload         8
     107: invokespecial #222                // Method day04/Position."<init>":(III)V
     110: goto          114
     113: aconst_null
     114: astore        6
     116: aload         6
     118: ifnull        49
     121: aload         6
     123: goto          127
     126: aconst_null
     127: nop
     128: astore_3
     129: aload_3
     130: ifnull        14
     133: aload_3
     134: goto          138
     137: aconst_null
     138: areturn

  private static final void mark(java.util.List<java.lang.Integer>, int);
    Code:
       0: aload_0
       1: iload_1
       2: iconst_m1
       3: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: invokeinterface #236,  3          // InterfaceMethod java/util/List.set:(ILjava/lang/Object;)Ljava/lang/Object;
      11: pop
      12: return

  private static final boolean hasWon(java.util.List<java.lang.Integer>, int, int);
    Code:
       0: iconst_0
       1: iconst_5
       2: invokestatic  #203                // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
       5: checkcast     #25                 // class java/lang/Iterable
       8: astore_3
       9: iconst_0
      10: istore        4
      12: aload_3
      13: instanceof    #39                 // class java/util/Collection
      16: ifeq          35
      19: aload_3
      20: checkcast     #39                 // class java/util/Collection
      23: invokeinterface #244,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      28: ifeq          35
      31: iconst_1
      32: goto          104
      35: aload_3
      36: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      41: astore        5
      43: aload         5
      45: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      50: ifeq          103
      53: aload         5
      55: checkcast     #205                // class kotlin/collections/IntIterator
      58: invokevirtual #208                // Method kotlin/collections/IntIterator.nextInt:()I
      61: istore        6
      63: iload         6
      65: istore        7
      67: iconst_0
      68: istore        8
      70: aload_0
      71: iload_2
      72: iconst_5
      73: imul
      74: iload         7
      76: iadd
      77: invokeinterface #212,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      82: checkcast     #214                // class java/lang/Number
      85: invokevirtual #217                // Method java/lang/Number.intValue:()I
      88: ifge          95
      91: iconst_1
      92: goto          96
      95: iconst_0
      96: ifne          43
      99: iconst_0
     100: goto          104
     103: iconst_1
     104: ifne          214
     107: iconst_0
     108: iconst_5
     109: invokestatic  #203                // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
     112: checkcast     #25                 // class java/lang/Iterable
     115: astore_3
     116: iconst_0
     117: istore        4
     119: aload_3
     120: instanceof    #39                 // class java/util/Collection
     123: ifeq          142
     126: aload_3
     127: checkcast     #39                 // class java/util/Collection
     130: invokeinterface #244,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
     135: ifeq          142
     138: iconst_1
     139: goto          211
     142: aload_3
     143: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     148: astore        5
     150: aload         5
     152: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     157: ifeq          210
     160: aload         5
     162: checkcast     #205                // class kotlin/collections/IntIterator
     165: invokevirtual #208                // Method kotlin/collections/IntIterator.nextInt:()I
     168: istore        6
     170: iload         6
     172: istore        7
     174: iconst_0
     175: istore        8
     177: aload_0
     178: iload         7
     180: iconst_5
     181: imul
     182: iload_1
     183: iadd
     184: invokeinterface #212,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     189: checkcast     #214                // class java/lang/Number
     192: invokevirtual #217                // Method java/lang/Number.intValue:()I
     195: ifge          202
     198: iconst_1
     199: goto          203
     202: iconst_0
     203: ifne          150
     206: iconst_0
     207: goto          211
     210: iconst_1
     211: ifeq          218
     214: iconst_1
     215: goto          219
     218: iconst_0
     219: ireturn

  private static final int part1(java.util.List<java.lang.Integer>, java.util.List<? extends java.util.List<java.lang.Integer>>);
    Code:
       0: aload_0
       1: checkcast     #25                 // class java/lang/Iterable
       4: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
       9: astore_2
      10: aload_2
      11: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      16: ifeq          251
      19: aload_2
      20: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      25: checkcast     #214                // class java/lang/Number
      28: invokevirtual #217                // Method java/lang/Number.intValue:()I
      31: istore_3
      32: iconst_0
      33: istore        4
      35: aload_1
      36: checkcast     #25                 // class java/lang/Iterable
      39: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      44: astore        5
      46: aload         5
      48: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      53: ifeq          241
      56: aload         5
      58: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      63: checkcast     #20                 // class java/util/List
      66: astore        6
      68: iconst_0
      69: istore        7
      71: aload         6
      73: iload_3
      74: invokestatic  #254                // Method findPosition:(Ljava/util/List;I)Lday04/Position;
      77: dup
      78: ifnull        226
      81: astore        8
      83: iconst_0
      84: istore        9
      86: aload         8
      88: invokevirtual #256                // Method day04/Position.component1:()I
      91: istore        10
      93: aload         8
      95: invokevirtual #258                // Method day04/Position.component2:()I
      98: istore        11
     100: aload         8
     102: invokevirtual #261                // Method day04/Position.component3:()I
     105: istore        12
     107: aload         6
     109: iload         12
     111: invokestatic  #263                // Method mark:(Ljava/util/List;I)V
     114: aload         6
     116: iload         10
     118: iload         11
     120: invokestatic  #265                // Method hasWon:(Ljava/util/List;II)Z
     123: ifeq          222
     126: iload_3
     127: aload         6
     129: checkcast     #25                 // class java/lang/Iterable
     132: astore        13
     134: istore        14
     136: iconst_0
     137: istore        15
     139: aload         13
     141: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     146: astore        16
     148: aload         16
     150: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     155: ifeq          207
     158: aload         16
     160: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     165: astore        17
     167: iload         15
     169: aload         17
     171: checkcast     #214                // class java/lang/Number
     174: invokevirtual #217                // Method java/lang/Number.intValue:()I
     177: istore        18
     179: istore        19
     181: iconst_0
     182: istore        20
     184: iload         18
     186: iflt          194
     189: iload         18
     191: goto          195
     194: iconst_0
     195: istore        21
     197: iload         19
     199: iload         21
     201: iadd
     202: istore        15
     204: goto          148
     207: iload         15
     209: istore        19
     211: iload         14
     213: iload         19
     215: imul
     216: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     219: goto          223
     222: aconst_null
     223: goto          228
     226: pop
     227: aconst_null
     228: nop
     229: astore        6
     231: aload         6
     233: ifnull        46
     236: aload         6
     238: goto          242
     241: aconst_null
     242: nop
     243: dup
     244: ifnonnull     252
     247: pop
     248: goto          10
     251: aconst_null
     252: dup
     253: ifnonnull     268
     256: pop
     257: new           #267                // class java/util/NoSuchElementException
     260: dup
     261: ldc_w         #269                // String No element of the collection was transformed to a non-null value.
     264: invokespecial #270                // Method java/util/NoSuchElementException."<init>":(Ljava/lang/String;)V
     267: athrow
     268: checkcast     #214                // class java/lang/Number
     271: invokevirtual #217                // Method java/lang/Number.intValue:()I
     274: ireturn

  private static final int part2(java.util.List<java.lang.Integer>, java.util.List<? extends java.util.List<java.lang.Integer>>);
    Code:
       0: aload_1
       1: checkcast     #25                 // class java/lang/Iterable
       4: astore_2
       5: iconst_0
       6: istore_3
       7: aload_2
       8: astore        4
      10: new           #27                 // class java/util/ArrayList
      13: dup
      14: aload_2
      15: bipush        10
      17: invokestatic  #33                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      20: invokespecial #37                 // Method java/util/ArrayList."<init>":(I)V
      23: checkcast     #39                 // class java/util/Collection
      26: astore        5
      28: iconst_0
      29: istore        6
      31: aload         4
      33: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      38: astore        7
      40: aload         7
      42: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      47: ifeq          241
      50: aload         7
      52: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      57: astore        8
      59: aload         5
      61: aload         8
      63: checkcast     #20                 // class java/util/List
      66: astore        9
      68: astore        23
      70: iconst_0
      71: istore        10
      73: aload_0
      74: astore        11
      76: iconst_0
      77: istore        12
      79: iconst_0
      80: istore        13
      82: aload         11
      84: invokeinterface #276,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      89: astore        14
      91: aload         14
      93: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      98: ifeq          196
     101: aload         14
     103: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     108: astore        15
     110: aload         15
     112: checkcast     #214                // class java/lang/Number
     115: invokevirtual #217                // Method java/lang/Number.intValue:()I
     118: istore        16
     120: iconst_0
     121: istore        17
     123: aload         9
     125: iload         16
     127: invokestatic  #254                // Method findPosition:(Ljava/util/List;I)Lday04/Position;
     130: dup
     131: ifnull        180
     134: astore        18
     136: iconst_0
     137: istore        19
     139: aload         18
     141: invokevirtual #256                // Method day04/Position.component1:()I
     144: istore        20
     146: aload         18
     148: invokevirtual #258                // Method day04/Position.component2:()I
     151: istore        21
     153: aload         18
     155: invokevirtual #261                // Method day04/Position.component3:()I
     158: istore        22
     160: aload         9
     162: iload         22
     164: invokestatic  #263                // Method mark:(Ljava/util/List;I)V
     167: aload         9
     169: iload         20
     171: iload         21
     173: invokestatic  #265                // Method hasWon:(Ljava/util/List;II)Z
     176: nop
     177: goto          182
     180: pop
     181: iconst_0
     182: ifeq          190
     185: iload         13
     187: goto          197
     190: iinc          13, 1
     193: goto          91
     196: iconst_m1
     197: istore        12
     199: iconst_0
     200: istore        13
     202: new           #278                // class day04/Victory
     205: dup
     206: iload         12
     208: aload_0
     209: iload         12
     211: invokeinterface #212,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     216: checkcast     #214                // class java/lang/Number
     219: invokevirtual #217                // Method java/lang/Number.intValue:()I
     222: aload         9
     224: invokespecial #281                // Method day04/Victory."<init>":(IILjava/util/List;)V
     227: nop
     228: nop
     229: aload         23
     231: swap
     232: invokeinterface #60,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     237: pop
     238: goto          40
     241: aload         5
     243: checkcast     #20                 // class java/util/List
     246: nop
     247: checkcast     #25                 // class java/lang/Iterable
     250: astore_2
     251: nop
     252: iconst_0
     253: istore_3
     254: aload_2
     255: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     260: astore        4
     262: aload         4
     264: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     269: ifne          276
     272: aconst_null
     273: goto          370
     276: aload         4
     278: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     283: astore        5
     285: aload         4
     287: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     292: ifne          300
     295: aload         5
     297: goto          370
     300: aload         5
     302: checkcast     #278                // class day04/Victory
     305: astore        6
     307: iconst_0
     308: istore        7
     310: aload         6
     312: invokevirtual #284                // Method day04/Victory.getTurn:()I
     315: istore        6
     317: aload         4
     319: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     324: astore        7
     326: aload         7
     328: checkcast     #278                // class day04/Victory
     331: astore        8
     333: iconst_0
     334: istore        9
     336: aload         8
     338: invokevirtual #284                // Method day04/Victory.getTurn:()I
     341: istore        8
     343: iload         6
     345: iload         8
     347: if_icmpge     358
     350: aload         7
     352: astore        5
     354: iload         8
     356: istore        6
     358: aload         4
     360: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     365: ifne          317
     368: aload         5
     370: dup
     371: invokestatic  #289                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     374: checkcast     #278                // class day04/Victory
     377: astore_3
     378: iconst_0
     379: istore        4
     381: aload_3
     382: invokevirtual #290                // Method day04/Victory.component2:()I
     385: istore        5
     387: aload_3
     388: invokevirtual #293                // Method day04/Victory.component3:()Ljava/util/List;
     391: astore        6
     393: iload         5
     395: aload         6
     397: checkcast     #25                 // class java/lang/Iterable
     400: astore        7
     402: istore        8
     404: iconst_0
     405: istore        9
     407: aload         7
     409: invokeinterface #43,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     414: astore        10
     416: aload         10
     418: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     423: ifeq          475
     426: aload         10
     428: invokeinterface #52,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     433: astore        11
     435: iload         9
     437: aload         11
     439: checkcast     #214                // class java/lang/Number
     442: invokevirtual #217                // Method java/lang/Number.intValue:()I
     445: istore        12
     447: istore        13
     449: iconst_0
     450: istore        14
     452: iload         12
     454: iflt          462
     457: iload         12
     459: goto          463
     462: iconst_0
     463: istore        15
     465: iload         13
     467: iload         15
     469: iadd
     470: istore        9
     472: goto          416
     475: iload         9
     477: istore        13
     479: iload         8
     481: iload         13
     483: imul
     484: nop
     485: ireturn

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


package day03

import java.io.File

fun main() {
    val data = parse("src/main/kotlin/day03/Day03.txt")

    val answer1 = part1(data)
    val answer2 = part2(data)

    println("🎄 Day 03 🎄")

    println()

    println("[Part 1]")
    println("Answer: $answer1")

    println()

    println("[Part 2]")
    println("Answer: $answer2")
}

private fun parse(path: String): List<String> =
    File(path).readLines()

private fun part1(lines: List<String>): Int {
    val bitCount = lines[0].length
    val gamma = (0 until bitCount)
        .map { index -> lines.count { line -> line[index] == '1' } }
        .map { count -> if (2 * count > lines.size) 1 else 0 }
        .fold(0) { acc, bit -> (acc shl 1) or bit }

    val epsilon = gamma xor ((1 shl bitCount) - 1)
    return gamma * epsilon
}

private fun part2(lines: List<String>): Int {
    val calculateRating = { criteria: Char, complement: Char ->
        var index = 0
        val values = lines.toMutableList()
        while (values.size != 1) {
            val count = values.count { it[index] == '1' }
            val bit = if (2 * count >= values.size) criteria else complement
            values.removeAll { it[index] == bit }
            ++index
        }
        values.first().toInt(radix = 2)
    }

    val o2 = calculateRating('1', '0')
    val co2 = calculateRating('0', '1')

    return o2 * co2
}

Compiled from "Day03.kt"
public final class day03.Day03Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String src/main/kotlin/day03/Day03.txt
       2: invokestatic  #12                 // Method parse:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: invokestatic  #16                 // Method part1:(Ljava/util/List;)I
      10: istore_1
      11: aload_0
      12: invokestatic  #19                 // Method part2:(Ljava/util/List;)I
      15: istore_2
      16: ldc           #21                 // String 🎄 Day 03 🎄
      18: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      21: swap
      22: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      25: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      28: invokevirtual #35                 // Method java/io/PrintStream.println:()V
      31: ldc           #37                 // String [Part 1]
      33: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      36: swap
      37: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      40: new           #39                 // class java/lang/StringBuilder
      43: dup
      44: invokespecial #42                 // Method java/lang/StringBuilder."<init>":()V
      47: ldc           #44                 // String Answer:
      49: invokevirtual #48                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      52: iload_1
      53: invokevirtual #51                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      56: invokevirtual #55                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      59: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      62: swap
      63: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      66: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      69: invokevirtual #35                 // Method java/io/PrintStream.println:()V
      72: ldc           #57                 // String [Part 2]
      74: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      77: swap
      78: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      81: new           #39                 // class java/lang/StringBuilder
      84: dup
      85: invokespecial #42                 // Method java/lang/StringBuilder."<init>":()V
      88: ldc           #44                 // String Answer:
      90: invokevirtual #48                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      93: iload_2
      94: invokevirtual #51                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      97: invokevirtual #55                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     100: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
     103: swap
     104: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     107: return

  private static final java.util.List<java.lang.String> parse(java.lang.String);
    Code:
       0: new           #65                 // class java/io/File
       3: dup
       4: aload_0
       5: invokespecial #68                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       8: aconst_null
       9: iconst_1
      10: aconst_null
      11: invokestatic  #74                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      14: areturn

  private static final int part1(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: iconst_0
       2: invokeinterface #83,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
       7: checkcast     #85                 // class java/lang/String
      10: invokevirtual #89                 // Method java/lang/String.length:()I
      13: istore_1
      14: iconst_0
      15: iload_1
      16: invokestatic  #95                 // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
      19: checkcast     #97                 // class java/lang/Iterable
      22: astore_3
      23: nop
      24: iconst_0
      25: istore        4
      27: aload_3
      28: astore        5
      30: new           #99                 // class java/util/ArrayList
      33: dup
      34: aload_3
      35: bipush        10
      37: invokestatic  #105                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      40: invokespecial #108                // Method java/util/ArrayList."<init>":(I)V
      43: checkcast     #110                // class java/util/Collection
      46: astore        6
      48: iconst_0
      49: istore        7
      51: aload         5
      53: invokeinterface #114,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      58: astore        8
      60: aload         8
      62: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      67: ifeq          218
      70: aload         8
      72: checkcast     #122                // class kotlin/collections/IntIterator
      75: invokevirtual #125                // Method kotlin/collections/IntIterator.nextInt:()I
      78: istore        9
      80: aload         6
      82: iload         9
      84: istore        10
      86: astore        19
      88: iconst_0
      89: istore        11
      91: aload_0
      92: checkcast     #97                 // class java/lang/Iterable
      95: astore        12
      97: iconst_0
      98: istore        13
     100: aload         12
     102: instanceof    #110                // class java/util/Collection
     105: ifeq          125
     108: aload         12
     110: checkcast     #110                // class java/util/Collection
     113: invokeinterface #128,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
     118: ifeq          125
     121: iconst_0
     122: goto          202
     125: iconst_0
     126: istore        14
     128: aload         12
     130: invokeinterface #114,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     135: astore        15
     137: aload         15
     139: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     144: ifeq          200
     147: aload         15
     149: invokeinterface #132,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     154: astore        16
     156: aload         16
     158: checkcast     #85                 // class java/lang/String
     161: astore        17
     163: iconst_0
     164: istore        18
     166: aload         17
     168: iload         10
     170: invokevirtual #136                // Method java/lang/String.charAt:(I)C
     173: bipush        49
     175: if_icmpne     182
     178: iconst_1
     179: goto          183
     182: iconst_0
     183: ifeq          137
     186: iinc          14, 1
     189: iload         14
     191: ifge          137
     194: invokestatic  #139                // Method kotlin/collections/CollectionsKt.throwCountOverflow:()V
     197: goto          137
     200: iload         14
     202: nop
     203: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     206: aload         19
     208: swap
     209: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     214: pop
     215: goto          60
     218: aload         6
     220: checkcast     #79                 // class java/util/List
     223: nop
     224: checkcast     #97                 // class java/lang/Iterable
     227: astore_3
     228: nop
     229: iconst_0
     230: istore        4
     232: aload_3
     233: astore        5
     235: new           #99                 // class java/util/ArrayList
     238: dup
     239: aload_3
     240: bipush        10
     242: invokestatic  #105                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     245: invokespecial #108                // Method java/util/ArrayList."<init>":(I)V
     248: checkcast     #110                // class java/util/Collection
     251: astore        6
     253: iconst_0
     254: istore        7
     256: aload         5
     258: invokeinterface #114,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     263: astore        8
     265: aload         8
     267: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     272: ifeq          334
     275: aload         8
     277: invokeinterface #132,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     282: astore        9
     284: aload         6
     286: aload         9
     288: checkcast     #151                // class java/lang/Number
     291: invokevirtual #154                // Method java/lang/Number.intValue:()I
     294: istore        10
     296: astore        19
     298: iconst_0
     299: istore        11
     301: iconst_2
     302: iload         10
     304: imul
     305: aload_0
     306: invokeinterface #157,  1          // InterfaceMethod java/util/List.size:()I
     311: if_icmple     318
     314: iconst_1
     315: goto          319
     318: iconst_0
     319: invokestatic  #145                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     322: aload         19
     324: swap
     325: invokeinterface #149,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     330: pop
     331: goto          265
     334: aload         6
     336: checkcast     #79                 // class java/util/List
     339: nop
     340: checkcast     #97                 // class java/lang/Iterable
     343: astore_3
     344: iconst_0
     345: istore        4
     347: iconst_0
     348: istore        5
     350: iload         4
     352: istore        6
     354: aload_3
     355: invokeinterface #114,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     360: astore        7
     362: aload         7
     364: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     369: ifeq          410
     372: aload         7
     374: invokeinterface #132,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     379: astore        8
     381: iload         6
     383: aload         8
     385: checkcast     #151                // class java/lang/Number
     388: invokevirtual #154                // Method java/lang/Number.intValue:()I
     391: istore        9
     393: istore        10
     395: iconst_0
     396: istore        11
     398: iload         10
     400: iconst_1
     401: ishl
     402: iload         9
     404: ior
     405: istore        6
     407: goto          362
     410: iload         6
     412: istore_2
     413: iload_2
     414: iconst_1
     415: iload_1
     416: ishl
     417: iconst_1
     418: isub
     419: ixor
     420: istore_3
     421: iload_2
     422: iload_3
     423: imul
     424: ireturn

  private static final int part2(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: invokedynamic #207,  0            // InvokeDynamic #0:invoke:(Ljava/util/List;)Lkotlin/jvm/functions/Function2;
       6: astore_1
       7: aload_1
       8: bipush        49
      10: invokestatic  #212                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      13: bipush        48
      15: invokestatic  #212                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      18: invokeinterface #216,  3          // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      23: checkcast     #151                // class java/lang/Number
      26: invokevirtual #154                // Method java/lang/Number.intValue:()I
      29: istore_2
      30: aload_1
      31: bipush        48
      33: invokestatic  #212                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      36: bipush        49
      38: invokestatic  #212                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      41: invokeinterface #216,  3          // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      46: checkcast     #151                // class java/lang/Number
      49: invokevirtual #154                // Method java/lang/Number.intValue:()I
      52: istore_3
      53: iload_2
      54: iload_3
      55: imul
      56: ireturn

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

  private static final boolean part2$lambda$6$lambda$5(kotlin.jvm.internal.Ref$IntRef, char, java.lang.String);
    Code:
       0: aload_2
       1: ldc           #229                // String it
       3: invokestatic  #235                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: aload_0
       8: getfield      #240                // Field kotlin/jvm/internal/Ref$IntRef.element:I
      11: invokevirtual #136                // Method java/lang/String.charAt:(I)C
      14: iload_1
      15: if_icmpne     22
      18: iconst_1
      19: goto          23
      22: iconst_0
      23: ireturn

  private static final int part2$lambda$6(java.util.List, char, char);
    Code:
       0: new           #237                // class kotlin/jvm/internal/Ref$IntRef
       3: dup
       4: invokespecial #245                // Method kotlin/jvm/internal/Ref$IntRef."<init>":()V
       7: astore_3
       8: aload_0
       9: checkcast     #110                // class java/util/Collection
      12: invokestatic  #249                // Method kotlin/collections/CollectionsKt.toMutableList:(Ljava/util/Collection;)Ljava/util/List;
      15: astore        4
      17: aload         4
      19: invokeinterface #157,  1          // InterfaceMethod java/util/List.size:()I
      24: iconst_1
      25: if_icmpeq     197
      28: aload         4
      30: checkcast     #97                 // class java/lang/Iterable
      33: astore        6
      35: iconst_0
      36: istore        7
      38: aload         6
      40: instanceof    #110                // class java/util/Collection
      43: ifeq          63
      46: aload         6
      48: checkcast     #110                // class java/util/Collection
      51: invokeinterface #128,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      56: ifeq          63
      59: iconst_0
      60: goto          142
      63: iconst_0
      64: istore        8
      66: aload         6
      68: invokeinterface #114,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      73: astore        9
      75: aload         9
      77: invokeinterface #120,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      82: ifeq          140
      85: aload         9
      87: invokeinterface #132,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      92: astore        10
      94: aload         10
      96: checkcast     #85                 // class java/lang/String
      99: astore        11
     101: iconst_0
     102: istore        12
     104: aload         11
     106: aload_3
     107: getfield      #240                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     110: invokevirtual #136                // Method java/lang/String.charAt:(I)C
     113: bipush        49
     115: if_icmpne     122
     118: iconst_1
     119: goto          123
     122: iconst_0
     123: ifeq          75
     126: iinc          8, 1
     129: iload         8
     131: ifge          75
     134: invokestatic  #139                // Method kotlin/collections/CollectionsKt.throwCountOverflow:()V
     137: goto          75
     140: iload         8
     142: istore        5
     144: iconst_2
     145: iload         5
     147: imul
     148: aload         4
     150: invokeinterface #157,  1          // InterfaceMethod java/util/List.size:()I
     155: if_icmplt     162
     158: iload_1
     159: goto          163
     162: iload_2
     163: istore        6
     165: aload         4
     167: aload_3
     168: iload         6
     170: invokedynamic #259,  0            // InvokeDynamic #1:invoke:(Lkotlin/jvm/internal/Ref$IntRef;C)Lkotlin/jvm/functions/Function1;
     175: invokestatic  #263                // Method kotlin/collections/CollectionsKt.removeAll:(Ljava/util/List;Lkotlin/jvm/functions/Function1;)Z
     178: pop
     179: aload_3
     180: aload_3
     181: getfield      #240                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     184: iconst_1
     185: iadd
     186: putfield      #240                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     189: aload_3
     190: getfield      #240                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     193: pop
     194: goto          17
     197: aload         4
     199: invokestatic  #267                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
     202: checkcast     #85                 // class java/lang/String
     205: iconst_2
     206: invokestatic  #273                // Method kotlin/text/CharsKt.checkRadix:(I)I
     209: invokestatic  #277                // Method java/lang/Integer.parseInt:(Ljava/lang/String;I)I
     212: ireturn
}


package day02

import java.io.File

fun main() {
    val data = parse("src/main/kotlin/day02/Day02.txt")

    val answer1 = part1(data)
    val answer2 = part2(data)

    println("🎄 Day 02 🎄")

    println()

    println("[Part 1]")
    println("Answer: $answer1")

    println()

    println("[Part 2]")
    println("Answer: $answer2")
}

private enum class Action {
    Up, Down, Forward,
}

private data class Command(
    val action: Action,
    val number: Int,
)

private fun parse(path: String): List<Command> =
    File(path)
        .readLines()
        .map(String::toCommand)

private fun String.toCommand(): Command {
    val (actionPart, numberPart) = this.split(" ")
    val action = when (actionPart) {
        "up" -> Action.Up
        "down" -> Action.Down
        "forward" -> Action.Forward
        else -> error("Invalid action")
    }
    val number = numberPart.toInt()
    return Command(action, number)
}

private fun part1(commands: List<Command>): Int {
    var (horizontal, depth) = arrayOf(0, 0)
    for ((action, number) in commands) {
        when (action) {
            Action.Up -> depth -= number
            Action.Down -> depth += number
            Action.Forward -> horizontal += number
        }
    }
    return horizontal * depth
}

private fun part2(commands: List<Command>): Int {
    var (horizontal, depth, aim) = arrayOf(0, 0, 0)
    for ((action, number) in commands) {
        when (action) {
            Action.Up -> aim -= number
            Action.Down -> aim += number
            Action.Forward -> {
                horizontal += number
                depth += aim * number
            }
        }
    }
    return horizontal * depth
}

Compiled from "Day02.kt"
public final class day02.Day02Kt {
  public static final void main();
    Code:
       0: ldc           #8                  // String src/main/kotlin/day02/Day02.txt
       2: invokestatic  #12                 // Method parse:(Ljava/lang/String;)Ljava/util/List;
       5: astore_0
       6: aload_0
       7: invokestatic  #16                 // Method part1:(Ljava/util/List;)I
      10: istore_1
      11: aload_0
      12: invokestatic  #19                 // Method part2:(Ljava/util/List;)I
      15: istore_2
      16: ldc           #21                 // String 🎄 Day 02 🎄
      18: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      21: swap
      22: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      25: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      28: invokevirtual #35                 // Method java/io/PrintStream.println:()V
      31: ldc           #37                 // String [Part 1]
      33: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      36: swap
      37: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      40: new           #39                 // class java/lang/StringBuilder
      43: dup
      44: invokespecial #42                 // Method java/lang/StringBuilder."<init>":()V
      47: ldc           #44                 // String Answer:
      49: invokevirtual #48                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      52: iload_1
      53: invokevirtual #51                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      56: invokevirtual #55                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      59: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      62: swap
      63: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      66: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      69: invokevirtual #35                 // Method java/io/PrintStream.println:()V
      72: ldc           #57                 // String [Part 2]
      74: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
      77: swap
      78: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      81: new           #39                 // class java/lang/StringBuilder
      84: dup
      85: invokespecial #42                 // Method java/lang/StringBuilder."<init>":()V
      88: ldc           #44                 // String Answer:
      90: invokevirtual #48                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      93: iload_2
      94: invokevirtual #51                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      97: invokevirtual #55                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     100: getstatic     #27                 // Field java/lang/System.out:Ljava/io/PrintStream;
     103: swap
     104: invokevirtual #33                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     107: return

  private static final java.util.List<day02.Command> parse(java.lang.String);
    Code:
       0: new           #65                 // class java/io/File
       3: dup
       4: aload_0
       5: invokespecial #68                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       8: aconst_null
       9: iconst_1
      10: aconst_null
      11: invokestatic  #74                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      14: checkcast     #76                 // class java/lang/Iterable
      17: astore_1
      18: nop
      19: iconst_0
      20: istore_2
      21: aload_1
      22: astore_3
      23: new           #78                 // class java/util/ArrayList
      26: dup
      27: aload_1
      28: bipush        10
      30: invokestatic  #84                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      33: invokespecial #87                 // Method java/util/ArrayList."<init>":(I)V
      36: checkcast     #89                 // class java/util/Collection
      39: astore        4
      41: iconst_0
      42: istore        5
      44: aload_3
      45: invokeinterface #93,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      50: astore        6
      52: aload         6
      54: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      59: ifeq          102
      62: aload         6
      64: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      69: astore        7
      71: aload         4
      73: aload         7
      75: checkcast     #105                // class java/lang/String
      78: astore        8
      80: astore        10
      82: iconst_0
      83: istore        9
      85: aload         8
      87: invokestatic  #109                // Method toCommand:(Ljava/lang/String;)Lday02/Command;
      90: aload         10
      92: swap
      93: invokeinterface #113,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      98: pop
      99: goto          52
     102: aload         4
     104: checkcast     #115                // class java/util/List
     107: nop
     108: areturn

  private static final day02.Command toCommand(java.lang.String);
    Code:
       0: aload_0
       1: checkcast     #130                // class java/lang/CharSequence
       4: iconst_1
       5: anewarray     #105                // class java/lang/String
       8: astore_2
       9: aload_2
      10: iconst_0
      11: ldc           #132                // String
      13: aastore
      14: aload_2
      15: iconst_0
      16: iconst_0
      17: bipush        6
      19: aconst_null
      20: invokestatic  #138                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      23: astore_1
      24: aload_1
      25: iconst_0
      26: invokeinterface #142,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      31: checkcast     #105                // class java/lang/String
      34: astore_2
      35: aload_1
      36: iconst_1
      37: invokeinterface #142,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      42: checkcast     #105                // class java/lang/String
      45: astore_3
      46: aload_2
      47: astore        5
      49: aload         5
      51: invokevirtual #146                // Method java/lang/String.hashCode:()I
      54: lookupswitch  { // 3
            -677145915: 88
                  3739: 101
               3089570: 114
               default: 145
          }
      88: aload         5
      90: ldc           #148                // String forward
      92: invokevirtual #151                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      95: ifne          139
      98: goto          145
     101: aload         5
     103: ldc           #153                // String up
     105: invokevirtual #151                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     108: ifne          127
     111: goto          145
     114: aload         5
     116: ldc           #155                // String down
     118: invokevirtual #151                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     121: ifne          133
     124: goto          145
     127: getstatic     #161                // Field day02/Action.Up:Lday02/Action;
     130: goto          158
     133: getstatic     #164                // Field day02/Action.Down:Lday02/Action;
     136: goto          158
     139: getstatic     #167                // Field day02/Action.Forward:Lday02/Action;
     142: goto          158
     145: new           #169                // class java/lang/IllegalStateException
     148: dup
     149: ldc           #171                // String Invalid action
     151: invokevirtual #172                // Method java/lang/Object.toString:()Ljava/lang/String;
     154: invokespecial #173                // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     157: athrow
     158: astore        4
     160: aload_3
     161: invokestatic  #179                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     164: istore        5
     166: new           #181                // class day02/Command
     169: dup
     170: aload         4
     172: iload         5
     174: invokespecial #184                // Method day02/Command."<init>":(Lday02/Action;I)V
     177: areturn

  private static final int part1(java.util.List<day02.Command>);
    Code:
       0: iconst_2
       1: anewarray     #175                // class java/lang/Integer
       4: astore_2
       5: aload_2
       6: iconst_0
       7: iconst_0
       8: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: aastore
      12: aload_2
      13: iconst_1
      14: iconst_0
      15: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      18: aastore
      19: aload_2
      20: astore_1
      21: aload_1
      22: iconst_0
      23: aaload
      24: checkcast     #196                // class java/lang/Number
      27: invokevirtual #199                // Method java/lang/Number.intValue:()I
      30: istore_2
      31: aload_1
      32: iconst_1
      33: aaload
      34: checkcast     #196                // class java/lang/Number
      37: invokevirtual #199                // Method java/lang/Number.intValue:()I
      40: istore_3
      41: aload_0
      42: invokeinterface #200,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      47: astore        4
      49: aload         4
      51: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      56: ifeq          152
      59: aload         4
      61: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      66: checkcast     #181                // class day02/Command
      69: astore        5
      71: aload         5
      73: invokevirtual #204                // Method day02/Command.component1:()Lday02/Action;
      76: astore        6
      78: aload         5
      80: invokevirtual #207                // Method day02/Command.component2:()I
      83: istore        7
      85: aload         6
      87: getstatic     #213                // Field day02/Day02Kt$WhenMappings.$EnumSwitchMapping$0:[I
      90: swap
      91: invokevirtual #216                // Method day02/Action.ordinal:()I
      94: iaload
      95: tableswitch   { // 1 to 3
                     1: 120
                     2: 128
                     3: 136
               default: 144
          }
     120: iload_3
     121: iload         7
     123: isub
     124: istore_3
     125: goto          49
     128: iload_3
     129: iload         7
     131: iadd
     132: istore_3
     133: goto          49
     136: iload_2
     137: iload         7
     139: iadd
     140: istore_2
     141: goto          49
     144: new           #218                // class kotlin/NoWhenBranchMatchedException
     147: dup
     148: invokespecial #219                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     151: athrow
     152: iload_2
     153: iload_3
     154: imul
     155: ireturn

  private static final int part2(java.util.List<day02.Command>);
    Code:
       0: iconst_3
       1: anewarray     #175                // class java/lang/Integer
       4: astore_2
       5: aload_2
       6: iconst_0
       7: iconst_0
       8: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: aastore
      12: aload_2
      13: iconst_1
      14: iconst_0
      15: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      18: aastore
      19: aload_2
      20: iconst_2
      21: iconst_0
      22: invokestatic  #194                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: aload_2
      27: astore_1
      28: aload_1
      29: iconst_0
      30: aaload
      31: checkcast     #196                // class java/lang/Number
      34: invokevirtual #199                // Method java/lang/Number.intValue:()I
      37: istore_2
      38: aload_1
      39: iconst_1
      40: aaload
      41: checkcast     #196                // class java/lang/Number
      44: invokevirtual #199                // Method java/lang/Number.intValue:()I
      47: istore_3
      48: aload_1
      49: iconst_2
      50: aaload
      51: checkcast     #196                // class java/lang/Number
      54: invokevirtual #199                // Method java/lang/Number.intValue:()I
      57: istore        4
      59: aload_0
      60: invokeinterface #200,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      65: astore        5
      67: aload         5
      69: invokeinterface #99,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      74: ifeq          184
      77: aload         5
      79: invokeinterface #103,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      84: checkcast     #181                // class day02/Command
      87: astore        6
      89: aload         6
      91: invokevirtual #204                // Method day02/Command.component1:()Lday02/Action;
      94: astore        7
      96: aload         6
      98: invokevirtual #207                // Method day02/Command.component2:()I
     101: istore        8
     103: aload         7
     105: getstatic     #213                // Field day02/Day02Kt$WhenMappings.$EnumSwitchMapping$0:[I
     108: swap
     109: invokevirtual #216                // Method day02/Action.ordinal:()I
     112: iaload
     113: tableswitch   { // 1 to 3
                     1: 140
                     2: 150
                     3: 160
               default: 176
          }
     140: iload         4
     142: iload         8
     144: isub
     145: istore        4
     147: goto          67
     150: iload         4
     152: iload         8
     154: iadd
     155: istore        4
     157: goto          67
     160: iload_2
     161: iload         8
     163: iadd
     164: istore_2
     165: iload_3
     166: iload         4
     168: iload         8
     170: imul
     171: iadd
     172: istore_3
     173: goto          67
     176: new           #218                // class kotlin/NoWhenBranchMatchedException
     179: dup
     180: invokespecial #219                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     183: athrow
     184: iload_2
     185: iload_3
     186: imul
     187: ireturn

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

Compiled from "Day02.kt"
public final class day02.Day02Kt$WhenMappings {
  public static final int[] $EnumSwitchMapping$0;

  static {};
    Code:
       0: invokestatic  #14                 // Method day02/Action.values:()[Lday02/Action;
       3: arraylength
       4: newarray       int
       6: astore_0
       7: nop
       8: aload_0
       9: getstatic     #18                 // Field day02/Action.Up:Lday02/Action;
      12: invokevirtual #22                 // Method day02/Action.ordinal:()I
      15: iconst_1
      16: iastore
      17: goto          21
      20: astore_1
      21: nop
      22: aload_0
      23: getstatic     #25                 // Field day02/Action.Down:Lday02/Action;
      26: invokevirtual #22                 // Method day02/Action.ordinal:()I
      29: iconst_2
      30: iastore
      31: goto          35
      34: astore_1
      35: nop
      36: aload_0
      37: getstatic     #28                 // Field day02/Action.Forward:Lday02/Action;
      40: invokevirtual #22                 // Method day02/Action.ordinal:()I
      43: iconst_3
      44: iastore
      45: goto          49
      48: astore_1
      49: aload_0
      50: putstatic     #32                 // Field $EnumSwitchMapping$0:[I
      53: return
    Exception table:
       from    to  target type
           7    17    20   Class java/lang/NoSuchFieldError
          21    31    34   Class java/lang/NoSuchFieldError
          35    45    48   Class java/lang/NoSuchFieldError
}