import Direction.D
import Direction.L
import Direction.R
import Direction.U
import java.io.File
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.sign

fun main() {
  val result = File("inputs/day_9.txt").useLines { tailPositions(it, 9) }
  println(result)
}

fun tailPositions(lines: Sequence<String>, tailLength: Int = 1) =
  max(lines.fold(listOf(Position(t = (0..tailLength).map { Point(0, 0) }))) { acc, line ->
    acc + moves(Move.parse(line), acc.last(), tailLength)
  }
    .distinctBy { it.t[tailLength - 1] }
    .count(), 1)

data class Point(val x: Int, val y: Int) {
  operator fun plus(other: Point) = Point(x + other.x, y + other.y)

  fun diff(other: Point) = Point(other.x - x, other.y - y)
  fun follow(diff: Point) = when {
    max(abs(diff.x), abs(diff.y)) <= 1 -> this
    else -> copy(x = x + diff.x.sign, y = y + diff.y.sign)
  }
}

fun moves(move: Move, current: Position, tailLength: Int) =
  (1..move.steps).fold(listOf(current)) { positions, _ ->
    val previousPos = positions.last()
    val h = previousPos.h + next(move.direction)
    val t =
      (0 until tailLength).fold(listOf(previousPos.t[0].follow(previousPos.t[0].diff(h)))) { acc, i ->
        acc + previousPos.t[i + 1].follow(previousPos.t[i + 1].diff(acc.last()))
      }
    positions + Position(h, t)
  }

fun next(direction: Direction) = when (direction) {
  R -> Point(0, 1)
  U -> Point(-1, 0)
  L -> Point(0, -1)
  D -> Point(1, 0)
}

data class Position(val h: Point = Point(0, 0), val t: List<Point>)

data class Move(val direction: Direction, val steps: Int) {
  companion object {
    fun parse(line: String) = Move(toDirection(line), line.split(" ")[1].toInt())

    private fun toDirection(line: String) = when (line.split(" ")[0]) {
      "R" -> R
      "U" -> U
      "L" -> L
      "D" -> D
      else -> throw IllegalArgumentException()
    }
  }
}

enum class Direction {
  R,
  U,
  L,
  D
}

Compiled from "Day9.kt"
public final class Day9Kt {
  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String inputs/day_9.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: iconst_0
      15: istore_3
      16: aload_1
      17: astore        4
      19: sipush        8192
      22: istore        5
      24: aload         4
      26: astore        6
      28: new           #24                 // class java/io/InputStreamReader
      31: dup
      32: new           #26                 // class java/io/FileInputStream
      35: dup
      36: aload         6
      38: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      41: checkcast     #31                 // class java/io/InputStream
      44: aload_2
      45: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      48: checkcast     #36                 // class java/io/Reader
      51: astore        6
      53: aload         6
      55: instanceof    #38                 // class java/io/BufferedReader
      58: ifeq          69
      61: aload         6
      63: checkcast     #38                 // class java/io/BufferedReader
      66: goto          80
      69: new           #38                 // class java/io/BufferedReader
      72: dup
      73: aload         6
      75: iload         5
      77: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      80: checkcast     #43                 // class java/io/Closeable
      83: astore        4
      85: aconst_null
      86: astore        5
      88: nop
      89: aload         4
      91: checkcast     #38                 // class java/io/BufferedReader
      94: astore        6
      96: iconst_0
      97: istore        7
      99: aload         6
     101: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     104: astore        8
     106: iconst_0
     107: istore        9
     109: aload         8
     111: bipush        9
     113: invokestatic  #53                 // Method tailPositions:(Lkotlin/sequences/Sequence;I)I
     116: istore        6
     118: aload         4
     120: aload         5
     122: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     125: iload         6
     127: goto          151
     130: astore        7
     132: aload         7
     134: astore        5
     136: aload         7
     138: athrow
     139: astore        7
     141: aload         4
     143: aload         5
     145: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     148: aload         7
     150: athrow
     151: nop
     152: istore_0
     153: getstatic     #65                 // Field java/lang/System.out:Ljava/io/PrintStream;
     156: iload_0
     157: invokevirtual #71                 // Method java/io/PrintStream.println:(I)V
     160: return
    Exception table:
       from    to  target type
          88   118   130   Class java/lang/Throwable
          88   118   139   any
         130   139   139   any
         139   141   139   any

