package day04

import java.io.File

fun main() {
    var drawnNumbers: List<Int> = listOf()
    var bingoBoards: List<BingoBoard> = listOf()
    File("src/main/kotlin/day04/input.txt").useLines { seq ->
        val iterator = seq.iterator()
        drawnNumbers = List(1) { iterator.next() }.single().split(",").map { it.toInt() }

        bingoBoards = iterator.asSequence()
            .filter { it.isNotEmpty() }
            .chunked(5)
            .map { BingoBoard(it.map { it.split(" ").filter { it.isNotEmpty() }.map { it.toInt() } }.toList()) }
            .toList()

    }
    for (drawnNumber in drawnNumbers) {
        val indexOfWinningBoard = bingoBoards.indexOfFirst { it.isWinning(drawnNumber) }
        if (indexOfWinningBoard != -1) {
            println(drawnNumber * bingoBoards[indexOfWinningBoard].unmarkedNumbers().sum())
            break
        }
    }
    val notYetWonBoards = ArrayList(bingoBoards)
    val wonBoards = mutableListOf<BingoBoard>()
    for (drawnNumber in drawnNumbers) {
        val wonBoardsForDrawnNumber = notYetWonBoards.filter { it.isWinning(drawnNumber) }
        wonBoards.addAll(wonBoardsForDrawnNumber)
        notYetWonBoards.removeAll(wonBoardsForDrawnNumber)
        if (notYetWonBoards.isEmpty()) {
            println(drawnNumber * wonBoards.last().unmarkedNumbers().sum())
            break
        }
    }

}

class BingoBoard(private val board: List<List<Int>>) {
    private val markedNumbers: MutableList<Int> = mutableListOf()

    fun isWinning(drawnNumber: Int): Boolean {
        board.forEach {
            if (it.contains(drawnNumber)) {
                markedNumbers.add(drawnNumber)
            }
        }
        return checkBoard()
    }

    private fun checkBoard(): Boolean {
        return board.any {
            it.all { it in markedNumbers }
        } || (0..4).map { column ->
            board.map { it[column] }
        }.any {
            it.all { it in markedNumbers }
        }
    }

    fun unmarkedNumbers(): List<Int> = board.flatten().filter { it !in markedNumbers }
}

Compiled from "solution.kt"
public final class day04.SolutionKt {
  public static final void main();
    Code:
       0: new           #10                 // class kotlin/jvm/internal/Ref$ObjectRef
       3: dup
       4: invokespecial #13                 // Method kotlin/jvm/internal/Ref$ObjectRef."<init>":()V
       7: astore_0
       8: aload_0
       9: invokestatic  #19                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      12: putfield      #23                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
      15: aconst_null
      16: astore_1
      17: invokestatic  #19                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      20: astore_1
      21: new           #25                 // class java/io/File
      24: dup
      25: ldc           #27                 // String src/main/kotlin/day04/input.txt
      27: invokespecial #30                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      30: astore_2
      31: getstatic     #36                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      34: astore_3
      35: iconst_0
      36: istore        4
      38: aload_2
      39: astore        5
      41: sipush        8192
      44: istore        6
      46: aload         5
      48: astore        7
      50: new           #38                 // class java/io/InputStreamReader
      53: dup
      54: new           #40                 // class java/io/FileInputStream
      57: dup
      58: aload         7
      60: invokespecial #43                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      63: checkcast     #45                 // class java/io/InputStream
      66: aload_3
      67: invokespecial #48                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      70: checkcast     #50                 // class java/io/Reader
      73: astore        7
      75: aload         7
      77: instanceof    #52                 // class java/io/BufferedReader
      80: ifeq          91
      83: aload         7
      85: checkcast     #52                 // class java/io/BufferedReader
      88: goto          102
      91: new           #52                 // class java/io/BufferedReader
      94: dup
      95: aload         7
      97: iload         6
      99: invokespecial #55                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
     102: checkcast     #57                 // class java/io/Closeable
     105: astore        5
     107: aconst_null
     108: astore        6
     110: nop
     111: aload         5
     113: checkcast     #52                 // class java/io/BufferedReader
     116: astore        7
     118: iconst_0
     119: istore        8
     121: aload         7
     123: invokestatic  #63                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     126: astore        9
     128: iconst_0
     129: istore        10
     131: aload         9
     133: invokeinterface #69,  1           // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
     138: astore        11
     140: aload_0
     141: iconst_1
     142: istore        12
     144: astore        13
     146: new           #71                 // class java/util/ArrayList
     149: dup
     150: iload         12
     152: invokespecial #74                 // Method java/util/ArrayList."<init>":(I)V
     155: astore        14
     157: iconst_0
     158: istore        15
     160: iload         15
     162: iload         12
     164: if_icmpge     205
     167: iload         15
     169: istore        16
     171: aload         14
     173: iload         16
     175: istore        17
     177: astore        18
     179: iconst_0
     180: istore        19
     182: aload         11
     184: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     189: checkcast     #82                 // class java/lang/String
     192: aload         18
     194: swap
     195: invokevirtual #86                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     198: pop
     199: iinc          15, 1
     202: goto          160
     205: aload         14
     207: checkcast     #88                 // class java/util/List
     210: aload         13
     212: swap
     213: invokestatic  #92                 // Method kotlin/collections/CollectionsKt.single:(Ljava/util/List;)Ljava/lang/Object;
     216: checkcast     #94                 // class java/lang/CharSequence
     219: iconst_1
     220: anewarray     #82                 // class java/lang/String
     223: astore        12
     225: aload         12
     227: iconst_0
     228: ldc           #96                 // String ,
     230: aastore
     231: aload         12
     233: iconst_0
     234: iconst_0
     235: bipush        6
     237: aconst_null
     238: invokestatic  #102                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     241: checkcast     #104                // class java/lang/Iterable
     244: astore        12
     246: astore        13
     248: iconst_0
     249: istore        14
     251: aload         12
     253: astore        15
     255: new           #71                 // class java/util/ArrayList
     258: dup
     259: aload         12
     261: bipush        10
     263: invokestatic  #108                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     266: invokespecial #74                 // Method java/util/ArrayList."<init>":(I)V
     269: checkcast     #110                // class java/util/Collection
     272: astore        16
     274: iconst_0
     275: istore        17
     277: aload         15
     279: invokeinterface #111,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     284: astore        19
     286: aload         19
     288: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     293: ifeq          340
     296: aload         19
     298: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     303: astore        20
     305: aload         16
     307: aload         20
     309: checkcast     #82                 // class java/lang/String
     312: astore        21
     314: astore        18
     316: iconst_0
     317: istore        22
     319: aload         21
     321: invokestatic  #121                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     324: nop
     325: invokestatic  #125                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     328: aload         18
     330: swap
     331: invokeinterface #126,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     336: pop
     337: goto          286
     340: aload         16
     342: checkcast     #88                 // class java/util/List
     345: nop
     346: aload         13
     348: swap
     349: putfield      #23                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     352: aload         11
     354: invokestatic  #132                // Method kotlin/sequences/SequencesKt.asSequence:(Ljava/util/Iterator;)Lkotlin/sequences/Sequence;
     357: invokedynamic #152,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
     362: invokestatic  #156                // Method kotlin/sequences/SequencesKt.filter:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
     365: iconst_5
     366: invokestatic  #160                // Method kotlin/sequences/SequencesKt.chunked:(Lkotlin/sequences/Sequence;I)Lkotlin/sequences/Sequence;
     369: invokedynamic #167,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function1;
     374: invokestatic  #170                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
     377: invokestatic  #174                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
     380: astore_1
     381: nop
     382: getstatic     #180                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     385: astore        7
     387: aload         5
     389: aload         6
     391: invokestatic  #186                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     394: goto          418
     397: astore        8
     399: aload         8
     401: astore        6
     403: aload         8
     405: athrow
     406: astore        8
     408: aload         5
     410: aload         6
     412: invokestatic  #186                // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     415: aload         8
     417: athrow
     418: nop
     419: aload_0
     420: getfield      #23                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     423: checkcast     #88                 // class java/util/List
     426: invokeinterface #187,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     431: astore_2
     432: aload_2
     433: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     438: ifeq          565
     441: aload_2
     442: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     447: checkcast     #189                // class java/lang/Number
     450: invokevirtual #193                // Method java/lang/Number.intValue:()I
     453: istore_3
     454: aload_1
     455: astore        5
     457: iconst_0
     458: istore        6
     460: iconst_0
     461: istore        7
     463: aload         5
     465: invokeinterface #187,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     470: astore        8
     472: aload         8
     474: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     479: ifeq          521
     482: aload         8
     484: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     489: astore        9
     491: aload         9
     493: checkcast     #195                // class day04/BingoBoard
     496: astore        10
     498: iconst_0
     499: istore        11
     501: aload         10
     503: iload_3
     504: invokevirtual #199                // Method day04/BingoBoard.isWinning:(I)Z
     507: ifeq          515
     510: iload         7
     512: goto          522
     515: iinc          7, 1
     518: goto          472
     521: iconst_m1
     522: istore        4
     524: iload         4
     526: iconst_m1
     527: if_icmpeq     432
     530: iload_3
     531: aload_1
     532: iload         4
     534: invokeinterface #203,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     539: checkcast     #195                // class day04/BingoBoard
     542: invokevirtual #206                // Method day04/BingoBoard.unmarkedNumbers:()Ljava/util/List;
     545: checkcast     #104                // class java/lang/Iterable
     548: invokestatic  #210                // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
     551: imul
     552: istore        5
     554: getstatic     #216                // Field java/lang/System.out:Ljava/io/PrintStream;
     557: iload         5
     559: invokevirtual #221                // Method java/io/PrintStream.println:(I)V
     562: goto          565
     565: new           #71                 // class java/util/ArrayList
     568: dup
     569: aload_1
     570: checkcast     #110                // class java/util/Collection
     573: invokespecial #224                // Method java/util/ArrayList."<init>":(Ljava/util/Collection;)V
     576: astore_2
     577: new           #71                 // class java/util/ArrayList
     580: dup
     581: invokespecial #225                // Method java/util/ArrayList."<init>":()V
     584: checkcast     #88                 // class java/util/List
     587: astore_3
     588: aload_0
     589: getfield      #23                 // Field kotlin/jvm/internal/Ref$ObjectRef.element:Ljava/lang/Object;
     592: checkcast     #88                 // class java/util/List
     595: invokeinterface #187,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     600: astore        4
     602: aload         4
     604: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     609: ifeq          785
     612: aload         4
     614: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     619: checkcast     #189                // class java/lang/Number
     622: invokevirtual #193                // Method java/lang/Number.intValue:()I
     625: istore        5
     627: aload_2
     628: checkcast     #104                // class java/lang/Iterable
     631: astore        7
     633: iconst_0
     634: istore        8
     636: aload         7
     638: astore        9
     640: new           #71                 // class java/util/ArrayList
     643: dup
     644: invokespecial #225                // Method java/util/ArrayList."<init>":()V
     647: checkcast     #110                // class java/util/Collection
     650: astore        10
     652: iconst_0
     653: istore        11
     655: aload         9
     657: invokeinterface #111,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     662: astore        12
     664: aload         12
     666: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     671: ifeq          716
     674: aload         12
     676: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     681: astore        13
     683: aload         13
     685: checkcast     #195                // class day04/BingoBoard
     688: astore        14
     690: iconst_0
     691: istore        15
     693: aload         14
     695: iload         5
     697: invokevirtual #199                // Method day04/BingoBoard.isWinning:(I)Z
     700: ifeq          664
     703: aload         10
     705: aload         13
     707: invokeinterface #126,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     712: pop
     713: goto          664
     716: aload         10
     718: checkcast     #88                 // class java/util/List
     721: nop
     722: astore        6
     724: aload_3
     725: aload         6
     727: checkcast     #110                // class java/util/Collection
     730: invokeinterface #229,  2          // InterfaceMethod java/util/List.addAll:(Ljava/util/Collection;)Z
     735: pop
     736: aload_2
     737: aload         6
     739: checkcast     #110                // class java/util/Collection
     742: invokevirtual #232                // Method java/util/ArrayList.removeAll:(Ljava/util/Collection;)Z
     745: pop
     746: aload_2
     747: invokevirtual #235                // Method java/util/ArrayList.isEmpty:()Z
     750: ifeq          602
     753: iload         5
     755: aload_3
     756: invokestatic  #238                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
     759: checkcast     #195                // class day04/BingoBoard
     762: invokevirtual #206                // Method day04/BingoBoard.unmarkedNumbers:()Ljava/util/List;
     765: checkcast     #104                // class java/lang/Iterable
     768: invokestatic  #210                // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
     771: imul
     772: istore        7
     774: getstatic     #216                // Field java/lang/System.out:Ljava/io/PrintStream;
     777: iload         7
     779: invokevirtual #221                // Method java/io/PrintStream.println:(I)V
     782: goto          785
     785: return
    Exception table:
       from    to  target type
         110   387   397   Class java/lang/Throwable
         110   387   406   any
         397   406   406   any
         406   408   406   any

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