  public static final int tailPositions(kotlin.sequences.Sequence<java.lang.String>, int);
    Code:
       0: aload_0
       1: ldc           #91                 // String lines
       3: invokestatic  #97                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: astore_2
       8: aconst_null
       9: new           #99                 // class kotlin/ranges/IntRange
      12: dup
      13: iconst_0
      14: iload_1
      15: invokespecial #102                // Method kotlin/ranges/IntRange."<init>":(II)V
      18: checkcast     #104                // class java/lang/Iterable
      21: astore_3
      22: astore        12
      24: iconst_0
      25: istore        4
      27: aload_3
      28: astore        5
      30: new           #106                // class java/util/ArrayList
      33: dup
      34: aload_3
      35: bipush        10
      37: invokestatic  #112                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      40: invokespecial #114                // Method java/util/ArrayList."<init>":(I)V
      43: checkcast     #116                // class java/util/Collection
      46: astore        6
      48: iconst_0
      49: istore        7
      51: aload         5
      53: invokeinterface #120,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      58: astore        8
      60: aload         8
      62: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      67: ifeq          112
      70: aload         8
      72: checkcast     #128                // class kotlin/collections/IntIterator
      75: invokevirtual #132                // Method kotlin/collections/IntIterator.nextInt:()I
      78: istore        9
      80: aload         6
      82: iload         9
      84: istore        10
      86: astore        13
      88: iconst_0
      89: istore        11
      91: new           #134                // class Point
      94: dup
      95: iconst_0
      96: iconst_0
      97: invokespecial #135                // Method Point."<init>":(II)V
     100: aload         13
     102: swap
     103: invokeinterface #139,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     108: pop
     109: goto          60
     112: aload         6
     114: checkcast     #141                // class java/util/List
     117: nop
     118: aload         12
     120: swap
     121: iconst_1
     122: aconst_null
     123: astore        14
     125: istore        15
     127: astore        16
     129: astore        17
     131: new           #143                // class Position
     134: dup
     135: aload         17
     137: aload         16
     139: iload         15
     141: aload         14
     143: invokespecial #146                // Method Position."<init>":(LPoint;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
     146: invokestatic  #150                // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
     149: astore_3
     150: iconst_0
     151: istore        4
     153: aload_3
     154: astore        5
     156: aload_2
     157: invokeinterface #151,  1          // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
     162: astore        6
     164: aload         6
     166: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     171: ifeq          233
     174: aload         6
     176: invokeinterface #155,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     181: astore        7
     183: aload         5
     185: aload         7
     187: checkcast     #157                // class java/lang/String
     190: astore        8
     192: astore        9
     194: iconst_0
     195: istore        10
     197: aload         9
     199: checkcast     #116                // class java/util/Collection
     202: getstatic     #163                // Field Move.Companion:LMove$Companion;
     205: aload         8
     207: invokevirtual #169                // Method Move$Companion.parse:(Ljava/lang/String;)LMove;
     210: aload         9
     212: invokestatic  #173                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
     215: checkcast     #143                // class Position
     218: iload_1
     219: invokestatic  #177                // Method moves:(LMove;LPosition;I)Ljava/util/List;
     222: checkcast     #104                // class java/lang/Iterable
     225: invokestatic  #181                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
     228: astore        5
     230: goto          164
     233: aload         5
     235: checkcast     #104                // class java/lang/Iterable
     238: astore_2
     239: nop
     240: iconst_0
     241: istore_3
     242: new           #183                // class java/util/HashSet
     245: dup
     246: invokespecial #185                // Method java/util/HashSet."<init>":()V
     249: astore        4
     251: new           #106                // class java/util/ArrayList
     254: dup
     255: invokespecial #186                // Method java/util/ArrayList."<init>":()V
     258: astore        5
     260: aload_2
     261: invokeinterface #120,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     266: astore        6
     268: aload         6
     270: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     275: ifeq          336
     278: aload         6
     280: invokeinterface #155,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     285: astore        7
     287: aload         7
     289: checkcast     #143                // class Position
     292: astore        8
     294: iconst_0
     295: istore        9
     297: aload         8
     299: invokevirtual #190                // Method Position.getT:()Ljava/util/List;
     302: iload_1
     303: iconst_1
     304: isub
     305: invokeinterface #194,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     310: checkcast     #134                // class Point
     313: astore        8
     315: aload         4
     317: aload         8
     319: invokevirtual #195                // Method java/util/HashSet.add:(Ljava/lang/Object;)Z
     322: ifeq          268
     325: aload         5
     327: aload         7
     329: invokevirtual #196                // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
     332: pop
     333: goto          268
     336: aload         5
     338: checkcast     #141                // class java/util/List
     341: checkcast     #116                // class java/util/Collection
     344: invokeinterface #199,  1          // InterfaceMethod java/util/Collection.size:()I
     349: istore_2
     350: iconst_1
     351: istore_3
     352: iload_2
     353: iload_3
     354: invokestatic  #205                // Method java/lang/Math.max:(II)I
     357: ireturn

  public static int tailPositions$default(kotlin.sequences.Sequence, int, int, java.lang.Object);
    Code:
       0: iload_2
       1: iconst_2
       2: iand
       3: ifeq          8
       6: iconst_1
       7: istore_1
       8: aload_0
       9: iload_1
      10: invokestatic  #53                 // Method tailPositions:(Lkotlin/sequences/Sequence;I)I
      13: ireturn

  public static final java.util.List<Position> moves(Move, Position, int);
    Code:
       0: aload_0
       1: ldc           #241                // String move
       3: invokestatic  #97                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #243                // String current
       9: invokestatic  #97                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: new           #99                 // class kotlin/ranges/IntRange
      15: dup
      16: iconst_1
      17: aload_0
      18: invokevirtual #246                // Method Move.getSteps:()I
      21: invokespecial #102                // Method kotlin/ranges/IntRange."<init>":(II)V
      24: checkcast     #104                // class java/lang/Iterable
      27: astore_3
      28: aload_1
      29: invokestatic  #150                // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      32: astore        4
      34: iconst_0
      35: istore        5
      37: aload         4
      39: astore        6
      41: aload_3
      42: invokeinterface #120,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      47: astore        7
      49: aload         7
      51: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      56: ifeq          290
      59: aload         7
      61: checkcast     #128                // class kotlin/collections/IntIterator
      64: invokevirtual #132                // Method kotlin/collections/IntIterator.nextInt:()I
      67: istore        8
      69: aload         6
      71: astore        9
      73: iconst_0
      74: istore        10
      76: aload         9
      78: invokestatic  #173                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      81: checkcast     #143                // class Position
      84: astore        11
      86: aload         11
      88: invokevirtual #250                // Method Position.getH:()LPoint;
      91: aload_0
      92: invokevirtual #254                // Method Move.getDirection:()LDirection;
      95: invokestatic  #257                // Method next:(LDirection;)LPoint;
      98: invokevirtual #260                // Method Point.plus:(LPoint;)LPoint;
     101: astore        12
     103: iconst_0
     104: iload_2
     105: invokestatic  #266                // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
     108: checkcast     #104                // class java/lang/Iterable
     111: astore        13
     113: aload         11
     115: invokevirtual #190                // Method Position.getT:()Ljava/util/List;
     118: iconst_0
     119: invokeinterface #194,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     124: checkcast     #134                // class Point
     127: aload         11
     129: invokevirtual #190                // Method Position.getT:()Ljava/util/List;
     132: iconst_0
     133: invokeinterface #194,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     138: checkcast     #134                // class Point
     141: aload         12
     143: invokevirtual #269                // Method Point.diff:(LPoint;)LPoint;
     146: invokevirtual #272                // Method Point.follow:(LPoint;)LPoint;
     149: invokestatic  #150                // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
     152: astore        14
     154: iconst_0
     155: istore        15
     157: aload         14
     159: astore        16
     161: aload         13
     163: invokeinterface #120,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     168: astore        17
     170: aload         17
     172: invokeinterface #126,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     177: ifeq          262
     180: aload         17
     182: checkcast     #128                // class kotlin/collections/IntIterator
     185: invokevirtual #132                // Method kotlin/collections/IntIterator.nextInt:()I
     188: istore        18
     190: aload         16
     192: iload         18
     194: istore        19
     196: astore        20
     198: iconst_0
     199: istore        21
     201: aload         20
     203: checkcast     #116                // class java/util/Collection
     206: aload         11
     208: invokevirtual #190                // Method Position.getT:()Ljava/util/List;
     211: iload         19
     213: iconst_1
     214: iadd
     215: invokeinterface #194,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     220: checkcast     #134                // class Point
     223: aload         11
     225: invokevirtual #190                // Method Position.getT:()Ljava/util/List;
     228: iload         19
     230: iconst_1
     231: iadd
     232: invokeinterface #194,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     237: checkcast     #134                // class Point
     240: aload         20
     242: invokestatic  #173                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
     245: checkcast     #134                // class Point
     248: invokevirtual #269                // Method Point.diff:(LPoint;)LPoint;
     251: invokevirtual #272                // Method Point.follow:(LPoint;)LPoint;
     254: invokestatic  #275                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
     257: astore        16
     259: goto          170
     262: aload         16
     264: astore        22
     266: aload         9
     268: checkcast     #116                // class java/util/Collection
     271: new           #143                // class Position
     274: dup
     275: aload         12
     277: aload         22
     279: invokespecial #278                // Method Position."<init>":(LPoint;Ljava/util/List;)V
     282: invokestatic  #275                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
     285: astore        6
     287: goto          49
     290: aload         6
     292: areturn

  public static final Point next(Direction);
    Code:
       0: aload_0
       1: ldc_w         #289                // String direction
       4: invokestatic  #97                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: getstatic     #295                // Field Day9Kt$WhenMappings.$EnumSwitchMapping$0:[I
      11: swap
      12: invokevirtual #300                // Method Direction.ordinal:()I
      15: iaload
      16: tableswitch   { // 1 to 4
                     1: 48
                     2: 60
                     3: 72
                     4: 84
               default: 96
          }
      48: new           #134                // class Point
      51: dup
      52: iconst_0
      53: iconst_1
      54: invokespecial #135                // Method Point."<init>":(II)V
      57: goto          104
      60: new           #134                // class Point
      63: dup
      64: iconst_m1
      65: iconst_0
      66: invokespecial #135                // Method Point."<init>":(II)V
      69: goto          104
      72: new           #134                // class Point
      75: dup
      76: iconst_0
      77: iconst_m1
      78: invokespecial #135                // Method Point."<init>":(II)V
      81: goto          104
      84: new           #134                // class Point
      87: dup
      88: iconst_1
      89: iconst_0
      90: invokespecial #135                // Method Point."<init>":(II)V
      93: goto          104
      96: new           #302                // class kotlin/NoWhenBranchMatchedException
      99: dup
     100: invokespecial #303                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
     103: athrow
     104: areturn

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

Compiled from "Day9.kt"
public final class Day9Kt$WhenMappings {
  public static final int[] $EnumSwitchMapping$0;