  private static final boolean main$lambda$7$lambda$2(java.lang.String);
    Code:
       0: aload_0
       1: ldc_w         #292                // String it
       4: invokestatic  #298                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: checkcast     #94                 // class java/lang/CharSequence
      11: invokeinterface #301,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      16: ifle          23
      19: iconst_1
      20: goto          24
      23: iconst_0
      24: ireturn

  private static final day04.BingoBoard main$lambda$7$lambda$6(java.util.List);
    Code:
       0: aload_0
       1: ldc_w         #292                // String it
       4: invokestatic  #298                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: checkcast     #104                // class java/lang/Iterable
      11: astore_1
      12: iconst_0
      13: istore_2
      14: aload_1
      15: astore_3
      16: new           #71                 // class java/util/ArrayList
      19: dup
      20: aload_1
      21: bipush        10
      23: invokestatic  #108                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      26: invokespecial #74                 // Method java/util/ArrayList."<init>":(I)V
      29: checkcast     #110                // class java/util/Collection
      32: astore        4
      34: iconst_0
      35: istore        5
      37: aload_3
      38: invokeinterface #111,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          329
      55: aload         6
      57: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      62: astore        7
      64: aload         4
      66: aload         7
      68: checkcast     #82                 // class java/lang/String
      71: astore        8
      73: astore        20
      75: iconst_0
      76: istore        9
      78: aload         8
      80: checkcast     #94                 // class java/lang/CharSequence
      83: iconst_1
      84: anewarray     #82                 // class java/lang/String
      87: astore        10
      89: aload         10
      91: iconst_0
      92: ldc_w         #303                // String
      95: aastore
      96: aload         10
      98: iconst_0
      99: iconst_0
     100: bipush        6
     102: aconst_null
     103: invokestatic  #102                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     106: checkcast     #104                // class java/lang/Iterable
     109: astore        10
     111: iconst_0
     112: istore        11
     114: aload         10
     116: astore        12
     118: new           #71                 // class java/util/ArrayList
     121: dup
     122: invokespecial #225                // Method java/util/ArrayList."<init>":()V
     125: checkcast     #110                // class java/util/Collection
     128: astore        13
     130: iconst_0
     131: istore        14
     133: aload         12
     135: invokeinterface #111,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     140: astore        15
     142: aload         15
     144: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     149: ifeq          206
     152: aload         15
     154: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     159: astore        16
     161: aload         16
     163: checkcast     #82                 // class java/lang/String
     166: astore        17
     168: iconst_0
     169: istore        18
     171: aload         17
     173: checkcast     #94                 // class java/lang/CharSequence
     176: invokeinterface #301,  1          // InterfaceMethod java/lang/CharSequence.length:()I
     181: ifle          188
     184: iconst_1
     185: goto          189
     188: iconst_0
     189: nop
     190: ifeq          142
     193: aload         13
     195: aload         16
     197: invokeinterface #126,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     202: pop
     203: goto          142
     206: aload         13
     208: checkcast     #88                 // class java/util/List
     211: nop
     212: checkcast     #104                // class java/lang/Iterable
     215: astore        10
     217: nop
     218: iconst_0
     219: istore        11
     221: aload         10
     223: astore        12
     225: new           #71                 // class java/util/ArrayList
     228: dup
     229: aload         10
     231: bipush        10
     233: invokestatic  #108                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     236: invokespecial #74                 // Method java/util/ArrayList."<init>":(I)V
     239: checkcast     #110                // class java/util/Collection
     242: astore        13
     244: iconst_0
     245: istore        14
     247: aload         12
     249: invokeinterface #111,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     254: astore        15
     256: aload         15
     258: invokeinterface #115,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     263: ifeq          310
     266: aload         15
     268: invokeinterface #80,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     273: astore        16
     275: aload         13
     277: aload         16
     279: checkcast     #82                 // class java/lang/String
     282: astore        17
     284: astore        19
     286: iconst_0
     287: istore        18
     289: aload         17
     291: invokestatic  #121                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     294: nop
     295: invokestatic  #125                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     298: aload         19
     300: swap
     301: invokeinterface #126,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     306: pop
     307: goto          256
     310: aload         13
     312: checkcast     #88                 // class java/util/List
     315: nop
     316: nop
     317: aload         20
     319: swap
     320: invokeinterface #126,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     325: pop
     326: goto          45
     329: aload         4
     331: checkcast     #88                 // class java/util/List
     334: nop
     335: checkcast     #104                // class java/lang/Iterable
     338: invokestatic  #306                // Method kotlin/collections/CollectionsKt.toList:(Ljava/lang/Iterable;)Ljava/util/List;
     341: astore        21
     343: new           #195                // class day04/BingoBoard
     346: dup
     347: aload         21
     349: invokespecial #309                // Method day04/BingoBoard."<init>":(Ljava/util/List;)V
     352: areturn
}


package day03

import java.io.File

fun main() {
    val lines = File("src/main/kotlin/day03/input.txt").readLines()
    val binaryCodeCounts = IntArray(12) { 0 }
    val reportDatBitsHistogram = lines
        .map { it.toCharArray() }
        .fold(binaryCodeCounts) { counter, reportLine ->
            for (i in counter.indices) {
                counter[i] += reportLine[i].digitToInt()
            }
            counter
        }
    val gammaRate = reportDatBitsHistogram
        .map { if (it > lines.size / 2) 0 else 1 }
        .joinToString(separator = "")
        .toCharArray()
        .binaryToDecimal()
    val epsilonRate = reportDatBitsHistogram
        .map { if (it > lines.size / 2) 1 else 0 }
        .joinToString(separator = "")
        .toCharArray()
        .binaryToDecimal()

    println(gammaRate) //1519
    println(epsilonRate) //2576
    println(gammaRate * epsilonRate)

    //Part 2
    val diagnosticReportLines = lines
        .map { it.toCharArray() }

    val oxygenGeneratorRating = filterOxygenGeneratorRating(diagnosticReportLines, 0)[0].binaryToDecimal()
    println(oxygenGeneratorRating) //3597
    val co2ScrubberRating = filterCO2ScrubberRating(diagnosticReportLines, 0)[0].binaryToDecimal()
    println(co2ScrubberRating) //1389
    println(oxygenGeneratorRating * co2ScrubberRating)
}

fun filterOxygenGeneratorRating(reportData: List<CharArray>, reportIndex: Int): List<CharArray> =
    filterDiagnosticReport(
        reportData,
        reportIndex
    ) { filterSize, significantBit, reportSize -> (filterSize + if (reportSize % 2 == 0 && significantBit != null && significantBit == 1) 1 else 0) > reportSize / 2 }

fun filterCO2ScrubberRating(reportData: List<CharArray>, reportIndex: Int): List<CharArray> =
    filterDiagnosticReport(
        reportData,
        reportIndex
    ) { filterSize, significantBit, reportSize -> (filterSize - if (reportSize % 2 == 0 && significantBit != null && significantBit == 0) 1 else 0) < (reportSize + 1) / 2 }

fun filterDiagnosticReport(
    reportData: List<CharArray>,
    reportIndex: Int,
    evaluationPredicate: (Int, Int?, Int) -> Boolean
): List<CharArray> {
    if (reportIndex == reportData[0].size || reportData.size == 1) {
        return reportData
    }
    val filteredReportData = reportData
        .partition { it[reportIndex] == '1' }
        .toList()
        .first {
            evaluationPredicate(
                it.size,
                if (it.isNotEmpty()) it[0][reportIndex].digitToInt() else null,
                reportData.size
            )
        }
    return filterDiagnosticReport(filteredReportData, reportIndex + 1, evaluationPredicate)
}

fun CharArray.binaryToDecimal(): Int {
    var value = 0
    for (char in this) {
        value = value shl 1
        value += char - '0'
    }
    return value
}

Compiled from "solution.kt"
public final class day03.SolutionKt {
  public static final void main();
    Code:
       0: new           #8                  // class java/io/File
       3: dup
       4: ldc           #10                 // String src/main/kotlin/day03/input.txt
       6: invokespecial #14                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #20                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      15: astore_0
      16: iconst_0
      17: istore_2
      18: bipush        12
      20: newarray       int
      22: astore_3
      23: iload_2
      24: bipush        12
      26: if_icmpge     43
      29: iload_2
      30: istore        4
      32: aload_3
      33: iload         4
      35: iconst_0
      36: iastore
      37: iinc          2, 1
      40: goto          23
      43: aload_3
      44: astore_1
      45: aload_0
      46: checkcast     #22                 // class java/lang/Iterable
      49: astore_3
      50: nop
      51: iconst_0
      52: istore        4
      54: aload_3
      55: astore        5
      57: new           #24                 // class java/util/ArrayList
      60: dup
      61: aload_3
      62: bipush        10
      64: invokestatic  #30                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      67: invokespecial #33                 // Method java/util/ArrayList."<init>":(I)V
      70: checkcast     #35                 // class java/util/Collection
      73: astore        6
      75: iconst_0
      76: istore        7
      78: aload         5
      80: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      85: astore        8
      87: aload         8
      89: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      94: ifeq          144
      97: aload         8
      99: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     104: astore        9
     106: aload         6
     108: aload         9
     110: checkcast     #51                 // class java/lang/String
     113: astore        10
     115: astore        15
     117: iconst_0
     118: istore        11
     120: aload         10
     122: invokevirtual #55                 // Method java/lang/String.toCharArray:()[C
     125: dup
     126: ldc           #57                 // String toCharArray(...)
     128: invokestatic  #63                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     131: nop
     132: aload         15
     134: swap
     135: invokeinterface #67,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     140: pop
     141: goto          87
     144: aload         6
     146: checkcast     #69                 // class java/util/List
     149: nop
     150: checkcast     #22                 // class java/lang/Iterable
     153: astore_3
     154: nop
     155: iconst_0
     156: istore        4
     158: aload_1
     159: astore        5
     161: aload_3
     162: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     167: astore        6
     169: aload         6
     171: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     176: ifeq          253
     179: aload         6
     181: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     186: astore        7
     188: aload         5
     190: aload         7
     192: checkcast     #71                 // class "[C"
     195: astore        8
     197: astore        9
     199: iconst_0
     200: istore        10
     202: iconst_0
     203: istore        11
     205: aload         9
     207: arraylength
     208: istore        12
     210: iload         11
     212: iload         12
     214: if_icmpge     246
     217: iload         11
     219: istore        13
     221: aload         9
     223: iload         13
     225: aload         9
     227: iload         13
     229: iaload
     230: aload         8
     232: iload         11
     234: caload
     235: invokestatic  #77                 // Method kotlin/text/CharsKt.digitToInt:(C)I
     238: iadd
     239: iastore
     240: iinc          11, 1
     243: goto          210
     246: aload         9
     248: astore        5
     250: goto          169
     253: aload         5
     255: astore_2
     256: aload_2
     257: astore        4
     259: nop
     260: iconst_0
     261: istore        5
     263: aload         4
     265: astore        6
     267: new           #24                 // class java/util/ArrayList
     270: dup
     271: aload         4
     273: arraylength
     274: invokespecial #33                 // Method java/util/ArrayList."<init>":(I)V
     277: checkcast     #35                 // class java/util/Collection
     280: astore        7
     282: iconst_0
     283: istore        8
     285: iconst_0
     286: istore        9
     288: aload         6
     290: arraylength
     291: istore        10
     293: iload         9
     295: iload         10
     297: if_icmpge     354
     300: aload         6
     302: iload         9
     304: iaload
     305: istore        11
     307: aload         7
     309: iload         11
     311: istore        12
     313: astore        15
     315: iconst_0
     316: istore        13
     318: iload         12
     320: aload_0
     321: invokeinterface #81,  1           // InterfaceMethod java/util/List.size:()I
     326: iconst_2
     327: idiv
     328: if_icmple     335
     331: iconst_0
     332: goto          336
     335: iconst_1
     336: invokestatic  #87                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     339: aload         15
     341: swap
     342: invokeinterface #67,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     347: pop
     348: iinc          9, 1
     351: goto          293
     354: aload         7
     356: checkcast     #69                 // class java/util/List
     359: nop
     360: checkcast     #22                 // class java/lang/Iterable
     363: ldc           #89                 // String
     365: checkcast     #91                 // class java/lang/CharSequence
     368: aconst_null
     369: aconst_null
     370: iconst_0
     371: aconst_null
     372: aconst_null
     373: bipush        62
     375: aconst_null
     376: invokestatic  #95                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     379: invokevirtual #55                 // Method java/lang/String.toCharArray:()[C
     382: dup
     383: ldc           #57                 // String toCharArray(...)
     385: invokestatic  #63                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     388: invokestatic  #99                 // Method binaryToDecimal:([C)I
     391: istore_3
     392: aload_2
     393: astore        5
     395: nop
     396: iconst_0
     397: istore        6
     399: aload         5
     401: astore        7
     403: new           #24                 // class java/util/ArrayList
     406: dup
     407: aload         5
     409: arraylength
     410: invokespecial #33                 // Method java/util/ArrayList."<init>":(I)V
     413: checkcast     #35                 // class java/util/Collection
     416: astore        8
     418: iconst_0
     419: istore        9
     421: iconst_0
     422: istore        10
     424: aload         7
     426: arraylength
     427: istore        11
     429: iload         10
     431: iload         11
     433: if_icmpge     490
     436: aload         7
     438: iload         10
     440: iaload
     441: istore        12
     443: aload         8
     445: iload         12
     447: istore        13
     449: astore        15
     451: iconst_0
     452: istore        14
     454: iload         13
     456: aload_0
     457: invokeinterface #81,  1           // InterfaceMethod java/util/List.size:()I
     462: iconst_2
     463: idiv
     464: if_icmple     471
     467: iconst_1
     468: goto          472
     471: iconst_0
     472: invokestatic  #87                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     475: aload         15
     477: swap
     478: invokeinterface #67,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     483: pop
     484: iinc          10, 1
     487: goto          429
     490: aload         8
     492: checkcast     #69                 // class java/util/List
     495: nop
     496: checkcast     #22                 // class java/lang/Iterable
     499: ldc           #89                 // String
     501: checkcast     #91                 // class java/lang/CharSequence
     504: aconst_null
     505: aconst_null
     506: iconst_0
     507: aconst_null
     508: aconst_null
     509: bipush        62
     511: aconst_null
     512: invokestatic  #95                 // Method kotlin/collections/CollectionsKt.joinToString$default:(Ljava/lang/Iterable;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;ILjava/lang/CharSequence;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/String;
     515: invokevirtual #55                 // Method java/lang/String.toCharArray:()[C
     518: dup
     519: ldc           #57                 // String toCharArray(...)
     521: invokestatic  #63                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     524: invokestatic  #99                 // Method binaryToDecimal:([C)I
     527: istore        4
     529: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     532: iload_3
     533: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     536: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     539: iload         4
     541: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     544: iload_3
     545: iload         4
     547: imul
     548: istore        5
     550: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     553: iload         5
     555: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     558: aload_0
     559: checkcast     #22                 // class java/lang/Iterable
     562: astore        6
     564: nop
     565: iconst_0
     566: istore        7
     568: aload         6
     570: astore        8
     572: new           #24                 // class java/util/ArrayList
     575: dup
     576: aload         6
     578: bipush        10
     580: invokestatic  #30                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     583: invokespecial #33                 // Method java/util/ArrayList."<init>":(I)V
     586: checkcast     #35                 // class java/util/Collection
     589: astore        9
     591: iconst_0
     592: istore        10
     594: aload         8
     596: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     601: astore        11
     603: aload         11
     605: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     610: ifeq          660
     613: aload         11
     615: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     620: astore        12
     622: aload         9
     624: aload         12
     626: checkcast     #51                 // class java/lang/String
     629: astore        13
     631: astore        15
     633: iconst_0
     634: istore        14
     636: aload         13
     638: invokevirtual #55                 // Method java/lang/String.toCharArray:()[C
     641: dup
     642: ldc           #57                 // String toCharArray(...)
     644: invokestatic  #63                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     647: nop
     648: aload         15
     650: swap
     651: invokeinterface #67,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     656: pop
     657: goto          603
     660: aload         9
     662: checkcast     #69                 // class java/util/List
     665: nop
     666: astore        5
     668: aload         5
     670: iconst_0
     671: invokestatic  #114                // Method filterOxygenGeneratorRating:(Ljava/util/List;I)Ljava/util/List;
     674: iconst_0
     675: invokeinterface #118,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     680: checkcast     #71                 // class "[C"
     683: invokestatic  #99                 // Method binaryToDecimal:([C)I
     686: istore        6
     688: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     691: iload         6
     693: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     696: aload         5
     698: iconst_0
     699: invokestatic  #121                // Method filterCO2ScrubberRating:(Ljava/util/List;I)Ljava/util/List;
     702: iconst_0
     703: invokeinterface #118,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     708: checkcast     #71                 // class "[C"
     711: invokestatic  #99                 // Method binaryToDecimal:([C)I
     714: istore        7
     716: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     719: iload         7
     721: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     724: iload         6
     726: iload         7
     728: imul
     729: istore        8
     731: getstatic     #105                // Field java/lang/System.out:Ljava/io/PrintStream;
     734: iload         8
     736: invokevirtual #110                // Method java/io/PrintStream.println:(I)V
     739: return