  static {};
    Code:
       0: invokestatic  #14                 // Method Direction.values:()[LDirection;
       3: arraylength
       4: newarray       int
       6: astore_0
       7: nop
       8: aload_0
       9: getstatic     #18                 // Field Direction.R:LDirection;
      12: invokevirtual #22                 // Method Direction.ordinal:()I
      15: iconst_1
      16: iastore
      17: goto          21
      20: astore_1
      21: nop
      22: aload_0
      23: getstatic     #25                 // Field Direction.U:LDirection;
      26: invokevirtual #22                 // Method Direction.ordinal:()I
      29: iconst_2
      30: iastore
      31: goto          35
      34: astore_1
      35: nop
      36: aload_0
      37: getstatic     #28                 // Field Direction.L:LDirection;
      40: invokevirtual #22                 // Method Direction.ordinal:()I
      43: iconst_3
      44: iastore
      45: goto          49
      48: astore_1
      49: nop
      50: aload_0
      51: getstatic     #31                 // Field Direction.D:LDirection;
      54: invokevirtual #22                 // Method Direction.ordinal:()I
      57: iconst_4
      58: iastore
      59: goto          63
      62: astore_1
      63: aload_0
      64: putstatic     #35                 // Field $EnumSwitchMapping$0:[I
      67: return
    Exception table:
       from    to  target type
           7    17    20   Class java/lang/NoSuchFieldError
          21    31    34   Class java/lang/NoSuchFieldError
          35    45    48   Class java/lang/NoSuchFieldError
          49    59    62   Class java/lang/NoSuchFieldError
}


import java.io.File
import java.lang.Integer.max

fun main() {
  val result = File("inputs/day_8.txt").useLines { findScenicScore(it) }
  println(result)
}

fun findVisible(lines: Sequence<String>) =
  Grid(lines.map { line -> line.map { it.digitToInt()} }.toList())
    .toVisbile()

fun findScenicScore(lines: Sequence<String>) =
  Grid(lines.map { line -> line.map { it.digitToInt()} }.toList())
    .score()

data class Grid(val data: List<List<Int>>) {
  fun toVisbile() = data.indices.flatMap { x ->
    (0 until data[0].size).filter { y ->
      left(x, y) || right(x, y) || top(x, y) || down(x, y)
    }
  }.count()

  fun score() = data.indices.flatMap { x ->
    (0 until data[0].size).map { y ->
      leftScore(x, y) * rightScore(x, y) * topScore(x, y) * downScore(x, y)
    }
  }.max()

  private fun leftScore(x: Int, y: Int) = y - max(data[x].subList(0, y).indexOfLast { it >= data[x][y] }, 0)
  private fun rightScore(x: Int, y: Int) = data[x].subList(y+1, data[x].size)
    .indexOfFirst { it >= data[x][y] }
    .let { if (it == -1) data[x].size-1-y else it + 1 }
  private fun topScore(x: Int, y: Int) = x - max((0 until x).indexOfLast { data[x][y] <= data[it][y] }, 0)
  private fun downScore(x: Int, y: Int) = (x+1 until data.size)
    .indexOfFirst { data[x][y] <= data[it][y] }
    .let { if (it == -1) data.size-1-x else it + 1 }

  private fun left(x: Int, y: Int) = data[x].subList(0, y).maxOrZero() < data[x][y]
  private fun right(x: Int, y: Int) = data[x].subList(y+1, data[x].size).maxOrZero() < data[x][y]
  private fun top(x: Int, y: Int) = (0 until x).map { data[it][y] }.maxOrZero() < data[x][y]
  private fun down(x: Int, y: Int) = (x+1 until data.size).map { data[it][y] }.maxOrZero() < data[x][y]

  fun List<Int>.maxOrZero() = if (this.isEmpty()) -1 else this.max()
}

Compiled from "Day8.kt"
public final class Day8Kt {
  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String inputs/day_8.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: iconst_0
      15: istore_3
      16: aload_1
      17: astore        4
      19: sipush        8192
      22: istore        5
      24: aload         4
      26: astore        6
      28: new           #24                 // class java/io/InputStreamReader
      31: dup
      32: new           #26                 // class java/io/FileInputStream
      35: dup
      36: aload         6
      38: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      41: checkcast     #31                 // class java/io/InputStream
      44: aload_2
      45: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      48: checkcast     #36                 // class java/io/Reader
      51: astore        6
      53: aload         6
      55: instanceof    #38                 // class java/io/BufferedReader
      58: ifeq          69
      61: aload         6
      63: checkcast     #38                 // class java/io/BufferedReader
      66: goto          80
      69: new           #38                 // class java/io/BufferedReader
      72: dup
      73: aload         6
      75: iload         5
      77: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      80: checkcast     #43                 // class java/io/Closeable
      83: astore        4
      85: aconst_null
      86: astore        5
      88: nop
      89: aload         4
      91: checkcast     #38                 // class java/io/BufferedReader
      94: astore        6
      96: iconst_0
      97: istore        7
      99: aload         6
     101: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     104: astore        8
     106: iconst_0
     107: istore        9
     109: aload         8
     111: invokestatic  #53                 // Method findScenicScore:(Lkotlin/sequences/Sequence;)I
     114: istore        6
     116: aload         4
     118: aload         5
     120: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     123: iload         6
     125: goto          149
     128: astore        7
     130: aload         7
     132: astore        5
     134: aload         7
     136: athrow
     137: astore        7
     139: aload         4
     141: aload         5
     143: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     146: aload         7
     148: athrow
     149: nop
     150: istore_0
     151: getstatic     #65                 // Field java/lang/System.out:Ljava/io/PrintStream;
     154: iload_0
     155: invokevirtual #71                 // Method java/io/PrintStream.println:(I)V
     158: return
    Exception table:
       from    to  target type
          88   116   128   Class java/lang/Throwable
          88   116   137   any
         128   137   137   any
         137   139   137   any