  public static final java.util.List<char[]> filterOxygenGeneratorRating(java.util.List<char[]>, int);
    Code:
       0: aload_0
       1: ldc           #160                // String reportData
       3: invokestatic  #163                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iload_1
       8: invokedynamic #183,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function3;
      13: invokestatic  #187                // Method filterDiagnosticReport:(Ljava/util/List;ILkotlin/jvm/functions/Function3;)Ljava/util/List;
      16: areturn

  public static final java.util.List<char[]> filterCO2ScrubberRating(java.util.List<char[]>, int);
    Code:
       0: aload_0
       1: ldc           #160                // String reportData
       3: invokestatic  #163                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: iload_1
       8: invokedynamic #193,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function3;
      13: invokestatic  #187                // Method filterDiagnosticReport:(Ljava/util/List;ILkotlin/jvm/functions/Function3;)Ljava/util/List;
      16: areturn

  public static final java.util.List<char[]> filterDiagnosticReport(java.util.List<char[]>, int, kotlin.jvm.functions.Function3<? super java.lang.Integer, ? super java.lang.Integer, ? super java.lang.Integer, java.lang.Boolean>);
    Code:
       0: aload_0
       1: ldc           #160                // String reportData
       3: invokestatic  #163                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #196                // String evaluationPredicate
       9: invokestatic  #163                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iload_1
      13: aload_0
      14: iconst_0
      15: invokeinterface #118,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      20: checkcast     #71                 // class "[C"
      23: arraylength
      24: if_icmpeq     37
      27: aload_0
      28: invokeinterface #81,  1           // InterfaceMethod java/util/List.size:()I
      33: iconst_1
      34: if_icmpne     39
      37: aload_0
      38: areturn
      39: aload_0
      40: checkcast     #22                 // class java/lang/Iterable
      43: astore        4
      45: nop
      46: iconst_0
      47: istore        5
      49: new           #24                 // class java/util/ArrayList
      52: dup
      53: invokespecial #198                // Method java/util/ArrayList."<init>":()V
      56: astore        6
      58: new           #24                 // class java/util/ArrayList
      61: dup
      62: invokespecial #198                // Method java/util/ArrayList."<init>":()V
      65: astore        7
      67: aload         4
      69: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      74: astore        8
      76: aload         8
      78: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      83: ifeq          143
      86: aload         8
      88: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      93: astore        9
      95: aload         9
      97: checkcast     #71                 // class "[C"
     100: astore        10
     102: iconst_0
     103: istore        11
     105: aload         10
     107: iload_1
     108: caload
     109: bipush        49
     111: if_icmpne     118
     114: iconst_1
     115: goto          119
     118: iconst_0
     119: ifeq          132
     122: aload         6
     124: aload         9
     126: invokevirtual #199                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     129: goto          139
     132: aload         7
     134: aload         9
     136: invokevirtual #199                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     139: pop
     140: goto          76
     143: new           #201                // class kotlin/Pair
     146: dup
     147: aload         6
     149: aload         7
     151: invokespecial #204                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     154: invokestatic  #210                // Method kotlin/TuplesKt.toList:(Lkotlin/Pair;)Ljava/util/List;
     157: checkcast     #22                 // class java/lang/Iterable
     160: astore        4
     162: nop
     163: iconst_0
     164: istore        5
     166: aload         4
     168: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     173: astore        6
     175: aload         6
     177: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     182: ifeq          288
     185: aload         6
     187: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     192: astore        7
     194: aload         7
     196: checkcast     #69                 // class java/util/List
     199: astore        8
     201: iconst_0
     202: istore        9
     204: aload_2
     205: aload         8
     207: invokeinterface #81,  1           // InterfaceMethod java/util/List.size:()I
     212: invokestatic  #87                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     215: aload         8
     217: checkcast     #35                 // class java/util/Collection
     220: invokeinterface #213,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
     225: ifne          232
     228: iconst_1
     229: goto          233
     232: iconst_0
     233: ifeq          258
     236: aload         8
     238: iconst_0
     239: invokeinterface #118,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     244: checkcast     #71                 // class "[C"
     247: iload_1
     248: caload
     249: invokestatic  #77                 // Method kotlin/text/CharsKt.digitToInt:(C)I
     252: invokestatic  #87                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     255: goto          259
     258: aconst_null
     259: aload_0
     260: invokeinterface #81,  1           // InterfaceMethod java/util/List.size:()I
     265: invokestatic  #87                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     268: invokeinterface #217,  4          // InterfaceMethod kotlin/jvm/functions/Function3.invoke:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     273: checkcast     #219                // class java/lang/Boolean
     276: invokevirtual #222                // Method java/lang/Boolean.booleanValue:()Z
     279: nop
     280: ifeq          175
     283: aload         7
     285: goto          298
     288: new           #224                // class java/util/NoSuchElementException
     291: dup
     292: ldc           #226                // String Collection contains no element matching the predicate.
     294: invokespecial #227                // Method java/util/NoSuchElementException."<init>":(Ljava/lang/String;)V
     297: athrow
     298: checkcast     #69                 // class java/util/List
     301: astore_3
     302: aload_3
     303: iload_1
     304: iconst_1
     305: iadd
     306: aload_2
     307: invokestatic  #187                // Method filterDiagnosticReport:(Ljava/util/List;ILkotlin/jvm/functions/Function3;)Ljava/util/List;
     310: areturn

  public static final int binaryToDecimal(char[]);
    Code:
       0: aload_0
       1: ldc           #240                // String <this>
       3: invokestatic  #163                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: iconst_0
       7: istore_1
       8: iconst_0
       9: istore_2
      10: aload_0
      11: arraylength
      12: istore_3
      13: iload_2
      14: iload_3
      15: if_icmpge     41
      18: aload_0
      19: iload_2
      20: caload
      21: istore        4
      23: iload_1
      24: iconst_1
      25: ishl
      26: istore_1
      27: iload_1
      28: iload         4
      30: bipush        48
      32: isub
      33: iadd
      34: istore_1
      35: iinc          2, 1
      38: goto          13
      41: iload_1
      42: ireturn

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

  private static final boolean filterOxygenGeneratorRating$lambda$5(int, java.lang.Integer, int);
    Code:
       0: iload_0
       1: iload_2
       2: iconst_2
       3: irem
       4: ifne          25
       7: aload_1
       8: ifnull        25
      11: aload_1
      12: iconst_1
      13: istore_3
      14: invokevirtual #252                // Method java/lang/Integer.intValue:()I
      17: iload_3
      18: if_icmpne     25
      21: iconst_1
      22: goto          26
      25: iconst_0
      26: iadd
      27: iload_2
      28: iconst_2
      29: idiv
      30: if_icmple     37
      33: iconst_1
      34: goto          38
      37: iconst_0
      38: ireturn

  private static final boolean filterCO2ScrubberRating$lambda$6(int, java.lang.Integer, int);
    Code:
       0: iload_0
       1: iload_2
       2: iconst_2
       3: irem
       4: ifne          22
       7: aload_1
       8: ifnull        22
      11: aload_1
      12: invokevirtual #252                // Method java/lang/Integer.intValue:()I
      15: ifne          22
      18: iconst_1
      19: goto          23
      22: iconst_0
      23: isub
      24: iload_2
      25: iconst_1
      26: iadd
      27: iconst_2
      28: idiv
      29: if_icmpge     36
      32: iconst_1
      33: goto          37
      36: iconst_0
      37: ireturn
}


package day02

import java.io.File

fun main() {
    val lines = File("src/main/kotlin/day02/input.txt").readLines()

    val submarineV1 = lines
        .fold(SubmarineV1()) { submarine, commandString ->
            submarine.execute(commandString.toCommand())
        }
    println(submarineV1.x * submarineV1.y)

    val submarineV2 = lines
        .fold(SubmarineV2()) { submarine, commandString ->
            submarine.execute(commandString.toCommand())
        }
    println(submarineV2.x * submarineV2.y)
}

sealed class Command
class Forward(val amount: Int): Command()
class Down(val amount: Int): Command()
class Up(val amount: Int): Command()

fun String.toCommand(): Command {
    val moveType = this.substringBefore(" ")
    val amount = this.substringAfter(" ").toInt()
    return when (moveType) {
        "forward" -> Forward(amount)
        "down" -> Down(amount)
        "up" -> Up(amount)
        else -> Forward(0)
    }
}

class SubmarineV1(var x: Int = 0, var y: Int = 0) {
    fun execute(command: Command): SubmarineV1 = when (command) {
        is Forward -> apply { x += command.amount }
        is Down -> apply { y += command.amount }
        is Up -> apply { y -= command.amount }
    }
}

class SubmarineV2(var x: Int = 0, var y: Int = 0, var aim: Int = 0) {
    fun execute(command: Command): SubmarineV2 = when (command) {
        is Forward -> apply { x += command.amount; y += aim * command.amount }
        is Down -> apply { aim += command.amount }
        is Up -> apply { aim -= command.amount }
    }
}

Compiled from "solution.kt"
public final class day02.SolutionKt {
  public static final void main();
    Code:
       0: new           #8                  // class java/io/File
       3: dup
       4: ldc           #10                 // String src/main/kotlin/day02/input.txt
       6: invokespecial #14                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #20                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      15: astore_0
      16: aload_0
      17: checkcast     #22                 // class java/lang/Iterable
      20: astore_2
      21: new           #24                 // class day02/SubmarineV1
      24: dup
      25: iconst_0
      26: iconst_0
      27: iconst_3
      28: aconst_null
      29: invokespecial #27                 // Method day02/SubmarineV1."<init>":(IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
      32: astore_3
      33: iconst_0
      34: istore        4
      36: aload_3
      37: astore        5
      39: aload_2
      40: invokeinterface #31,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      45: astore        6
      47: aload         6
      49: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      54: ifeq          95
      57: aload         6
      59: invokeinterface #41,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      64: astore        7
      66: aload         5
      68: aload         7
      70: checkcast     #43                 // class java/lang/String
      73: astore        8
      75: astore        9
      77: iconst_0
      78: istore        10
      80: aload         9
      82: aload         8
      84: invokestatic  #47                 // Method toCommand:(Ljava/lang/String;)Lday02/Command;
      87: invokevirtual #51                 // Method day02/SubmarineV1.execute:(Lday02/Command;)Lday02/SubmarineV1;
      90: astore        5
      92: goto          47
      95: aload         5
      97: astore_1
      98: aload_1
      99: invokevirtual #55                 // Method day02/SubmarineV1.getX:()I
     102: aload_1
     103: invokevirtual #58                 // Method day02/SubmarineV1.getY:()I
     106: imul
     107: istore_2
     108: getstatic     #64                 // Field java/lang/System.out:Ljava/io/PrintStream;
     111: iload_2
     112: invokevirtual #70                 // Method java/io/PrintStream.println:(I)V
     115: aload_0
     116: checkcast     #22                 // class java/lang/Iterable
     119: astore_3
     120: new           #72                 // class day02/SubmarineV2
     123: dup
     124: iconst_0
     125: iconst_0
     126: iconst_0
     127: bipush        7
     129: aconst_null
     130: invokespecial #75                 // Method day02/SubmarineV2."<init>":(IIIILkotlin/jvm/internal/DefaultConstructorMarker;)V
     133: astore        4
     135: iconst_0
     136: istore        5
     138: aload         4
     140: astore        6
     142: aload_3
     143: invokeinterface #31,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     148: astore        7
     150: aload         7
     152: invokeinterface #37,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     157: ifeq          198
     160: aload         7
     162: invokeinterface #41,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     167: astore        8
     169: aload         6
     171: aload         8
     173: checkcast     #43                 // class java/lang/String
     176: astore        9
     178: astore        10
     180: iconst_0
     181: istore        11
     183: aload         10
     185: aload         9
     187: invokestatic  #47                 // Method toCommand:(Ljava/lang/String;)Lday02/Command;
     190: invokevirtual #78                 // Method day02/SubmarineV2.execute:(Lday02/Command;)Lday02/SubmarineV2;
     193: astore        6
     195: goto          150
     198: aload         6
     200: astore_2
     201: aload_2
     202: invokevirtual #79                 // Method day02/SubmarineV2.getX:()I
     205: aload_2
     206: invokevirtual #80                 // Method day02/SubmarineV2.getY:()I
     209: imul
     210: istore_3
     211: getstatic     #64                 // Field java/lang/System.out:Ljava/io/PrintStream;
     214: iload_3
     215: invokevirtual #70                 // Method java/io/PrintStream.println:(I)V
     218: return