  public static final int findVisible(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #92                 // String lines
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #100                // class Grid
       9: dup
      10: aload_0
      11: invokedynamic #119,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
      16: invokestatic  #125                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      19: invokestatic  #129                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
      22: invokespecial #132                // Method Grid."<init>":(Ljava/util/List;)V
      25: invokevirtual #136                // Method Grid.toVisbile:()I
      28: ireturn

  public static final int findScenicScore(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #92                 // String lines
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #100                // class Grid
       9: dup
      10: aload_0
      11: invokedynamic #141,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function1;
      16: invokestatic  #125                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      19: invokestatic  #129                // Method kotlin/sequences/SequencesKt.toList:(Lkotlin/sequences/Sequence;)Ljava/util/List;
      22: invokespecial #132                // Method Grid."<init>":(Ljava/util/List;)V
      25: invokevirtual #144                // Method Grid.score:()I
      28: ireturn

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

  private static final java.util.List findVisible$lambda$2(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #151                // String line
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #153                // class java/lang/CharSequence
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: astore_3
      15: new           #155                // class java/util/ArrayList
      18: dup
      19: aload_1
      20: invokeinterface #158,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      25: invokespecial #160                // Method java/util/ArrayList."<init>":(I)V
      28: checkcast     #162                // class java/util/Collection
      31: astore        4
      33: iconst_0
      34: istore        5
      36: iconst_0
      37: istore        6
      39: iload         6
      41: aload_3
      42: invokeinterface #158,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      47: if_icmpge     94
      50: aload_3
      51: iload         6
      53: invokeinterface #166,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      58: istore        7
      60: aload         4
      62: iload         7
      64: istore        8
      66: astore        10
      68: iconst_0
      69: istore        9
      71: iload         8
      73: invokestatic  #172                // Method kotlin/text/CharsKt.digitToInt:(C)I
      76: invokestatic  #178                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      79: aload         10
      81: swap
      82: invokeinterface #182,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      87: pop
      88: iinc          6, 1
      91: goto          39
      94: aload         4
      96: checkcast     #184                // class java/util/List
      99: nop
     100: areturn

  private static final java.util.List findScenicScore$lambda$4(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #151                // String line
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #153                // class java/lang/CharSequence
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: astore_3
      15: new           #155                // class java/util/ArrayList
      18: dup
      19: aload_1
      20: invokeinterface #158,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      25: invokespecial #160                // Method java/util/ArrayList."<init>":(I)V
      28: checkcast     #162                // class java/util/Collection
      31: astore        4
      33: iconst_0
      34: istore        5
      36: iconst_0
      37: istore        6
      39: iload         6
      41: aload_3
      42: invokeinterface #158,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      47: if_icmpge     94
      50: aload_3
      51: iload         6
      53: invokeinterface #166,  2          // InterfaceMethod java/lang/CharSequence.charAt:(I)C
      58: istore        7
      60: aload         4
      62: iload         7
      64: istore        8
      66: astore        10
      68: iconst_0
      69: istore        9
      71: iload         8
      73: invokestatic  #172                // Method kotlin/text/CharsKt.digitToInt:(C)I
      76: invokestatic  #178                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      79: aload         10
      81: swap
      82: invokeinterface #182,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
      87: pop
      88: iinc          6, 1
      91: goto          39
      94: aload         4
      96: checkcast     #184                // class java/util/List
      99: nop
     100: areturn
}


import RPS.PAPER
import RPS.ROCK
import RPS.SCISSORS
import java.io.File
import kotlin.IllegalArgumentException

fun main() {
  val result = File("inputs/day_2.txt").useLines { computeScorePart2(it) }
  println(result)
}

// Part 1
fun computeScorePart1(lines: Sequence<String>) =
  lines.map { it.split(" ") }
    .map { scorePart1(it.first().toRPS(), it.last().toRPS()) }
    .sum()

fun scorePart1(opponent: RPS, mine: RPS): Int {
  return mine.points + when {
    opponent == mine -> 3
    opponent.wins() == mine -> 6
    else -> 0
  }
}

// Part 2
fun computeScorePart2(lines: Sequence<String>) =
  lines.map { it.split(" ") }
    .map { scorePart2(it.first().toRPS(), it.last()) }
    .sum()

fun scorePart2(opponent: RPS, result: String) = when (result) {
  "X" -> opponent.lose().points
  "Y" -> 3 + opponent.points
  else -> 6 + opponent.wins().points
}

enum class RPS(val points: Int) {
  ROCK(1),
  PAPER(2),
  SCISSORS(3);

  fun wins() = order.first { (first, _) -> first == this }.second

  fun lose() = order.first { (_, second) -> second == this }.first

  companion object {
    val order = listOf(ROCK to PAPER, PAPER to SCISSORS, SCISSORS to ROCK)
  }
}

fun String.toRPS() = when (this) {
  "A", "X" -> ROCK
  "B", "Y" -> PAPER
  "C", "Z" -> SCISSORS
  else -> throw IllegalArgumentException()
}

Compiled from "Day2.kt"
public final class Day2Kt {
  public static final void main();
    Code:
       0: new           #10                 // class java/io/File
       3: dup
       4: ldc           #12                 // String inputs/day_2.txt
       6: invokespecial #16                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: astore_1
      10: getstatic     #22                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      13: astore_2
      14: iconst_0
      15: istore_3
      16: aload_1
      17: astore        4
      19: sipush        8192
      22: istore        5
      24: aload         4
      26: astore        6
      28: new           #24                 // class java/io/InputStreamReader
      31: dup
      32: new           #26                 // class java/io/FileInputStream
      35: dup
      36: aload         6
      38: invokespecial #29                 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V
      41: checkcast     #31                 // class java/io/InputStream
      44: aload_2
      45: invokespecial #34                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      48: checkcast     #36                 // class java/io/Reader
      51: astore        6
      53: aload         6
      55: instanceof    #38                 // class java/io/BufferedReader
      58: ifeq          69
      61: aload         6
      63: checkcast     #38                 // class java/io/BufferedReader
      66: goto          80
      69: new           #38                 // class java/io/BufferedReader
      72: dup
      73: aload         6
      75: iload         5
      77: invokespecial #41                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      80: checkcast     #43                 // class java/io/Closeable
      83: astore        4
      85: aconst_null
      86: astore        5
      88: nop
      89: aload         4
      91: checkcast     #38                 // class java/io/BufferedReader
      94: astore        6
      96: iconst_0
      97: istore        7
      99: aload         6
     101: invokestatic  #49                 // Method kotlin/io/TextStreamsKt.lineSequence:(Ljava/io/BufferedReader;)Lkotlin/sequences/Sequence;
     104: astore        8
     106: iconst_0
     107: istore        9
     109: aload         8
     111: invokestatic  #53                 // Method computeScorePart2:(Lkotlin/sequences/Sequence;)I
     114: istore        6
     116: aload         4
     118: aload         5
     120: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     123: iload         6
     125: goto          149
     128: astore        7
     130: aload         7
     132: astore        5
     134: aload         7
     136: athrow
     137: astore        7
     139: aload         4
     141: aload         5
     143: invokestatic  #59                 // Method kotlin/io/CloseableKt.closeFinally:(Ljava/io/Closeable;Ljava/lang/Throwable;)V
     146: aload         7
     148: athrow
     149: nop
     150: istore_0
     151: getstatic     #65                 // Field java/lang/System.out:Ljava/io/PrintStream;
     154: iload_0
     155: invokevirtual #71                 // Method java/io/PrintStream.println:(I)V
     158: return
    Exception table:
       from    to  target type
          88   116   128   Class java/lang/Throwable
          88   116   137   any
         128   137   137   any
         137   139   137   any

  public static final int computeScorePart1(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #92                 // String lines
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #117,  0            // InvokeDynamic #0:invoke:()Lkotlin/jvm/functions/Function1;
      12: invokestatic  #123                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      15: invokedynamic #131,  0            // InvokeDynamic #1:invoke:()Lkotlin/jvm/functions/Function1;
      20: invokestatic  #123                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      23: invokestatic  #134                // Method kotlin/sequences/SequencesKt.sumOfInt:(Lkotlin/sequences/Sequence;)I
      26: ireturn

  public static final int scorePart1(RPS, RPS);
    Code:
       0: aload_0
       1: ldc           #138                // String opponent
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #140                // String mine
       9: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: invokevirtual #146                // Method RPS.getPoints:()I
      16: aload_0
      17: aload_1
      18: if_acmpne     25
      21: iconst_3
      22: goto          39
      25: aload_0
      26: invokevirtual #150                // Method RPS.wins:()LRPS;
      29: aload_1
      30: if_acmpne     38
      33: bipush        6
      35: goto          39
      38: iconst_0
      39: iadd
      40: ireturn

  public static final int computeScorePart2(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #92                 // String lines
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #156,  0            // InvokeDynamic #2:invoke:()Lkotlin/jvm/functions/Function1;
      12: invokestatic  #123                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      15: invokedynamic #161,  0            // InvokeDynamic #3:invoke:()Lkotlin/jvm/functions/Function1;
      20: invokestatic  #123                // Method kotlin/sequences/SequencesKt.map:(Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
      23: invokestatic  #134                // Method kotlin/sequences/SequencesKt.sumOfInt:(Lkotlin/sequences/Sequence;)I
      26: ireturn

  public static final int scorePart2(RPS, java.lang.String);
    Code:
       0: aload_0
       1: ldc           #138                // String opponent
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #164                // String result
       9: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: astore_2
      14: aload_2
      15: ldc           #166                // String X
      17: invokestatic  #170                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      20: ifeq          33
      23: aload_0
      24: invokevirtual #173                // Method RPS.lose:()LRPS;
      27: invokevirtual #146                // Method RPS.getPoints:()I
      30: goto          61
      33: aload_2
      34: ldc           #175                // String Y
      36: invokestatic  #170                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      39: ifeq          51
      42: iconst_3
      43: aload_0
      44: invokevirtual #146                // Method RPS.getPoints:()I
      47: iadd
      48: goto          61
      51: bipush        6
      53: aload_0
      54: invokevirtual #150                // Method RPS.wins:()LRPS;
      57: invokevirtual #146                // Method RPS.getPoints:()I
      60: iadd
      61: ireturn

  public static final RPS toRPS(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #182                // String <this>
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: astore_1
       8: aload_1
       9: invokevirtual #185                // Method java/lang/String.hashCode:()I
      12: lookupswitch  { // 6
                    65: 72
                    66: 84
                    67: 96
                    88: 108
                    89: 120
                    90: 132
               default: 162
          }
      72: aload_1
      73: ldc           #187                // String A
      75: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      78: ifne          144
      81: goto          162
      84: aload_1
      85: ldc           #193                // String B
      87: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      90: ifne          150
      93: goto          162
      96: aload_1
      97: ldc           #195                // String C
      99: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     102: ifne          156
     105: goto          162
     108: aload_1
     109: ldc           #166                // String X
     111: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     114: ifne          144
     117: goto          162
     120: aload_1
     121: ldc           #175                // String Y
     123: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     126: ifne          150
     129: goto          162
     132: aload_1
     133: ldc           #197                // String Z
     135: invokevirtual #191                // Method java/lang/String.equals:(Ljava/lang/Object;)Z
     138: ifne          156
     141: goto          162
     144: getstatic     #200                // Field RPS.ROCK:LRPS;
     147: goto          170
     150: getstatic     #203                // Field RPS.PAPER:LRPS;
     153: goto          170
     156: getstatic     #206                // Field RPS.SCISSORS:LRPS;
     159: goto          170
     162: new           #208                // class java/lang/IllegalArgumentException
     165: dup
     166: invokespecial #210                // Method java/lang/IllegalArgumentException."<init>":()V
     169: athrow
     170: areturn

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

  private static final java.util.List computeScorePart1$lambda$1(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #217                // String it
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #219                // class java/lang/CharSequence
      10: iconst_1
      11: anewarray     #178                // class java/lang/String
      14: astore_1
      15: aload_1
      16: iconst_0
      17: ldc           #221                // String
      19: aastore
      20: aload_1
      21: iconst_0
      22: iconst_0
      23: bipush        6
      25: aconst_null
      26: invokestatic  #227                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      29: areturn

  private static final int computeScorePart1$lambda$2(java.util.List);
    Code:
       0: aload_0
       1: ldc           #217                // String it
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #233                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      10: checkcast     #178                // class java/lang/String
      13: invokestatic  #235                // Method toRPS:(Ljava/lang/String;)LRPS;
      16: aload_0
      17: invokestatic  #238                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      20: checkcast     #178                // class java/lang/String
      23: invokestatic  #235                // Method toRPS:(Ljava/lang/String;)LRPS;
      26: invokestatic  #240                // Method scorePart1:(LRPS;LRPS;)I
      29: ireturn

  private static final java.util.List computeScorePart2$lambda$3(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #217                // String it
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #219                // class java/lang/CharSequence
      10: iconst_1
      11: anewarray     #178                // class java/lang/String
      14: astore_1
      15: aload_1
      16: iconst_0
      17: ldc           #221                // String
      19: aastore
      20: aload_1
      21: iconst_0
      22: iconst_0
      23: bipush        6
      25: aconst_null
      26: invokestatic  #227                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      29: areturn

  private static final int computeScorePart2$lambda$4(java.util.List);
    Code:
       0: aload_0
       1: ldc           #217                // String it
       3: invokestatic  #98                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #233                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      10: checkcast     #178                // class java/lang/String
      13: invokestatic  #235                // Method toRPS:(Ljava/lang/String;)LRPS;
      16: aload_0
      17: invokestatic  #238                // Method kotlin/collections/CollectionsKt.last:(Ljava/util/List;)Ljava/lang/Object;
      20: checkcast     #178                // class java/lang/String
      23: invokestatic  #243                // Method scorePart2:(LRPS;Ljava/lang/String;)I
      26: ireturn
}


import java.nio.file.Path

fun fileSizeToDelete(lines: Sequence<String>) = directorySizes(lines).smallestFileToDelete()

fun fileSize(lines: Sequence<String>) =
  directorySizes(lines).directorySizes.values
    .filter { it <=100000 }
    .sum()

private fun directorySizes(lines: Sequence<String>) =
  lines.fold(DirectoryStructure()) { acc, line ->
    when {
      line.startsWith("$ cd ") -> acc.cd(line.split(" ")[2])
      line[0].isDigit() -> acc.addSizes(line.split(" ")[0].toInt())
      else -> acc
    }
  }

data class DirectoryStructure(
  val directorySizes: Map<Path, Int> = mapOf(),
  val current: Path = ROOT_PATH
) {
  fun cd(dirName: String) = when (dirName) {
    ROOT -> copy(current = ROOT_PATH)
    PARENT -> copy(current = current.parent)
    else -> copy(current = current.resolve(dirName))
  }

  fun addSizes(size: Int) = copy(directorySizes = directorySizes + findSizes(current, size))

  fun totalSize() = directorySizes[ROOT_PATH]!!

  private fun findSizes(current: Path, size: Int): List<Pair<Path, Int>> =
    listOf(current to directorySizes.getOrDefault(current, 0) + size) + parentSize(current, size)

  private fun parentSize(current: Path, size: Int) =
    if (current.parent == null) listOf() else findSizes(current.parent, size)
  fun smallestFileToDelete() = directorySizes.values
    .sorted().first { totalSize() - it <= 40000000 }

  companion object {
    val ROOT = "/"
    val PARENT = ".."
    val ROOT_PATH = Path.of(ROOT)
  }
}

Compiled from "Day7.kt"
public final class Day7Kt {
  public static final int fileSizeToDelete(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String lines
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #20                 // Method directorySizes:(Lkotlin/sequences/Sequence;)LDirectoryStructure;
      10: invokevirtual #26                 // Method DirectoryStructure.smallestFileToDelete:()I
      13: ireturn

  public static final int fileSize(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #10                 // String lines
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #20                 // Method directorySizes:(Lkotlin/sequences/Sequence;)LDirectoryStructure;
      10: invokevirtual #32                 // Method DirectoryStructure.getDirectorySizes:()Ljava/util/Map;
      13: invokeinterface #38,  1           // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
      18: checkcast     #40                 // class java/lang/Iterable
      21: astore_1
      22: nop
      23: iconst_0
      24: istore_2
      25: aload_1
      26: astore_3
      27: new           #42                 // class java/util/ArrayList
      30: dup
      31: invokespecial #46                 // Method java/util/ArrayList."<init>":()V
      34: checkcast     #48                 // class java/util/Collection
      37: astore        4
      39: iconst_0
      40: istore        5
      42: aload_3
      43: invokeinterface #52,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      48: astore        6
      50: aload         6
      52: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      57: ifeq          110
      60: aload         6
      62: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      67: astore        7
      69: aload         7
      71: checkcast     #64                 // class java/lang/Number
      74: invokevirtual #67                 // Method java/lang/Number.intValue:()I
      77: istore        8
      79: iconst_0
      80: istore        9
      82: iload         8
      84: ldc           #68                 // int 100000
      86: if_icmpgt     93
      89: iconst_1
      90: goto          94
      93: iconst_0
      94: ifeq          50
      97: aload         4
      99: aload         7
     101: invokeinterface #72,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     106: pop
     107: goto          50
     110: aload         4
     112: checkcast     #74                 // class java/util/List
     115: nop
     116: checkcast     #40                 // class java/lang/Iterable
     119: invokestatic  #80                 // Method kotlin/collections/CollectionsKt.sumOfInt:(Ljava/lang/Iterable;)I
     122: ireturn

  private static final DirectoryStructure directorySizes(kotlin.sequences.Sequence<java.lang.String>);
    Code:
       0: aload_0
       1: astore_1
       2: new           #22                 // class DirectoryStructure
       5: dup
       6: aconst_null
       7: aconst_null
       8: iconst_3
       9: aconst_null
      10: invokespecial #98                 // Method DirectoryStructure."<init>":(Ljava/util/Map;Ljava/nio/file/Path;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      13: astore_2
      14: iconst_0
      15: istore_3
      16: aload_2
      17: astore        4
      19: aload_1
      20: invokeinterface #99,  1           // InterfaceMethod kotlin/sequences/Sequence.iterator:()Ljava/util/Iterator;
      25: astore        5
      27: aload         5
      29: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      34: ifeq          185
      37: aload         5
      39: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      44: astore        6
      46: aload         4
      48: aload         6
      50: checkcast     #101                // class java/lang/String
      53: astore        7
      55: astore        8
      57: iconst_0
      58: istore        9
      60: nop
      61: aload         7
      63: ldc           #103                // String $ cd
      65: iconst_0
      66: iconst_2
      67: aconst_null
      68: invokestatic  #109                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
      71: ifeq          118
      74: aload         8
      76: aload         7
      78: checkcast     #111                // class java/lang/CharSequence
      81: iconst_1
      82: anewarray     #101                // class java/lang/String
      85: astore        10
      87: aload         10
      89: iconst_0
      90: ldc           #113                // String
      92: aastore
      93: aload         10
      95: iconst_0
      96: iconst_0
      97: bipush        6
      99: aconst_null
     100: invokestatic  #117                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     103: iconst_2
     104: invokeinterface #121,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     109: checkcast     #101                // class java/lang/String
     112: invokevirtual #125                // Method DirectoryStructure.cd:(Ljava/lang/String;)LDirectoryStructure;
     115: goto          179
     118: aload         7
     120: iconst_0
     121: invokevirtual #129                // Method java/lang/String.charAt:(I)C
     124: invokestatic  #135                // Method java/lang/Character.isDigit:(C)Z
     127: ifeq          177
     130: aload         8
     132: aload         7
     134: checkcast     #111                // class java/lang/CharSequence
     137: iconst_1
     138: anewarray     #101                // class java/lang/String
     141: astore        10
     143: aload         10
     145: iconst_0
     146: ldc           #113                // String
     148: aastore
     149: aload         10
     151: iconst_0
     152: iconst_0
     153: bipush        6
     155: aconst_null
     156: invokestatic  #117                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     159: iconst_0
     160: invokeinterface #121,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     165: checkcast     #101                // class java/lang/String
     168: invokestatic  #141                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     171: invokevirtual #145                // Method DirectoryStructure.addSizes:(I)LDirectoryStructure;
     174: goto          179
     177: aload         8
     179: nop
     180: astore        4
     182: goto          27
     185: aload         4
     187: areturn
}