  public static final day02.Command toCommand(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #104                // String <this>
       3: invokestatic  #110                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: ldc           #112                // String
       9: aconst_null
      10: iconst_2
      11: aconst_null
      12: invokestatic  #118                // Method kotlin/text/StringsKt.substringBefore$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      15: astore_1
      16: aload_0
      17: ldc           #112                // String
      19: aconst_null
      20: iconst_2
      21: aconst_null
      22: invokestatic  #121                // Method kotlin/text/StringsKt.substringAfter$default:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
      25: invokestatic  #127                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      28: istore_2
      29: aload_1
      30: astore_3
      31: aload_3
      32: invokevirtual #130                // Method java/lang/String.hashCode:()I
      35: lookupswitch  { // 3
            -677145915: 68
                  3739: 80
               3089570: 92
               default: 146
          }
      68: aload_3
      69: ldc           #132                // String forward
      71: invokevirtual #136                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      74: ifne          104
      77: goto          146
      80: aload_3
      81: ldc           #138                // String up
      83: invokevirtual #136                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      86: ifne          132
      89: goto          146
      92: aload_3
      93: ldc           #140                // String down
      95: invokevirtual #136                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      98: ifne          118
     101: goto          146
     104: new           #142                // class day02/Forward
     107: dup
     108: iload_2
     109: invokespecial #144                // Method day02/Forward."<init>":(I)V
     112: checkcast     #146                // class day02/Command
     115: goto          157
     118: new           #148                // class day02/Down
     121: dup
     122: iload_2
     123: invokespecial #149                // Method day02/Down."<init>":(I)V
     126: checkcast     #146                // class day02/Command
     129: goto          157
     132: new           #151                // class day02/Up
     135: dup
     136: iload_2
     137: invokespecial #152                // Method day02/Up."<init>":(I)V
     140: checkcast     #146                // class day02/Command
     143: goto          157
     146: new           #142                // class day02/Forward
     149: dup
     150: iconst_0
     151: invokespecial #144                // Method day02/Forward."<init>":(I)V
     154: checkcast     #146                // class day02/Command
     157: areturn

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


package day05

import java.io.File
import kotlin.math.abs

fun main() {
    val segmentPattern = Regex("""(\d+),(\d+) -> (\d+),(\d+)""")
    val inputLines = File("src/main/kotlin/day05/input.txt").readLines()
    val segments = inputLines
        .mapNotNull { segmentPattern.matchEntire(it) }
        .map {
            Segment(
                Point(it.groupValues[1].toInt(), it.groupValues[2].toInt()),
                Point(it.groupValues[3].toInt(), it.groupValues[4].toInt())
            )
        }
    val dangerousVentCount = segments.asSequence()
        .filter { it.isLateral() }
        .dangerousVentCount()
    println(dangerousVentCount)

    val dangerousVentCount2 = segments.asSequence()
        .dangerousVentCount()
    println(dangerousVentCount2)
}

fun Sequence<Segment>.dangerousVentCount() = this
    .map { it.getSegmentPoints() }
    .flatten()
    .groupBy { it }
    .count { it.value.size > 1 }

data class Segment(val p1: Point, val p2: Point) {

    fun isLateral(): Boolean = p1.x == p2.x || p1.y == p2.y

    fun getSegmentPoints(): List<Point> {
        val points = mutableListOf<Point>()
        var lastPoint: Point = p1
        for (i in 0..getLength()) {
            points.add(lastPoint)
            lastPoint += getDirectionVector()
        }
        return points
    }

    private fun getDirectionVector(): Vector {
        val dx = p2.x - p1.x
        val dy = p2.y - p1.y
        return Vector(dx / getLength(), dy / getLength())
    }

    private fun getLength(): Int = maxOf(abs(p2.x - p1.x), abs(p2.y - p1.y))
}

data class Point(val x: Int, val y:Int) {
    operator fun plus(vector: Vector): Point = Point(x + vector.dx, y + vector.dy)
}

data class Vector(val dx: Int, val dy: Int)

Compiled from "solution.kt"
public final class day05.SolutionKt {
  public static final void main();
    Code:
       0: new           #8                  // class kotlin/text/Regex
       3: dup
       4: ldc           #10                 // String (\\d+),(\\d+) -> (\\d+),(\\d+)
       6: invokespecial #14                 // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
       9: astore_0
      10: new           #16                 // class java/io/File
      13: dup
      14: ldc           #18                 // String src/main/kotlin/day05/input.txt
      16: invokespecial #19                 // Method java/io/File."<init>":(Ljava/lang/String;)V
      19: aconst_null
      20: iconst_1
      21: aconst_null
      22: invokestatic  #25                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      25: astore_1
      26: aload_1
      27: checkcast     #27                 // class java/lang/Iterable
      30: astore_3
      31: nop
      32: iconst_0
      33: istore        4
      35: aload_3
      36: astore        5
      38: new           #29                 // class java/util/ArrayList
      41: dup
      42: invokespecial #31                 // Method java/util/ArrayList."<init>":()V
      45: checkcast     #33                 // class java/util/Collection
      48: astore        6
      50: iconst_0
      51: istore        7
      53: aload         5
      55: astore        8
      57: iconst_0
      58: istore        9
      60: aload         8
      62: invokeinterface #37,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      67: astore        10
      69: aload         10
      71: invokeinterface #43,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      76: ifeq          141
      79: aload         10
      81: invokeinterface #47,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      86: astore        11
      88: aload         11
      90: astore        12
      92: iconst_0
      93: istore        13
      95: aload         12
      97: checkcast     #49                 // class java/lang/String
     100: astore        14
     102: iconst_0
     103: istore        15
     105: aload_0
     106: aload         14
     108: checkcast     #51                 // class java/lang/CharSequence
     111: invokevirtual #55                 // Method kotlin/text/Regex.matchEntire:(Ljava/lang/CharSequence;)Lkotlin/text/MatchResult;
     114: dup
     115: ifnull        136
     118: astore        16
     120: iconst_0
     121: istore        17
     123: aload         6
     125: aload         16
     127: invokeinterface #59,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     132: pop
     133: goto          137
     136: pop
     137: nop
     138: goto          69
     141: nop
     142: aload         6
     144: checkcast     #61                 // class java/util/List
     147: nop
     148: checkcast     #27                 // class java/lang/Iterable
     151: astore_3
     152: nop
     153: iconst_0
     154: istore        4
     156: aload_3
     157: astore        5
     159: new           #29                 // class java/util/ArrayList
     162: dup
     163: aload_3
     164: bipush        10
     166: invokestatic  #67                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     169: invokespecial #70                 // Method java/util/ArrayList."<init>":(I)V
     172: checkcast     #33                 // class java/util/Collection
     175: astore        6
     177: iconst_0
     178: istore        7
     180: aload         5
     182: invokeinterface #37,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     187: astore        8
     189: aload         8
     191: invokeinterface #43,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     196: ifeq          332
     199: aload         8
     201: invokeinterface #47,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     206: astore        9
     208: aload         6
     210: aload         9
     212: checkcast     #72                 // class kotlin/text/MatchResult
     215: astore        10
     217: astore        18
     219: iconst_0
     220: istore        11
     222: new           #74                 // class day05/Segment
     225: dup
     226: new           #76                 // class day05/Point
     229: dup
     230: aload         10
     232: invokeinterface #80,  1           // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     237: iconst_1
     238: invokeinterface #84,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     243: checkcast     #49                 // class java/lang/String
     246: invokestatic  #90                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     249: aload         10
     251: invokeinterface #80,  1           // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     256: iconst_2
     257: invokeinterface #84,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     262: checkcast     #49                 // class java/lang/String
     265: invokestatic  #90                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     268: invokespecial #93                 // Method day05/Point."<init>":(II)V
     271: new           #76                 // class day05/Point
     274: dup
     275: aload         10
     277: invokeinterface #80,  1           // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     282: iconst_3
     283: invokeinterface #84,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     288: checkcast     #49                 // class java/lang/String
     291: invokestatic  #90                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     294: aload         10
     296: invokeinterface #80,  1           // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     301: iconst_4
     302: invokeinterface #84,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     307: checkcast     #49                 // class java/lang/String
     310: invokestatic  #90                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     313: invokespecial #93                 // Method day05/Point."<init>":(II)V
     316: invokespecial #96                 // Method day05/Segment."<init>":(Lday05/Point;Lday05/Point;)V
     319: nop
     320: aload         18
     322: swap
     323: invokeinterface #59,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     328: pop
     329: goto          189
     332: aload         6
     334: checkcast     #61                 // class java/util/List
     337: nop
     338: astore_2
     339: aload_2
     340: checkcast     #27                 // class java/lang/Iterable
     343: invokestatic  #100                // Method kotlin/collections/CollectionsKt.asSequence:(Ljava/lang/Iterable;)Lkotlin/sequences/Sequence;
     346: invokedynamic #120,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
     351: invokestatic  #126                // Method kotlin/sequences/SequencesKt.filter:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
     354: invokestatic  #130                // Method dangerousVentCount:(Lkotlin/sequences/Sequence;)I
     357: istore_3
     358: getstatic     #136                // Field java/lang/System.out:Ljava/io/PrintStream;
     361: iload_3
     362: invokevirtual #141                // Method java/io/PrintStream.println:(I)V
     365: aload_2
     366: checkcast     #27                 // class java/lang/Iterable
     369: invokestatic  #100                // Method kotlin/collections/CollectionsKt.asSequence:(Ljava/lang/Iterable;)Lkotlin/sequences/Sequence;
     372: invokestatic  #130                // Method dangerousVentCount:(Lkotlin/sequences/Sequence;)I
     375: istore        4
     377: getstatic     #136                // Field java/lang/System.out:Ljava/io/PrintStream;
     380: iload         4
     382: invokevirtual #141                // Method java/io/PrintStream.println:(I)V
     385: return

  public static final int dangerousVentCount(kotlin.sequences.Sequence<day05.Segment>);
    Code:
       0: aload_0
       1: ldc           #177                // String <this>
       3: invokestatic  #183                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #190,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function1;
      12: invokestatic  #193                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      15: invokestatic  #197                // Method kotlin/sequences/SequencesKt.flattenSequenceOfIterable:(Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
      18: astore_1
      19: nop
      20: iconst_0
      21: istore_2
      22: aload_1
      23: astore_3
      24: new           #199                // class java/util/LinkedHashMap
      27: dup
      28: invokespecial #200                // Method java/util/LinkedHashMap."<init>":()V
      31: checkcast     #202                // class java/util/Map
      34: astore        4
      36: iconst_0
      37: istore        5
      39: aload_3
      40: invokeinterface #205,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      45: astore        6
      47: aload         6
      49: invokeinterface #43,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      54: ifeq          156
      57: aload         6
      59: invokeinterface #47,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      64: astore        7
      66: aload         7
      68: checkcast     #76                 // class day05/Point
      71: astore        8
      73: iconst_0
      74: istore        9
      76: aload         8
      78: astore        10
      80: aload         4
      82: astore        11
      84: iconst_0
      85: istore        12
      87: aload         11
      89: aload         10
      91: invokeinterface #207,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      96: astore        13
      98: aload         13
     100: ifnonnull     135
     103: iconst_0
     104: istore        14
     106: new           #29                 // class java/util/ArrayList
     109: dup
     110: invokespecial #31                 // Method java/util/ArrayList."<init>":()V
     113: checkcast     #61                 // class java/util/List
     116: astore        14
     118: aload         11
     120: aload         10
     122: aload         14
     124: invokeinterface #211,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     129: pop
     130: aload         14
     132: goto          137
     135: aload         13
     137: nop
     138: checkcast     #61                 // class java/util/List
     141: astore        8
     143: aload         8
     145: aload         7
     147: invokeinterface #212,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     152: pop
     153: goto          47
     156: aload         4
     158: nop
     159: astore_1
     160: nop
     161: iconst_0
     162: istore_2
     163: aload_1
     164: invokeinterface #215,  1          // InterfaceMethod java/util/Map.isEmpty:()Z
     169: ifeq          176
     172: iconst_0
     173: goto          254
     176: iconst_0
     177: istore_3
     178: aload_1
     179: invokeinterface #219,  1          // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
     184: invokeinterface #222,  1          // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
     189: astore        4
     191: aload         4
     193: invokeinterface #43,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     198: ifeq          253
     201: aload         4
     203: invokeinterface #47,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     208: checkcast     #224                // class java/util/Map$Entry
     211: astore        5
     213: aload         5
     215: astore        6
     217: iconst_0
     218: istore        7
     220: aload         6
     222: invokeinterface #227,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     227: checkcast     #61                 // class java/util/List
     230: invokeinterface #231,  1          // InterfaceMethod java/util/List.size:()I
     235: iconst_1
     236: if_icmple     243
     239: iconst_1
     240: goto          244
     243: iconst_0
     244: ifeq          191
     247: iinc          3, 1
     250: goto          191
     253: iload_3
     254: ireturn

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

  private static final boolean main$lambda$2(day05.Segment);
    Code:
       0: aload_0
       1: ldc_w         #259                // String it
       4: invokestatic  #183                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #262                // Method day05/Segment.isLateral:()Z
      11: ireturn

  private static final java.util.List dangerousVentCount$lambda$3(day05.Segment);
    Code:
       0: aload_0
       1: ldc_w         #259                // String it
       4: invokestatic  #183                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #266                // Method day05/Segment.getSegmentPoints:()Ljava/util/List;
      11: areturn
}


package day18

import java.io.File

fun main() {
    val lines = File("src/main/kotlin/day18/input.txt").readLines()
    val snailFishNumbers = lines.map { parseSnailFish(it) }
    println(snailFishNumbers.reduce { acc, snailFishNumber -> acc.copy() + snailFishNumber.copy() }.magnitude())

    var highestMagnitude = 0

    for (number1 in snailFishNumbers) {
        for (number2 in snailFishNumbers) {
            val magnitude1 = (number1.copy() + number2.copy()).magnitude()
            if (magnitude1 > highestMagnitude) highestMagnitude = magnitude1
            val magnitude2 = (number2.copy() + number1.copy()).magnitude()
            if (magnitude2 > highestMagnitude) highestMagnitude = magnitude2
        }
    }

    println(highestMagnitude)
}

fun parseSnailFish(value: String): SnailFishNumber {
    if (!value.startsWith('[')) return Regular(value.toInt())
    val inside = value.removeSurrounding("[", "]")
    var nestLevel = 0
    val index = inside.indexOfFirst {
        if (it == '[') nestLevel++
        else if (it == ']') nestLevel--
        else if (it == ',' && nestLevel == 0) return@indexOfFirst true
        false
    }
    return Pair(parseSnailFish(inside.substring(0, index)), parseSnailFish(inside.substring(index + 1)))
        .also {
            it.childsParent(it)
        }
}

sealed class SnailFishNumber(var parent: Pair? = null) {

    operator fun plus(other: SnailFishNumber): SnailFishNumber = Pair(this, other).also { it.childsParent(it) }.reduce()

    abstract fun print()

    abstract fun magnitude(): Int

    fun copy(): SnailFishNumber {
        return when(this) {
            is Pair -> Pair(this.left.copy(), this.right.copy()).also { it.childsParent(it) }
            is Regular -> Regular(this.value)
        }
    }

    protected fun reduce(): SnailFishNumber {
        while (true) {
//            this.print()
//            println()
            val exploding = findExploding()
            if (exploding != null) {
                exploding.explode()
                continue
            }
            val splitting = findSplitting()
            if (splitting != null) {
                splitting.split()
                continue
            }
            break
        }
        return this
    }

    private fun findExploding(nestLevel: Int = 0): Pair? {
        if (this is Pair) {
            if (nestLevel == 4) return this
            return this.left.findExploding( nestLevel + 1) ?: this.right.findExploding(nestLevel + 1)
        }
        return null
    }

    private fun findSplitting(): Regular? {
        return when (this) {
            is Regular -> if (this.value >= 10) this else null
            is Pair -> this.left.findSplitting() ?: this.right.findSplitting()
        }
    }
}

class Regular(var value: Int, parent: Pair? = null) : SnailFishNumber(parent) {
    override fun magnitude(): Int = value

    override fun print() {
        print(value)
    }

    fun add(addition: Int) {
        value += addition
    }

    fun split() {
        val newValue = Pair(Regular(value / 2), Regular(value / 2 + value % 2), parent)
            .also {
                it.childsParent(it)
            }
        if (parent != null) {
            if (parent!!.left == this) {
                parent!!.left = newValue
            } else {
                parent!!.right = newValue
            }
        }
    }
}

class Pair(var left: SnailFishNumber, var right: SnailFishNumber, parent: Pair? = null) : SnailFishNumber(parent) {
    override fun magnitude(): Int = 3 * left.magnitude() + 2 * right.magnitude()
    override fun print() {
        print("[");left.print();print(",");right.print();print("]")
    }

    fun explode() {
        findClosestLeftRegular()?.add((left as Regular).value)
        findClosestRightRegular()?.add((right as Regular).value)
        if (parent != null) {
            val newValue = Regular(0, parent)
            if (parent!!.left == this) {
                parent!!.left = newValue
            } else {
                parent!!.right = newValue
            }
        }
    }

    private fun findClosestLeftRegular(): Regular? {
        return if (parent != null) {
            if (parent!!.left == this) {
                parent!!.findClosestLeftRegular()
            } else {
                when (parent!!.left) {
                    is Regular -> parent!!.left as Regular
                    is Pair -> {
                        return (parent!!.left as Pair).findRightMostChild()
                    }
                }
            }
        } else {
            null
        }
    }

    private fun findRightMostChild(): Regular = when (this.right) {
        is Regular -> this.right as Regular
        else -> (this.right as Pair).findRightMostChild()
    }

    private fun findClosestRightRegular(): Regular? {
        return if (parent != null) {
            if (parent!!.right == this) {
                parent!!.findClosestRightRegular()
            } else {
                when (parent!!.right) {
                    is Regular -> parent!!.right as Regular
                    is Pair -> {
                        return (parent!!.right as Pair).findLeftMostChild()
                    }
                }
            }
        } else {
            null
        }
    }

    private fun findLeftMostChild(): Regular = when (this.left) {
        is Regular -> this.left as Regular
        else -> (this.left as Pair).findLeftMostChild()
    }

    fun childsParent(parent: Pair?) {
        left.parent = parent
        right.parent = parent
    }
}

Compiled from "solution.kt"
public final class day18.SolutionKt {
  public static final void main();
    Code:
       0: new           #8                  // class java/io/File
       3: dup
       4: ldc           #10                 // String src/main/kotlin/day18/input.txt
       6: invokespecial #14                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #20                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      15: astore_0
      16: aload_0
      17: checkcast     #22                 // class java/lang/Iterable
      20: astore_2
      21: iconst_0
      22: istore_3
      23: aload_2
      24: astore        4
      26: new           #24                 // class java/util/ArrayList
      29: dup
      30: aload_2
      31: bipush        10
      33: invokestatic  #30                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      36: invokespecial #33                 // Method java/util/ArrayList."<init>":(I)V
      39: checkcast     #35                 // class java/util/Collection
      42: astore        5
      44: iconst_0
      45: istore        6
      47: aload         4
      49: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      54: astore        7
      56: aload         7
      58: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      63: ifeq          106
      66: aload         7
      68: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      73: astore        8
      75: aload         5
      77: aload         8
      79: checkcast     #51                 // class java/lang/String
      82: astore        9
      84: astore        11
      86: iconst_0
      87: istore        10
      89: aload         9
      91: invokestatic  #55                 // Method parseSnailFish:(Ljava/lang/String;)Lday18/SnailFishNumber;
      94: aload         11
      96: swap
      97: invokeinterface #59,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     102: pop
     103: goto          56
     106: aload         5
     108: checkcast     #61                 // class java/util/List
     111: nop
     112: astore_1
     113: aload_1
     114: checkcast     #22                 // class java/lang/Iterable
     117: astore_2
     118: iconst_0
     119: istore_3
     120: aload_2
     121: invokeinterface #39,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     126: astore        4
     128: aload         4
     130: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     135: ifne          148
     138: new           #63                 // class java/lang/UnsupportedOperationException
     141: dup
     142: ldc           #65                 // String Empty collection can\'t be reduced.
     144: invokespecial #66                 // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V
     147: athrow
     148: aload         4
     150: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     155: astore        5
     157: aload         4
     159: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     164: ifeq          207
     167: aload         5
     169: aload         4
     171: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     176: checkcast     #68                 // class day18/SnailFishNumber
     179: astore        6
     181: checkcast     #68                 // class day18/SnailFishNumber
     184: astore        7
     186: iconst_0
     187: istore        8
     189: aload         7
     191: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     194: aload         6
     196: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     199: invokevirtual #76                 // Method day18/SnailFishNumber.plus:(Lday18/SnailFishNumber;)Lday18/SnailFishNumber;
     202: astore        5
     204: goto          157
     207: aload         5
     209: checkcast     #68                 // class day18/SnailFishNumber
     212: invokevirtual #80                 // Method day18/SnailFishNumber.magnitude:()I
     215: istore_2
     216: getstatic     #86                 // Field java/lang/System.out:Ljava/io/PrintStream;
     219: iload_2
     220: invokevirtual #91                 // Method java/io/PrintStream.println:(I)V
     223: iconst_0
     224: istore_2
     225: aload_1
     226: invokeinterface #92,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     231: astore_3
     232: aload_3
     233: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     238: ifeq          339
     241: aload_3
     242: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     247: checkcast     #68                 // class day18/SnailFishNumber
     250: astore        4
     252: aload_1
     253: invokeinterface #92,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     258: astore        5
     260: aload         5
     262: invokeinterface #45,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     267: ifeq          232
     270: aload         5
     272: invokeinterface #49,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     277: checkcast     #68                 // class day18/SnailFishNumber
     280: astore        6
     282: aload         4
     284: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     287: aload         6
     289: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     292: invokevirtual #76                 // Method day18/SnailFishNumber.plus:(Lday18/SnailFishNumber;)Lday18/SnailFishNumber;
     295: invokevirtual #80                 // Method day18/SnailFishNumber.magnitude:()I
     298: istore        7
     300: iload         7
     302: iload_2
     303: if_icmple     309
     306: iload         7
     308: istore_2
     309: aload         6
     311: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     314: aload         4
     316: invokevirtual #72                 // Method day18/SnailFishNumber.copy:()Lday18/SnailFishNumber;
     319: invokevirtual #76                 // Method day18/SnailFishNumber.plus:(Lday18/SnailFishNumber;)Lday18/SnailFishNumber;
     322: invokevirtual #80                 // Method day18/SnailFishNumber.magnitude:()I
     325: istore        8
     327: iload         8
     329: iload_2
     330: if_icmple     260
     333: iload         8
     335: istore_2
     336: goto          260
     339: getstatic     #86                 // Field java/lang/System.out:Ljava/io/PrintStream;
     342: iload_2
     343: invokevirtual #91                 // Method java/io/PrintStream.println:(I)V
     346: return

  public static final day18.SnailFishNumber parseSnailFish(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #125                // String value
       3: invokestatic  #131                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #133                // class java/lang/CharSequence
      10: bipush        91
      12: iconst_0
      13: iconst_2
      14: aconst_null
      15: invokestatic  #139                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
      18: ifne          39
      21: new           #141                // class day18/Regular
      24: dup
      25: aload_0
      26: invokestatic  #147                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      29: aconst_null
      30: iconst_2
      31: aconst_null
      32: invokespecial #150                // Method day18/Regular."<init>":(ILday18/Pair;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      35: checkcast     #68                 // class day18/SnailFishNumber
      38: areturn
      39: aload_0
      40: ldc           #152                // String [
      42: checkcast     #133                // class java/lang/CharSequence
      45: ldc           #154                // String ]
      47: checkcast     #133                // class java/lang/CharSequence
      50: invokestatic  #158                // Method kotlin/text/StringsKt.removeSurrounding:(Ljava/lang/String;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
      53: astore_1
      54: iconst_0
      55: istore_2
      56: aload_1
      57: checkcast     #133                // class java/lang/CharSequence
      60: astore        4
      62: iconst_0
      63: istore        5
      65: iconst_0
      66: istore        6
      68: aload         4
      70: invokeinterface #161,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      75: istore        7
      77: iload         6
      79: iload         7
      81: if_icmpge     156
      84: aload         4
      86: iload         6
      88: invokeinterface #165,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      93: istore        8
      95: iconst_0
      96: istore        9
      98: iload         8
     100: bipush        91
     102: if_icmpne     112
     105: iload_2
     106: iconst_1
     107: iadd
     108: istore_2
     109: goto          141
     112: iload         8
     114: bipush        93
     116: if_icmpne     126
     119: iload_2
     120: iconst_m1
     121: iadd
     122: istore_2
     123: goto          141
     126: iload         8
     128: bipush        44
     130: if_icmpne     141
     133: iload_2
     134: ifne          141
     137: iconst_1
     138: goto          142
     141: iconst_0
     142: ifeq          150
     145: iload         6
     147: goto          157
     150: iinc          6, 1
     153: goto          77
     156: iconst_m1
     157: istore_3
     158: new           #167                // class day18/Pair
     161: dup
     162: aload_1
     163: iconst_0
     164: iload_3
     165: invokevirtual #171                // Method java/lang/String.substring:(II)Ljava/lang/String;
     168: dup
     169: ldc           #173                // String substring(...)
     171: invokestatic  #176                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     174: invokestatic  #55                 // Method parseSnailFish:(Ljava/lang/String;)Lday18/SnailFishNumber;
     177: aload_1
     178: iload_3
     179: iconst_1
     180: iadd
     181: invokevirtual #179                // Method java/lang/String.substring:(I)Ljava/lang/String;
     184: dup
     185: ldc           #173                // String substring(...)
     187: invokestatic  #176                // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     190: invokestatic  #55                 // Method parseSnailFish:(Ljava/lang/String;)Lday18/SnailFishNumber;
     193: aconst_null
     194: iconst_4
     195: aconst_null
     196: invokespecial #182                // Method day18/Pair."<init>":(Lday18/SnailFishNumber;Lday18/SnailFishNumber;Lday18/Pair;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
     199: astore        4
     201: aload         4
     203: astore        5
     205: iconst_0
     206: istore        6
     208: aload         5
     210: aload         5
     212: invokevirtual #186                // Method day18/Pair.childsParent:(Lday18/Pair;)V
     215: nop
     216: aload         4
     218: checkcast     #68                 // class day18/SnailFishNumber
     221: areturn

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