package Chapter5

fun createMap(){

    val map: Map<Int,String> = mapOf( Pair(1,"One"), Pair(1,"One"), Pair(2,"Two"), Pair(3,"Three"), 4 to "Four", 5 to "Five")
    for(pair in map){
        println("${pair.key} ${pair.value}")
    }

    val setOfPairs = map.entries
    for ((key, value) in setOfPairs) {
        println("$key $value")
    }
}

fun mapFunctions(){

    val map: Map<Int,String> = mapOf( Pair(1,"One"), Pair(1,"One"), Pair(2,"Two"), Pair(3,"Three"), 4 to "Four", 5 to "Five")

    //Check if map is empty or not
    if( map.isNotEmpty()) {

        println("Map size is  ${map.size}" )

        val setofkeys = map.keys
        println("Keys $setofkeys")

        val setofvalues = map.values
        println("Values $setofvalues")

        var key = 1
        if(map.containsKey(key)) {
            val value = map.get(key)
            println("key: $key value: $value")
        }
    }
}

fun mapDaysOfWeek01(day: Int): String? {

    var result : String?
    val daysOfWeek: Map<Int, String> = mapOf(1 to "Monday", 2 to "Tuesday", 3 to "Wednesday", 4 to "Thrusday", 5 to "Firday", 6 to "Saturday", 7 to "Sunday")
    result = daysOfWeek.get(day)
    return result
}

fun mapDaysOfWeek02(day: Int): String {

    var result : String
    val daysOfWeek: Map<Int, String> = mapOf(1 to "Monday", 2 to "Tuesday", 3 to "Wednesday", 4 to "Thrusday", 5 to "Firday", 6 to "Saturday", 7 to "Sunday")
    result = daysOfWeek.getOrDefault(day, "Invalid input")
    return result
}

fun mutableMapPutFunction(){

    val map : MutableMap<Int,String> = mutableMapOf ( Pair(1,"One"), Pair(1,"One"), Pair(2,"Two"), Pair(3,"Three"))

    map.put(4 ,"Four")
    var result = map.put(4 ,"FOUR")
    println(map)
    println("Put " + result)

    result = map.put(1 ,"One")
    println(map)
    println("Put " + result)

}

fun mutableMapRemove(){

    val map : MutableMap<Int,String> = mutableMapOf ( Pair(1,"One"),Pair(2,"Two"), Pair(3,"Three"), Pair(4,"Four"))
    println(map)

    var result = map.remove(4)
    println("Remove " + result)

    var success = map.remove(2,"Two")
    println("Remove " + success)

    println(map)
}

fun clearAndPutAll(){

    val map : MutableMap<Int,String> = mutableMapOf ( Pair(1,"One"), Pair(2,"Two"), Pair(3,"Three"))
    println(map)

    val miniMap = mapOf(Pair(4,"Four"),Pair(5,"Five"))
    map.putAll(miniMap)
    println(map)

    map.clear()
    println(map)

    map.putAll(miniMap)
    println(map)
}

fun main(args: Array<String>) {

    mutableMapPutFunction()
}

Compiled from "Map.kt"
public final class Chapter5.MapKt {
  public static final void createMap();
    Code:
       0: bipush        6
       2: anewarray     #8                  // class kotlin/Pair
       5: astore_1
       6: aload_1
       7: iconst_0
       8: new           #8                  // class kotlin/Pair
      11: dup
      12: iconst_1
      13: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      16: ldc           #16                 // String One
      18: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      21: aastore
      22: aload_1
      23: iconst_1
      24: new           #8                  // class kotlin/Pair
      27: dup
      28: iconst_1
      29: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      32: ldc           #16                 // String One
      34: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      37: aastore
      38: aload_1
      39: iconst_2
      40: new           #8                  // class kotlin/Pair
      43: dup
      44: iconst_2
      45: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      48: ldc           #22                 // String Two
      50: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      53: aastore
      54: aload_1
      55: iconst_3
      56: new           #8                  // class kotlin/Pair
      59: dup
      60: iconst_3
      61: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      64: ldc           #24                 // String Three
      66: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      69: aastore
      70: aload_1
      71: iconst_4
      72: iconst_4
      73: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      76: ldc           #26                 // String Four
      78: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      81: aastore
      82: aload_1
      83: iconst_5
      84: iconst_5
      85: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      88: ldc           #34                 // String Five
      90: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      93: aastore
      94: aload_1
      95: invokestatic  #40                 // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
      98: astore_0
      99: aload_0
     100: invokeinterface #46,  1           // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
     105: invokeinterface #52,  1           // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
     110: astore_1
     111: aload_1
     112: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     117: ifeq          182
     120: aload_1
     121: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     126: checkcast     #64                 // class java/util/Map$Entry
     129: astore_2
     130: new           #66                 // class java/lang/StringBuilder
     133: dup
     134: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     137: aload_2
     138: invokeinterface #71,  1           // InterfaceMethod java/util/Map$Entry.getKey:()Ljava/lang/Object;
     143: checkcast     #73                 // class java/lang/Number
     146: invokevirtual #77                 // Method java/lang/Number.intValue:()I
     149: invokevirtual #81                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     152: bipush        32
     154: invokevirtual #84                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     157: aload_2
     158: invokeinterface #87,  1           // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     163: checkcast     #89                 // class java/lang/String
     166: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     169: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     172: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     175: swap
     176: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     179: goto          111
     182: aload_0
     183: invokeinterface #46,  1           // InterfaceMethod java/util/Map.entrySet:()Ljava/util/Set;
     188: astore_1
     189: aload_1
     190: invokeinterface #52,  1           // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
     195: astore_2
     196: aload_2
     197: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     202: ifeq          275
     205: aload_2
     206: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     211: checkcast     #64                 // class java/util/Map$Entry
     214: astore_3
     215: aload_3
     216: invokeinterface #71,  1           // InterfaceMethod java/util/Map$Entry.getKey:()Ljava/lang/Object;
     221: checkcast     #73                 // class java/lang/Number
     224: invokevirtual #77                 // Method java/lang/Number.intValue:()I
     227: istore        4
     229: aload_3
     230: invokeinterface #87,  1           // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     235: checkcast     #89                 // class java/lang/String
     238: astore        5
     240: new           #66                 // class java/lang/StringBuilder
     243: dup
     244: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     247: iload         4
     249: invokevirtual #81                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     252: bipush        32
     254: invokevirtual #84                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     257: aload         5
     259: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     262: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     265: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     268: swap
     269: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     272: goto          196
     275: return

  public static final void mapFunctions();
    Code:
       0: bipush        6
       2: anewarray     #8                  // class kotlin/Pair
       5: astore_1
       6: aload_1
       7: iconst_0
       8: new           #8                  // class kotlin/Pair
      11: dup
      12: iconst_1
      13: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      16: ldc           #16                 // String One
      18: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      21: aastore
      22: aload_1
      23: iconst_1
      24: new           #8                  // class kotlin/Pair
      27: dup
      28: iconst_1
      29: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      32: ldc           #16                 // String One
      34: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      37: aastore
      38: aload_1
      39: iconst_2
      40: new           #8                  // class kotlin/Pair
      43: dup
      44: iconst_2
      45: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      48: ldc           #22                 // String Two
      50: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      53: aastore
      54: aload_1
      55: iconst_3
      56: new           #8                  // class kotlin/Pair
      59: dup
      60: iconst_3
      61: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      64: ldc           #24                 // String Three
      66: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      69: aastore
      70: aload_1
      71: iconst_4
      72: iconst_4
      73: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      76: ldc           #26                 // String Four
      78: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      81: aastore
      82: aload_1
      83: iconst_5
      84: iconst_5
      85: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      88: ldc           #34                 // String Five
      90: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      93: aastore
      94: aload_1
      95: invokestatic  #40                 // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
      98: astore_0
      99: aload_0
     100: invokeinterface #122,  1          // InterfaceMethod java/util/Map.isEmpty:()Z
     105: ifne          112
     108: iconst_1
     109: goto          113
     112: iconst_0
     113: ifeq          279
     116: new           #66                 // class java/lang/StringBuilder
     119: dup
     120: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     123: ldc           #124                // String Map size is
     125: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     128: aload_0
     129: invokeinterface #127,  1          // InterfaceMethod java/util/Map.size:()I
     134: invokevirtual #81                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     137: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     140: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     143: swap
     144: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     147: aload_0
     148: invokeinterface #130,  1          // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set;
     153: astore_1
     154: new           #66                 // class java/lang/StringBuilder
     157: dup
     158: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     161: ldc           #132                // String Keys
     163: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     166: aload_1
     167: invokevirtual #135                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     170: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     173: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     176: swap
     177: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     180: aload_0
     181: invokeinterface #139,  1          // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
     186: astore_2
     187: new           #66                 // class java/lang/StringBuilder
     190: dup
     191: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     194: ldc           #141                // String Values
     196: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     199: aload_2
     200: invokevirtual #135                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     203: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     206: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     209: swap
     210: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     213: iconst_1
     214: istore_3
     215: aload_0
     216: iload_3
     217: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     220: invokeinterface #145,  2          // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
     225: ifeq          279
     228: aload_0
     229: iload_3
     230: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     233: invokeinterface #149,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     238: checkcast     #89                 // class java/lang/String
     241: astore        4
     243: new           #66                 // class java/lang/StringBuilder
     246: dup
     247: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     250: ldc           #151                // String key:
     252: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     255: iload_3
     256: invokevirtual #81                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     259: ldc           #153                // String  value:
     261: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     264: aload         4
     266: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     269: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     272: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     275: swap
     276: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     279: return

  public static final java.lang.String mapDaysOfWeek01(int);
    Code:
       0: aconst_null
       1: astore_1
       2: bipush        7
       4: anewarray     #8                  // class kotlin/Pair
       7: astore_3
       8: aload_3
       9: iconst_0
      10: iconst_1
      11: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      14: ldc           #163                // String Monday
      16: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      19: aastore
      20: aload_3
      21: iconst_1
      22: iconst_2
      23: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      26: ldc           #165                // String Tuesday
      28: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      31: aastore
      32: aload_3
      33: iconst_2
      34: iconst_3
      35: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      38: ldc           #167                // String Wednesday
      40: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      43: aastore
      44: aload_3
      45: iconst_3
      46: iconst_4
      47: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      50: ldc           #169                // String Thrusday
      52: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      55: aastore
      56: aload_3
      57: iconst_4
      58: iconst_5
      59: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      62: ldc           #171                // String Firday
      64: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      67: aastore
      68: aload_3
      69: iconst_5
      70: bipush        6
      72: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      75: ldc           #173                // String Saturday
      77: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      80: aastore
      81: aload_3
      82: bipush        6
      84: bipush        7
      86: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      89: ldc           #175                // String Sunday
      91: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      94: aastore
      95: aload_3
      96: invokestatic  #40                 // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
      99: astore_2
     100: aload_2
     101: iload_0
     102: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     105: invokeinterface #149,  2          // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     110: checkcast     #89                 // class java/lang/String
     113: astore_1
     114: aload_1
     115: areturn

  public static final java.lang.String mapDaysOfWeek02(int);
    Code:
       0: aconst_null
       1: astore_1
       2: bipush        7
       4: anewarray     #8                  // class kotlin/Pair
       7: astore_3
       8: aload_3
       9: iconst_0
      10: iconst_1
      11: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      14: ldc           #163                // String Monday
      16: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      19: aastore
      20: aload_3
      21: iconst_1
      22: iconst_2
      23: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      26: ldc           #165                // String Tuesday
      28: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      31: aastore
      32: aload_3
      33: iconst_2
      34: iconst_3
      35: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      38: ldc           #167                // String Wednesday
      40: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      43: aastore
      44: aload_3
      45: iconst_3
      46: iconst_4
      47: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      50: ldc           #169                // String Thrusday
      52: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      55: aastore
      56: aload_3
      57: iconst_4
      58: iconst_5
      59: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      62: ldc           #171                // String Firday
      64: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      67: aastore
      68: aload_3
      69: iconst_5
      70: bipush        6
      72: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      75: ldc           #173                // String Saturday
      77: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      80: aastore
      81: aload_3
      82: bipush        6
      84: bipush        7
      86: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      89: ldc           #175                // String Sunday
      91: invokestatic  #32                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      94: aastore
      95: aload_3
      96: invokestatic  #40                 // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
      99: astore_2
     100: aload_2
     101: iload_0
     102: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     105: ldc           #182                // String Invalid input
     107: invokeinterface #186,  3          // InterfaceMethod java/util/Map.getOrDefault:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     112: checkcast     #89                 // class java/lang/String
     115: astore_1
     116: aload_1
     117: areturn

  public static final void mutableMapPutFunction();
    Code:
       0: iconst_4
       1: anewarray     #8                  // class kotlin/Pair
       4: astore_1
       5: aload_1
       6: iconst_0
       7: new           #8                  // class kotlin/Pair
      10: dup
      11: iconst_1
      12: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: ldc           #16                 // String One
      17: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      20: aastore
      21: aload_1
      22: iconst_1
      23: new           #8                  // class kotlin/Pair
      26: dup
      27: iconst_1
      28: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      31: ldc           #16                 // String One
      33: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      36: aastore
      37: aload_1
      38: iconst_2
      39: new           #8                  // class kotlin/Pair
      42: dup
      43: iconst_2
      44: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      47: ldc           #22                 // String Two
      49: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      52: aastore
      53: aload_1
      54: iconst_3
      55: new           #8                  // class kotlin/Pair
      58: dup
      59: iconst_3
      60: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      63: ldc           #24                 // String Three
      65: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      68: aastore
      69: aload_1
      70: invokestatic  #190                // Method kotlin/collections/MapsKt.mutableMapOf:([Lkotlin/Pair;)Ljava/util/Map;
      73: astore_0
      74: aload_0
      75: iconst_4
      76: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      79: ldc           #26                 // String Four
      81: invokeinterface #193,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      86: pop
      87: aload_0
      88: iconst_4
      89: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      92: ldc           #195                // String FOUR
      94: invokeinterface #193,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      99: checkcast     #89                 // class java/lang/String
     102: astore_1
     103: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     106: aload_0
     107: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     110: new           #66                 // class java/lang/StringBuilder
     113: dup
     114: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     117: ldc           #197                // String Put
     119: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     122: aload_1
     123: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     126: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     129: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     132: swap
     133: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     136: aload_0
     137: iconst_1
     138: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     141: ldc           #16                 // String One
     143: invokeinterface #193,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     148: checkcast     #89                 // class java/lang/String
     151: astore_1
     152: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     155: aload_0
     156: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     159: new           #66                 // class java/lang/StringBuilder
     162: dup
     163: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     166: ldc           #197                // String Put
     168: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     171: aload_1
     172: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     175: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     178: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     181: swap
     182: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     185: return

  public static final void mutableMapRemove();
    Code:
       0: iconst_4
       1: anewarray     #8                  // class kotlin/Pair
       4: astore_1
       5: aload_1
       6: iconst_0
       7: new           #8                  // class kotlin/Pair
      10: dup
      11: iconst_1
      12: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: ldc           #16                 // String One
      17: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      20: aastore
      21: aload_1
      22: iconst_1
      23: new           #8                  // class kotlin/Pair
      26: dup
      27: iconst_2
      28: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      31: ldc           #22                 // String Two
      33: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      36: aastore
      37: aload_1
      38: iconst_2
      39: new           #8                  // class kotlin/Pair
      42: dup
      43: iconst_3
      44: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      47: ldc           #24                 // String Three
      49: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      52: aastore
      53: aload_1
      54: iconst_3
      55: new           #8                  // class kotlin/Pair
      58: dup
      59: iconst_4
      60: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      63: ldc           #26                 // String Four
      65: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      68: aastore
      69: aload_1
      70: invokestatic  #190                // Method kotlin/collections/MapsKt.mutableMapOf:([Lkotlin/Pair;)Ljava/util/Map;
      73: astore_0
      74: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      77: aload_0
      78: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      81: aload_0
      82: iconst_4
      83: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      86: invokeinterface #201,  2          // InterfaceMethod java/util/Map.remove:(Ljava/lang/Object;)Ljava/lang/Object;
      91: checkcast     #89                 // class java/lang/String
      94: astore_1
      95: new           #66                 // class java/lang/StringBuilder
      98: dup
      99: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     102: ldc           #203                // String Remove
     104: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     107: aload_1
     108: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     111: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     114: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     117: swap
     118: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     121: aload_0
     122: iconst_2
     123: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     126: ldc           #22                 // String Two
     128: invokeinterface #206,  3          // InterfaceMethod java/util/Map.remove:(Ljava/lang/Object;Ljava/lang/Object;)Z
     133: istore_2
     134: new           #66                 // class java/lang/StringBuilder
     137: dup
     138: invokespecial #68                 // Method java/lang/StringBuilder."<init>":()V
     141: ldc           #203                // String Remove
     143: invokevirtual #92                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     146: iload_2
     147: invokevirtual #209                // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
     150: invokevirtual #96                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     153: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     156: swap
     157: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     160: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     163: aload_0
     164: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     167: return

  public static final void clearAndPutAll();
    Code:
       0: iconst_3
       1: anewarray     #8                  // class kotlin/Pair
       4: astore_1
       5: aload_1
       6: iconst_0
       7: new           #8                  // class kotlin/Pair
      10: dup
      11: iconst_1
      12: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: ldc           #16                 // String One
      17: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      20: aastore
      21: aload_1
      22: iconst_1
      23: new           #8                  // class kotlin/Pair
      26: dup
      27: iconst_2
      28: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      31: ldc           #22                 // String Two
      33: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      36: aastore
      37: aload_1
      38: iconst_2
      39: new           #8                  // class kotlin/Pair
      42: dup
      43: iconst_3
      44: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      47: ldc           #24                 // String Three
      49: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      52: aastore
      53: aload_1
      54: invokestatic  #190                // Method kotlin/collections/MapsKt.mutableMapOf:([Lkotlin/Pair;)Ljava/util/Map;
      57: astore_0
      58: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      61: aload_0
      62: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      65: iconst_2
      66: anewarray     #8                  // class kotlin/Pair
      69: astore_2
      70: aload_2
      71: iconst_0
      72: new           #8                  // class kotlin/Pair
      75: dup
      76: iconst_4
      77: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      80: ldc           #26                 // String Four
      82: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      85: aastore
      86: aload_2
      87: iconst_1
      88: new           #8                  // class kotlin/Pair
      91: dup
      92: iconst_5
      93: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      96: ldc           #34                 // String Five
      98: invokespecial #20                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     101: aastore
     102: aload_2
     103: invokestatic  #40                 // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
     106: astore_1
     107: aload_0
     108: aload_1
     109: invokeinterface #216,  2          // InterfaceMethod java/util/Map.putAll:(Ljava/util/Map;)V
     114: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     117: aload_0
     118: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     121: aload_0
     122: invokeinterface #219,  1          // InterfaceMethod java/util/Map.clear:()V
     127: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     130: aload_0
     131: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     134: aload_0
     135: aload_1
     136: invokeinterface #216,  2          // InterfaceMethod java/util/Map.putAll:(Ljava/util/Map;)V
     141: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     144: aload_0
     145: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     148: return

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #224                // String args
       3: invokestatic  #230                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: invokestatic  #232                // Method mutableMapPutFunction:()V
       9: return
}


package day07

import java.io.File
import kotlin.system.measureTimeMillis

data class DirectoryTree (
    val name: String,
    val size: Int = 0,
    val children: List<DirectoryTree> = listOf()
) {

    val fullSize: Int by lazy { size + children.sumOf { it.fullSize } }

    fun getDirectorySizeList(): List<Int> =
        if (size == 0) {
            listOf(fullSize) + children.flatMap { it.getDirectorySizeList() }
        } else emptyList()

}

fun sumDirectoriesUnderSize(tree: DirectoryTree, maxSize: Int): Int
    = (tree.fullSize.takeIf { it <= maxSize } ?: 0) + tree.children.filter { it.size == 0 }.sumOf { sumDirectoriesUnderSize(it, maxSize) }

fun findSmallerDirectoryToDelete(tree: DirectoryTree): Int {
    val availableSpace = 70000000 - tree.fullSize
    val neededSpace = 30000000 - availableSpace
    assert(neededSpace > 0)

    return tree.getDirectorySizeList().sorted().first { it >= neededSpace }
}

fun addToTreeAtNode(tree: DirectoryTree, levels: List<String>, size: Int, name: String): DirectoryTree {
    return if (levels.isEmpty()) {
        tree.copy(children = tree.children + DirectoryTree(name, size))
    } else {
        val nextLevel = levels.first()
        val nextChild = tree.children.first { it.name == nextLevel }
        tree.copy(children =
            tree.children.filter{ it.name != nextLevel} + addToTreeAtNode(nextChild, levels.drop(1), size, name)
            )
    }
}

fun parseFileAndBuildTree() =
    File("src/main/kotlin/day07/input.txt")
        .readLines()
        .fold(Pair(emptyList<String>(), DirectoryTree("/"))) { acc, it ->
            if ( it.startsWith("$")) {
                Regex("cd ([.a-z]+)").find(it)
                    ?.groupValues
                    ?.let {
                        if (it[1] == "..") {
                            Pair(
                                acc.first.dropLast(1),
                                acc.second
                            )
                        } else {
                            Pair(
                                acc.first + it[1],
                                acc.second
                            )
                        }
                    }?: acc
            } else {
                val (sizeType, fileName) = it.split(' ')
                Pair(
                    acc.first,
                    addToTreeAtNode(
                        acc.second,
                        acc.first,
                        if (sizeType == "dir") 0 else sizeType.toInt(),
                        fileName
                    )
                )
            }
        }.second

fun main() {
    val elapsed = measureTimeMillis {
        val tree = parseFileAndBuildTree()
        println("The sum of the directory which size is under 100000 is ${sumDirectoriesUnderSize(tree, 100000)}")
        println("The size of the smallest directory to delete is ${findSmallerDirectoryToDelete(tree)}")
    }
    println("The whole thing needed $elapsed to finish")
}

Compiled from "Solution.kt"
public final class day07.SolutionKt {
  public static final int sumDirectoriesUnderSize(day07.DirectoryTree, int);
    Code:
       0: aload_0
       1: ldc           #9                  // String tree
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #21                 // Method day07/DirectoryTree.getFullSize:()I
      10: invokestatic  #27                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: astore_3
      14: aload_3
      15: checkcast     #29                 // class java/lang/Number
      18: invokevirtual #32                 // Method java/lang/Number.intValue:()I
      21: istore        4
      23: iconst_0
      24: istore        5
      26: iload         4
      28: iload_1
      29: if_icmpgt     36
      32: iconst_1
      33: goto          37
      36: iconst_0
      37: ifeq          44
      40: aload_3
      41: goto          45
      44: aconst_null
      45: dup
      46: ifnull        55
      49: invokevirtual #33                 // Method java/lang/Integer.intValue:()I
      52: goto          57
      55: pop
      56: iconst_0
      57: aload_0
      58: invokevirtual #37                 // Method day07/DirectoryTree.getChildren:()Ljava/util/List;
      61: checkcast     #39                 // class java/lang/Iterable
      64: astore_2
      65: istore        11
      67: iconst_0
      68: istore_3
      69: aload_2
      70: astore        4
      72: new           #41                 // class java/util/ArrayList
      75: dup
      76: invokespecial #45                 // Method java/util/ArrayList."<init>":()V
      79: checkcast     #47                 // class java/util/Collection
      82: astore        5
      84: iconst_0
      85: istore        6
      87: aload         4
      89: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      94: astore        7
      96: aload         7
      98: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     103: ifeq          154
     106: aload         7
     108: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     113: astore        8
     115: aload         8
     117: checkcast     #17                 // class day07/DirectoryTree
     120: astore        9
     122: iconst_0
     123: istore        10
     125: aload         9
     127: invokevirtual #64                 // Method day07/DirectoryTree.getSize:()I
     130: ifne          137
     133: iconst_1
     134: goto          138
     137: iconst_0
     138: ifeq          96
     141: aload         5
     143: aload         8
     145: invokeinterface #68,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     150: pop
     151: goto          96
     154: aload         5
     156: checkcast     #70                 // class java/util/List
     159: nop
     160: astore        12
     162: iload         11
     164: aload         12
     166: checkcast     #39                 // class java/lang/Iterable
     169: astore_2
     170: istore        11
     172: iconst_0
     173: istore_3
     174: aload_2
     175: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     180: astore        4
     182: aload         4
     184: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     189: ifeq          231
     192: aload         4
     194: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     199: astore        5
     201: iload_3
     202: aload         5
     204: checkcast     #17                 // class day07/DirectoryTree
     207: astore        6
     209: istore        12
     211: iconst_0
     212: istore        7
     214: aload         6
     216: iload_1
     217: invokestatic  #72                 // Method sumDirectoriesUnderSize:(Lday07/DirectoryTree;I)I
     220: istore        13
     222: iload         12
     224: iload         13
     226: iadd
     227: istore_3
     228: goto          182
     231: iload_3
     232: istore        12
     234: iload         11
     236: iload         12
     238: iadd
     239: ireturn

  public static final int findSmallerDirectoryToDelete(day07.DirectoryTree);
    Code:
       0: aload_0
       1: ldc           #9                  // String tree
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: ldc           #91                 // int 70000000
       8: aload_0
       9: invokevirtual #21                 // Method day07/DirectoryTree.getFullSize:()I
      12: isub
      13: istore_1
      14: ldc           #92                 // int 30000000
      16: iload_1
      17: isub
      18: istore_2
      19: iload_2
      20: ifle          27
      23: iconst_1
      24: goto          28
      27: iconst_0
      28: istore_3
      29: getstatic     #98                 // Field kotlin/_Assertions.ENABLED:Z
      32: ifeq          53
      35: iload_3
      36: ifne          53
      39: ldc           #100                // String Assertion failed
      41: astore        4
      43: new           #102                // class java/lang/AssertionError
      46: dup
      47: aload         4
      49: invokespecial #105                // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
      52: athrow
      53: aload_0
      54: invokevirtual #108                // Method day07/DirectoryTree.getDirectorySizeList:()Ljava/util/List;
      57: checkcast     #39                 // class java/lang/Iterable
      60: invokestatic  #114                // Method kotlin/collections/CollectionsKt.sorted:(Ljava/lang/Iterable;)Ljava/util/List;
      63: checkcast     #39                 // class java/lang/Iterable
      66: astore_3
      67: iconst_0
      68: istore        4
      70: aload_3
      71: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      76: astore        5
      78: aload         5
      80: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      85: ifeq          129
      88: aload         5
      90: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      95: astore        6
      97: aload         6
      99: checkcast     #29                 // class java/lang/Number
     102: invokevirtual #32                 // Method java/lang/Number.intValue:()I
     105: istore        7
     107: iconst_0
     108: istore        8
     110: iload         7
     112: iload_2
     113: if_icmplt     120
     116: iconst_1
     117: goto          121
     120: iconst_0
     121: ifeq          78
     124: aload         6
     126: goto          139
     129: new           #116                // class java/util/NoSuchElementException
     132: dup
     133: ldc           #118                // String Collection contains no element matching the predicate.
     135: invokespecial #121                // Method java/util/NoSuchElementException."<init>":(Ljava/lang/String;)V
     138: athrow
     139: checkcast     #29                 // class java/lang/Number
     142: invokevirtual #32                 // Method java/lang/Number.intValue:()I
     145: ireturn

  public static final day07.DirectoryTree addToTreeAtNode(day07.DirectoryTree, java.util.List<java.lang.String>, int, java.lang.String);
    Code:
       0: aload_0
       1: ldc           #9                  // String tree
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #132                // String levels
       9: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_3
      13: ldc           #134                // String name
      15: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_1
      19: invokeinterface #137,  1          // InterfaceMethod java/util/List.isEmpty:()Z
      24: ifeq          60
      27: aload_0
      28: aconst_null
      29: iconst_0
      30: aload_0
      31: invokevirtual #37                 // Method day07/DirectoryTree.getChildren:()Ljava/util/List;
      34: checkcast     #47                 // class java/util/Collection
      37: new           #17                 // class day07/DirectoryTree
      40: dup
      41: aload_3
      42: iload_2
      43: aconst_null
      44: iconst_4
      45: aconst_null
      46: invokespecial #140                // Method day07/DirectoryTree."<init>":(Ljava/lang/String;ILjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      49: invokestatic  #144                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
      52: iconst_3
      53: aconst_null
      54: invokestatic  #148                // Method day07/DirectoryTree.copy$default:(Lday07/DirectoryTree;Ljava/lang/String;ILjava/util/List;ILjava/lang/Object;)Lday07/DirectoryTree;
      57: goto          306
      60: aload_1
      61: invokestatic  #152                // Method kotlin/collections/CollectionsKt.first:(Ljava/util/List;)Ljava/lang/Object;
      64: checkcast     #154                // class java/lang/String
      67: astore        4
      69: aload_0
      70: invokevirtual #37                 // Method day07/DirectoryTree.getChildren:()Ljava/util/List;
      73: checkcast     #39                 // class java/lang/Iterable
      76: astore        6
      78: iconst_0
      79: istore        7
      81: aload         6
      83: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      88: astore        8
      90: aload         8
      92: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      97: ifeq          137
     100: aload         8
     102: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     107: astore        9
     109: aload         9
     111: checkcast     #17                 // class day07/DirectoryTree
     114: astore        10
     116: iconst_0
     117: istore        11
     119: aload         10
     121: invokevirtual #158                // Method day07/DirectoryTree.getName:()Ljava/lang/String;
     124: aload         4
     126: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     129: ifeq          90
     132: aload         9
     134: goto          147
     137: new           #116                // class java/util/NoSuchElementException
     140: dup
     141: ldc           #118                // String Collection contains no element matching the predicate.
     143: invokespecial #121                // Method java/util/NoSuchElementException."<init>":(Ljava/lang/String;)V
     146: athrow
     147: checkcast     #17                 // class day07/DirectoryTree
     150: astore        5
     152: aload_0
     153: aconst_null
     154: iconst_0
     155: aload_0
     156: invokevirtual #37                 // Method day07/DirectoryTree.getChildren:()Ljava/util/List;
     159: checkcast     #39                 // class java/lang/Iterable
     162: astore        6
     164: istore        17
     166: astore        16
     168: astore        15
     170: iconst_0
     171: istore        7
     173: aload         6
     175: astore        8
     177: new           #41                 // class java/util/ArrayList
     180: dup
     181: invokespecial #45                 // Method java/util/ArrayList."<init>":()V
     184: checkcast     #47                 // class java/util/Collection
     187: astore        9
     189: iconst_0
     190: istore        10
     192: aload         8
     194: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     199: astore        11
     201: aload         11
     203: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     208: ifeq          264
     211: aload         11
     213: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     218: astore        12
     220: aload         12
     222: checkcast     #17                 // class day07/DirectoryTree
     225: astore        13
     227: iconst_0
     228: istore        14
     230: aload         13
     232: invokevirtual #158                // Method day07/DirectoryTree.getName:()Ljava/lang/String;
     235: aload         4
     237: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     240: ifne          247
     243: iconst_1
     244: goto          248
     247: iconst_0
     248: ifeq          201
     251: aload         9
     253: aload         12
     255: invokeinterface #68,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     260: pop
     261: goto          201
     264: aload         9
     266: checkcast     #70                 // class java/util/List
     269: nop
     270: astore        18
     272: aload         15
     274: aload         16
     276: iload         17
     278: aload         18
     280: checkcast     #47                 // class java/util/Collection
     283: aload         5
     285: aload_1
     286: checkcast     #39                 // class java/lang/Iterable
     289: iconst_1
     290: invokestatic  #166                // Method kotlin/collections/CollectionsKt.drop:(Ljava/lang/Iterable;I)Ljava/util/List;
     293: iload_2
     294: aload_3
     295: invokestatic  #168                // Method addToTreeAtNode:(Lday07/DirectoryTree;Ljava/util/List;ILjava/lang/String;)Lday07/DirectoryTree;
     298: invokestatic  #144                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
     301: iconst_3
     302: aconst_null
     303: invokestatic  #148                // Method day07/DirectoryTree.copy$default:(Lday07/DirectoryTree;Ljava/lang/String;ILjava/util/List;ILjava/lang/Object;)Lday07/DirectoryTree;
     306: areturn

  public static final day07.DirectoryTree parseFileAndBuildTree();
    Code:
       0: new           #179                // class java/io/File
       3: dup
       4: ldc           #181                // String src/main/kotlin/day07/input.txt
       6: invokespecial #182                // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #188                // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      15: checkcast     #39                 // class java/lang/Iterable
      18: astore_0
      19: new           #190                // class kotlin/Pair
      22: dup
      23: invokestatic  #193                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      26: new           #17                 // class day07/DirectoryTree
      29: dup
      30: ldc           #195                // String /
      32: iconst_0
      33: aconst_null
      34: bipush        6
      36: aconst_null
      37: invokespecial #140                // Method day07/DirectoryTree."<init>":(Ljava/lang/String;ILjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      40: invokespecial #198                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      43: astore_1
      44: iconst_0
      45: istore_2
      46: aload_1
      47: astore_3
      48: aload_0
      49: invokeinterface #51,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      54: astore        4
      56: aload         4
      58: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      63: ifeq          344
      66: aload         4
      68: invokeinterface #61,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      73: astore        5
      75: aload_3
      76: aload         5
      78: checkcast     #154                // class java/lang/String
      81: astore        6
      83: astore        7
      85: iconst_0
      86: istore        8
      88: aload         6
      90: ldc           #200                // String $
      92: iconst_0
      93: iconst_2
      94: aconst_null
      95: invokestatic  #206                // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
      98: ifeq          233
     101: new           #208                // class kotlin/text/Regex
     104: dup
     105: ldc           #210                // String cd ([.a-z]+)
     107: invokespecial #211                // Method kotlin/text/Regex."<init>":(Ljava/lang/String;)V
     110: aload         6
     112: checkcast     #213                // class java/lang/CharSequence
     115: iconst_0
     116: iconst_2
     117: aconst_null
     118: invokestatic  #217                // Method kotlin/text/Regex.find$default:(Lkotlin/text/Regex;Ljava/lang/CharSequence;IILjava/lang/Object;)Lkotlin/text/MatchResult;
     121: astore        9
     123: aload         9
     125: ifnull        228
     128: aload         9
     130: invokeinterface #222,  1          // InterfaceMethod kotlin/text/MatchResult.getGroupValues:()Ljava/util/List;
     135: astore        10
     137: aload         10
     139: ifnull        228
     142: aload         10
     144: astore        11
     146: iconst_0
     147: istore        12
     149: aload         11
     151: iconst_1
     152: invokeinterface #226,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     157: ldc           #228                // String ..
     159: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     162: ifeq          192
     165: new           #190                // class kotlin/Pair
     168: dup
     169: aload         7
     171: invokevirtual #231                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     174: checkcast     #70                 // class java/util/List
     177: iconst_1
     178: invokestatic  #235                // Method kotlin/collections/CollectionsKt.dropLast:(Ljava/util/List;I)Ljava/util/List;
     181: aload         7
     183: invokevirtual #238                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     186: invokespecial #198                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     189: goto          223
     192: new           #190                // class kotlin/Pair
     195: dup
     196: aload         7
     198: invokevirtual #231                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     201: checkcast     #47                 // class java/util/Collection
     204: aload         11
     206: iconst_1
     207: invokeinterface #226,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     212: invokestatic  #144                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Object;)Ljava/util/List;
     215: aload         7
     217: invokevirtual #238                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     220: invokespecial #198                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     223: nop
     224: nop
     225: goto          339
     228: aload         7
     230: goto          339
     233: aload         6
     235: checkcast     #213                // class java/lang/CharSequence
     238: iconst_1
     239: newarray       char
     241: astore        10
     243: aload         10
     245: iconst_0
     246: bipush        32
     248: castore
     249: aload         10
     251: iconst_0
     252: iconst_0
     253: bipush        6
     255: aconst_null
     256: invokestatic  #242                // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[CZIILjava/lang/Object;)Ljava/util/List;
     259: astore        9
     261: aload         9
     263: iconst_0
     264: invokeinterface #226,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     269: checkcast     #154                // class java/lang/String
     272: astore        10
     274: aload         9
     276: iconst_1
     277: invokeinterface #226,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     282: checkcast     #154                // class java/lang/String
     285: astore        13
     287: new           #190                // class kotlin/Pair
     290: dup
     291: aload         7
     293: invokevirtual #231                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     296: aload         7
     298: invokevirtual #238                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     301: checkcast     #17                 // class day07/DirectoryTree
     304: aload         7
     306: invokevirtual #231                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     309: checkcast     #70                 // class java/util/List
     312: aload         10
     314: ldc           #244                // String dir
     316: invokestatic  #162                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
     319: ifeq          326
     322: iconst_0
     323: goto          331
     326: aload         10
     328: invokestatic  #248                // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     331: aload         13
     333: invokestatic  #168                // Method addToTreeAtNode:(Lday07/DirectoryTree;Ljava/util/List;ILjava/lang/String;)Lday07/DirectoryTree;
     336: invokespecial #198                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     339: nop
     340: astore_3
     341: goto          56
     344: aload_3
     345: invokevirtual #238                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     348: checkcast     #17                 // class day07/DirectoryTree
     351: areturn

  public static final void main();
    Code:
       0: iconst_0
       1: istore_2
       2: invokestatic  #265                // Method java/lang/System.currentTimeMillis:()J
       5: lstore_3
       6: iconst_0
       7: istore        5
       9: invokestatic  #267                // Method parseFileAndBuildTree:()Lday07/DirectoryTree;
      12: astore        6
      14: new           #269                // class java/lang/StringBuilder
      17: dup
      18: invokespecial #270                // Method java/lang/StringBuilder."<init>":()V
      21: ldc_w         #272                // String The sum of the directory which size is under 100000 is
      24: invokevirtual #276                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: aload         6
      29: ldc_w         #277                // int 100000
      32: invokestatic  #72                 // Method sumDirectoriesUnderSize:(Lday07/DirectoryTree;I)I
      35: invokevirtual #280                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      38: invokevirtual #283                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      41: getstatic     #287                // Field java/lang/System.out:Ljava/io/PrintStream;
      44: swap
      45: invokevirtual #292                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      48: new           #269                // class java/lang/StringBuilder
      51: dup
      52: invokespecial #270                // Method java/lang/StringBuilder."<init>":()V
      55: ldc_w         #294                // String The size of the smallest directory to delete is
      58: invokevirtual #276                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      61: aload         6
      63: invokestatic  #296                // Method findSmallerDirectoryToDelete:(Lday07/DirectoryTree;)I
      66: invokevirtual #280                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      69: invokevirtual #283                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      72: getstatic     #287                // Field java/lang/System.out:Ljava/io/PrintStream;
      75: swap
      76: invokevirtual #292                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      79: nop
      80: nop
      81: invokestatic  #265                // Method java/lang/System.currentTimeMillis:()J
      84: lload_3
      85: lsub
      86: lstore_0
      87: new           #269                // class java/lang/StringBuilder
      90: dup
      91: invokespecial #270                // Method java/lang/StringBuilder."<init>":()V
      94: ldc_w         #298                // String The whole thing needed
      97: invokevirtual #276                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     100: lload_0
     101: invokevirtual #301                // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
     104: ldc_w         #303                // String  to finish
     107: invokevirtual #276                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     110: invokevirtual #283                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     113: getstatic     #287                // Field java/lang/System.out:Ljava/io/PrintStream;
     116: swap
     117: invokevirtual #292                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     120: return

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


package day09

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

data class Position(
    val x: Int = 0,
    val y: Int = 0
) {

    fun doAStep(direction: Direction): Position {
        return when (direction) {
            Direction.UP -> this.copy(y = y+1)
            Direction.DOWN -> this.copy(y = y-1)
            Direction.LEFT -> this.copy(x = x-1)
            Direction.RIGHT -> this.copy(x = x+1)
        }
    }

    fun follow(position: Position): Position =
        if ( abs(x - position.x) <= 1 && abs(y - position.y) <= 1) this
        else if ( y == position.y) this.copy(x = x + if (position.x > x) 1 else -1)
        else if ( x == position.x) this.copy(y = y + if (position.y > y) 1 else -1)
        else this.copy(x = x + if (position.x > x) 1 else -1, y = y + if (position.y > y) 1 else -1)
}

class Rope(
    length: Int = 0,
    nodes: List<Position> = emptyList()
) {
    private val nodes = nodes.ifEmpty { List(length) { Position() } }

    private fun updateRecursive(headPosition: Position, nodes: List<Position>): List<Position> {
        return if(nodes.isEmpty()) emptyList()
        else {
            val newHead = nodes.first().follow(headPosition)
            listOf(newHead) + updateRecursive(newHead, nodes.subList(1, nodes.size))
        }
    }

    fun doAStep(direction: Direction): Rope {
        val newHead = nodes.first().doAStep(direction)
        return Rope(
            nodes = listOf(newHead) + updateRecursive(newHead, nodes.subList(1, nodes.size))
        )
    }

    fun getTailPosition() = nodes.last()

}

enum class Direction {
    UP,
    DOWN,
    LEFT,
    RIGHT;
    companion object {
        fun from(s: String): Direction {
            return when (s) {
                "U" -> UP
                "D" -> DOWN
                "L" -> LEFT
                "R" -> RIGHT
                else -> throw Exception()
            }
        }
    }
}

fun parseTailMovementAndCountPositions(size: Int) =
    File("src/main/kotlin/day09/input.txt")
        .readLines()
        .fold(Pair(Rope(size), setOf(Position()))) { acc, line ->
            val (d, amount) = line.split(" ")
            val direction = Direction.from(d)
            (0 until amount.toInt()).fold(acc) { innerAcc, _ ->
                val newRope = innerAcc.first.doAStep(direction)
                Pair(
                    newRope,
                    innerAcc.second + newRope.getTailPosition()
                )
            }
        }.second.size

fun main() {
    println("The number of positions the short rope visited at least once is: ${parseTailMovementAndCountPositions(2)}")
    println("The number of positions the long rope visited at least once is: ${parseTailMovementAndCountPositions(10)}")
}

Compiled from "Solution.kt"
public final class day09.SolutionKt {
  public static final int parseTailMovementAndCountPositions(int);
    Code:
       0: new           #8                  // class java/io/File
       3: dup
       4: ldc           #10                 // String src/main/kotlin/day09/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: checkcast     #22                 // class java/lang/Iterable
      18: astore_1
      19: new           #24                 // class kotlin/Pair
      22: dup
      23: new           #26                 // class day09/Rope
      26: dup
      27: iload_0
      28: aconst_null
      29: iconst_2
      30: aconst_null
      31: invokespecial #29                 // Method day09/Rope."<init>":(ILjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      34: new           #31                 // class day09/Position
      37: dup
      38: iconst_0
      39: iconst_0
      40: iconst_3
      41: aconst_null
      42: invokespecial #34                 // Method day09/Position."<init>":(IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
      45: invokestatic  #40                 // Method kotlin/collections/SetsKt.setOf:(Ljava/lang/Object;)Ljava/util/Set;
      48: invokespecial #43                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      51: astore_2
      52: iconst_0
      53: istore_3
      54: aload_2
      55: astore        4
      57: aload_1
      58: invokeinterface #47,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      63: astore        5
      65: aload         5
      67: invokeinterface #53,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      72: ifeq          274
      75: aload         5
      77: invokeinterface #57,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      82: astore        6
      84: aload         4
      86: aload         6
      88: checkcast     #59                 // class java/lang/String
      91: astore        7
      93: astore        8
      95: iconst_0
      96: istore        9
      98: aload         7
     100: checkcast     #61                 // class java/lang/CharSequence
     103: iconst_1
     104: anewarray     #59                 // class java/lang/String
     107: astore        10
     109: aload         10
     111: iconst_0
     112: ldc           #63                 // String
     114: aastore
     115: aload         10
     117: iconst_0
     118: iconst_0
     119: bipush        6
     121: aconst_null
     122: invokestatic  #69                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
     125: astore        11
     127: aload         11
     129: iconst_0
     130: invokeinterface #75,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     135: checkcast     #59                 // class java/lang/String
     138: astore        10
     140: aload         11
     142: iconst_1
     143: invokeinterface #75,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     148: checkcast     #59                 // class java/lang/String
     151: astore        12
     153: getstatic     #81                 // Field day09/Direction.Companion:Lday09/Direction$Companion;
     156: aload         10
     158: invokevirtual #87                 // Method day09/Direction$Companion.from:(Ljava/lang/String;)Lday09/Direction;
     161: astore        13
     163: iconst_0
     164: aload         12
     166: invokestatic  #93                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
     169: invokestatic  #99                 // Method kotlin/ranges/RangesKt.until:(II)Lkotlin/ranges/IntRange;
     172: checkcast     #22                 // class java/lang/Iterable
     175: astore        14
     177: iconst_0
     178: istore        15
     180: aload         8
     182: astore        16
     184: aload         14
     186: invokeinterface #47,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     191: astore        17
     193: aload         17
     195: invokeinterface #53,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     200: ifeq          266
     203: aload         17
     205: checkcast     #101                // class kotlin/collections/IntIterator
     208: invokevirtual #105                // Method kotlin/collections/IntIterator.nextInt:()I
     211: istore        18
     213: aload         16
     215: astore        19
     217: iconst_0
     218: istore        20
     220: aload         19
     222: invokevirtual #108                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     225: checkcast     #26                 // class day09/Rope
     228: aload         13
     230: invokevirtual #112                // Method day09/Rope.doAStep:(Lday09/Direction;)Lday09/Rope;
     233: astore        21
     235: new           #24                 // class kotlin/Pair
     238: dup
     239: aload         21
     241: aload         19
     243: invokevirtual #115                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     246: checkcast     #117                // class java/util/Set
     249: aload         21
     251: invokevirtual #121                // Method day09/Rope.getTailPosition:()Lday09/Position;
     254: invokestatic  #125                // Method kotlin/collections/SetsKt.plus:(Ljava/util/Set;Ljava/lang/Object;)Ljava/util/Set;
     257: invokespecial #43                 // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     260: nop
     261: astore        16
     263: goto          193
     266: aload         16
     268: nop
     269: astore        4
     271: goto          65
     274: aload         4
     276: invokevirtual #115                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     279: checkcast     #117                // class java/util/Set
     282: invokeinterface #128,  1          // InterfaceMethod java/util/Set.size:()I
     287: ireturn

  public static final void main();
    Code:
       0: new           #153                // class java/lang/StringBuilder
       3: dup
       4: invokespecial #155                // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #157                // String The number of positions the short rope visited at least once is:
       9: invokevirtual #161                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: iconst_2
      13: invokestatic  #163                // Method parseTailMovementAndCountPositions:(I)I
      16: invokevirtual #166                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      19: invokevirtual #170                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: getstatic     #176                // Field java/lang/System.out:Ljava/io/PrintStream;
      25: swap
      26: invokevirtual #182                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      29: new           #153                // class java/lang/StringBuilder
      32: dup
      33: invokespecial #155                // Method java/lang/StringBuilder."<init>":()V
      36: ldc           #184                // String The number of positions the long rope visited at least once is:
      38: invokevirtual #161                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      41: bipush        10
      43: invokestatic  #163                // Method parseTailMovementAndCountPositions:(I)I
      46: invokevirtual #166                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      49: invokevirtual #170                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      52: getstatic     #176                // Field java/lang/System.out:Ljava/io/PrintStream;
      55: swap
      56: invokevirtual #182                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      59: return

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


package day12

import java.io.File

fun Char.distance(other: Char) =
    if (this == 'E') other - 'z'
    else if (this == 'S') other - 'a'
    else if (other == 'E') 'z' - this
    else if (other == 'S') 'a' - this
    else other - this

data class DijkstraParams(
    val dist: MutableMap<Pair<Int, Int>, Distance> = mutableMapOf(),
    val prev: MutableMap<Pair<Int, Int>, Pair<Int, Int>?> = mutableMapOf(),
    val queue: MutableList<Pair<Int, Int>> = mutableListOf()
)

data class Distance(
    val distance: Int = Int.MAX_VALUE
) {

    operator fun plus(cost: Int): Distance =
        if(distance == Int.MAX_VALUE) throw Exception("Cannot sum to infinity")
        else Distance(distance + cost)

    fun isLess(other: Distance) = distance < other.distance

}

data class Node(
    val height: Char,
    val links: Map<Pair<Int, Int>, Int>
) {

    fun distance(node: Node) = height.distance(node.height)

}

data class Graph(
    val nodes: Map<Pair<Int, Int>, Node> = emptyMap(),
    val start: Pair<Int, Int> = Pair(0, 0),
    val end: Pair<Int, Int> = Pair(0, 0)
) {

    fun addNode(x: Int, y: Int, value: Char, vararg links: Triple<Int, Int, Char>?): Graph {
        val newNode = Node(
            when (value) { 'S' -> 'a' 'E' -> 'z' else -> value},
            links
                .filterNotNull()
                .fold(emptyMap()) { acc, it -> acc + (Pair(it.first, it.second) to 1)}
        )
        return when(value) {
            'S' -> this.copy(nodes = nodes + (Pair(x,y) to newNode), start = Pair(x, y))
            'E' -> this.copy(nodes = nodes + (Pair(x,y) to newNode), end = Pair(x, y))
            else -> this.copy(nodes = nodes + (Pair(x,y) to newNode))
        }
    }

    private tailrec fun stepsToStart(end: Pair<Int, Int>, nodes: Map<Pair<Int, Int>, Pair<Int, Int>?>, acc: Int = 0): Int =
        if(nodes[end] != null) stepsToStart(nodes[end]!!, nodes, acc+1)
        else acc

    fun findShortestPathWithDijkstra(): Int {
        val params = DijkstraParams()
        nodes.keys.onEach {
            params.dist[it] = Distance(if (it == start) 0 else Int.MAX_VALUE)
            params.prev[it] = null
            params.queue.add(it)
        }
        while(params.queue.contains(end)) {
            val minVertex = params.dist.filter { params.queue.contains(it.key) }.minBy { it.value.distance }.key
            nodes[minVertex]!!.links.filter { nodes[minVertex]!!.distance(nodes[it.key]!!) <= 1 }.entries.onEach {
                if (params.queue.contains(it.key)) {
                    val newDist = params.dist[minVertex]!! + it.value
                    if (newDist.isLess(params.dist[it.key]!!)) {
                        params.dist[it.key] = newDist
                        params.prev[it.key] = minVertex
                    }
                }
            }
            params.queue.remove(minVertex)
        }
        return stepsToStart(end, params.prev)
    }

    fun findShortestPathWithBFS(): Int {
        val queue = mutableListOf(Pair(end,0))
        val explored = mutableSetOf(end)
        var current = queue.first()
        while(queue.isNotEmpty() && nodes[queue.first().first]!!.height != 'a') {
            current = queue.first()
            val validLinks = nodes[current.first]!!.links.keys
                .filter { !explored.contains(it) && nodes[it]!!.distance(nodes[current.first]!!) <= 1 }
            queue.addAll(validLinks.map { Pair(it, current.second+1) })
            explored.addAll(validLinks)
            queue.removeAt(0)
        }
        return current.second
    }

}

fun parseInputFile() =
    File("src/main/kotlin/day12/input.txt")
        .readLines()
        .fold(emptyList<List<Char>>()) { acc, it ->
            acc + listOf(it.toCharArray().toList())
        }

fun getGraph() =
    parseInputFile()
        .let { rows ->
            (rows.indices).fold(Graph()) { acc, r ->
                (rows[r].indices).fold(acc) { graph, c ->
                    graph.addNode(
                        r, c, rows[r][c],
                        if (r == 0) null else Triple(r-1, c, rows[r-1][c]),
                        if (c == 0) null else Triple(r, c-1, rows[r][c-1]),
                        if (r == rows.size-1) null else Triple(r+1, c, rows[r+1][c]),
                        if (c == rows[r].size-1) null else Triple(r, c+1, rows[r][c+1])
                    )
                }
            }
        }

fun main() {
    println("The shortest path is made up of ${getGraph().findShortestPathWithDijkstra()} steps")
    println("The shortest hiking path is made up of ${getGraph().findShortestPathWithBFS()} steps")
}

Compiled from "Solution.kt"
public final class day12.SolutionKt {
  public static final int distance(char, char);
    Code:
       0: iload_0
       1: bipush        69
       3: if_icmpne     13
       6: iload_1
       7: bipush        122
       9: isub
      10: goto          55
      13: iload_0
      14: bipush        83
      16: if_icmpne     26
      19: iload_1
      20: bipush        97
      22: isub
      23: goto          55
      26: iload_1
      27: bipush        69
      29: if_icmpne     39
      32: bipush        122
      34: iload_0
      35: isub
      36: goto          55
      39: iload_1
      40: bipush        83
      42: if_icmpne     52
      45: bipush        97
      47: iload_0
      48: isub
      49: goto          55
      52: iload_1
      53: iload_0
      54: isub
      55: ireturn

  public static final java.util.List<java.util.List<java.lang.Character>> parseInputFile();
    Code:
       0: new           #15                 // class java/io/File
       3: dup
       4: ldc           #17                 // String src/main/kotlin/day12/input.txt
       6: invokespecial #21                 // Method java/io/File."<init>":(Ljava/lang/String;)V
       9: aconst_null
      10: iconst_1
      11: aconst_null
      12: invokestatic  #27                 // Method kotlin/io/FilesKt.readLines$default:(Ljava/io/File;Ljava/nio/charset/Charset;ILjava/lang/Object;)Ljava/util/List;
      15: checkcast     #29                 // class java/lang/Iterable
      18: astore_0
      19: invokestatic  #34                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      22: astore_1
      23: iconst_0
      24: istore_2
      25: aload_1
      26: astore_3
      27: aload_0
      28: invokeinterface #38,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      33: astore        4
      35: aload         4
      37: invokeinterface #44,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      42: ifeq          99
      45: aload         4
      47: invokeinterface #48,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      52: astore        5
      54: aload_3
      55: aload         5
      57: checkcast     #50                 // class java/lang/String
      60: astore        6
      62: astore        7
      64: iconst_0
      65: istore        8
      67: aload         7
      69: checkcast     #52                 // class java/util/Collection
      72: aload         6
      74: invokevirtual #56                 // Method java/lang/String.toCharArray:()[C
      77: dup
      78: ldc           #58                 // String toCharArray(...)
      80: invokestatic  #64                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      83: invokestatic  #70                 // Method kotlin/collections/ArraysKt.toList:([C)Ljava/util/List;
      86: invokestatic  #74                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      89: checkcast     #29                 // class java/lang/Iterable
      92: invokestatic  #78                 // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
      95: astore_3
      96: goto          35
      99: aload_3
     100: areturn

  public static final day12.Graph getGraph();
    Code:
       0: invokestatic  #97                 // Method parseInputFile:()Ljava/util/List;
       3: astore_0
       4: iconst_0
       5: istore_1
       6: aload_0
       7: checkcast     #52                 // class java/util/Collection
      10: invokestatic  #101                // Method kotlin/collections/CollectionsKt.getIndices:(Ljava/util/Collection;)Lkotlin/ranges/IntRange;
      13: checkcast     #29                 // class java/lang/Iterable
      16: astore_2
      17: new           #103                // class day12/Graph
      20: dup
      21: aconst_null
      22: aconst_null
      23: aconst_null
      24: bipush        7
      26: aconst_null
      27: invokespecial #106                // Method day12/Graph."<init>":(Ljava/util/Map;Lkotlin/Pair;Lkotlin/Pair;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      30: astore_3
      31: iconst_0
      32: istore        4
      34: aload_3
      35: astore        5
      37: aload_2
      38: invokeinterface #38,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      43: astore        6
      45: aload         6
      47: invokeinterface #44,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      52: ifeq          431
      55: aload         6
      57: checkcast     #108                // class kotlin/collections/IntIterator
      60: invokevirtual #112                // Method kotlin/collections/IntIterator.nextInt:()I
      63: istore        7
      65: aload         5
      67: iload         7
      69: istore        8
      71: astore        9
      73: iconst_0
      74: istore        10
      76: aload_0
      77: iload         8
      79: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      84: checkcast     #52                 // class java/util/Collection
      87: invokestatic  #101                // Method kotlin/collections/CollectionsKt.getIndices:(Ljava/util/Collection;)Lkotlin/ranges/IntRange;
      90: checkcast     #29                 // class java/lang/Iterable
      93: astore        11
      95: iconst_0
      96: istore        12
      98: aload         9
     100: astore        13
     102: aload         11
     104: invokeinterface #38,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     109: astore        14
     111: aload         14
     113: invokeinterface #44,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     118: ifeq          423
     121: aload         14
     123: checkcast     #108                // class kotlin/collections/IntIterator
     126: invokevirtual #112                // Method kotlin/collections/IntIterator.nextInt:()I
     129: istore        15
     131: aload         13
     133: iload         15
     135: istore        16
     137: astore        17
     139: iconst_0
     140: istore        18
     142: aload         17
     144: iload         8
     146: iload         16
     148: aload_0
     149: iload         8
     151: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     156: checkcast     #93                 // class java/util/List
     159: iload         16
     161: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     166: checkcast     #118                // class java/lang/Character
     169: invokevirtual #122                // Method java/lang/Character.charValue:()C
     172: iconst_4
     173: anewarray     #124                // class kotlin/Triple
     176: astore        19
     178: aload         19
     180: iconst_0
     181: iload         8
     183: ifne          190
     186: aconst_null
     187: goto          229
     190: new           #124                // class kotlin/Triple
     193: dup
     194: iload         8
     196: iconst_1
     197: isub
     198: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     201: iload         16
     203: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     206: aload_0
     207: iload         8
     209: iconst_1
     210: isub
     211: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     216: checkcast     #93                 // class java/util/List
     219: iload         16
     221: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     226: invokespecial #133                // Method kotlin/Triple."<init>":(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
     229: aastore
     230: aload         19
     232: iconst_1
     233: iload         16
     235: ifne          242
     238: aconst_null
     239: goto          281
     242: new           #124                // class kotlin/Triple
     245: dup
     246: iload         8
     248: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     251: iload         16
     253: iconst_1
     254: isub
     255: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     258: aload_0
     259: iload         8
     261: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     266: checkcast     #93                 // class java/util/List
     269: iload         16
     271: iconst_1
     272: isub
     273: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     278: invokespecial #133                // Method kotlin/Triple."<init>":(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
     281: aastore
     282: aload         19
     284: iconst_2
     285: iload         8
     287: aload_0
     288: invokeinterface #136,  1          // InterfaceMethod java/util/List.size:()I
     293: iconst_1
     294: isub
     295: if_icmpne     302
     298: aconst_null
     299: goto          341
     302: new           #124                // class kotlin/Triple
     305: dup
     306: iload         8
     308: iconst_1
     309: iadd
     310: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     313: iload         16
     315: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     318: aload_0
     319: iload         8
     321: iconst_1
     322: iadd
     323: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     328: checkcast     #93                 // class java/util/List
     331: iload         16
     333: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     338: invokespecial #133                // Method kotlin/Triple."<init>":(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
     341: aastore
     342: aload         19
     344: iconst_3
     345: iload         16
     347: aload_0
     348: iload         8
     350: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     355: checkcast     #93                 // class java/util/List
     358: invokeinterface #136,  1          // InterfaceMethod java/util/List.size:()I
     363: iconst_1
     364: isub
     365: if_icmpne     372
     368: aconst_null
     369: goto          411
     372: new           #124                // class kotlin/Triple
     375: dup
     376: iload         8
     378: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     381: iload         16
     383: iconst_1
     384: iadd
     385: invokestatic  #130                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     388: aload_0
     389: iload         8
     391: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     396: checkcast     #93                 // class java/util/List
     399: iload         16
     401: iconst_1
     402: iadd
     403: invokeinterface #116,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     408: invokespecial #133                // Method kotlin/Triple."<init>":(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
     411: aastore
     412: aload         19
     414: invokevirtual #140                // Method day12/Graph.addNode:(IIC[Lkotlin/Triple;)Lday12/Graph;
     417: nop
     418: astore        13
     420: goto          111
     423: aload         13
     425: nop
     426: astore        5
     428: goto          45
     431: aload         5
     433: nop
     434: nop
     435: areturn

  public static final void main();
    Code:
       0: new           #154                // class java/lang/StringBuilder
       3: dup
       4: invokespecial #156                // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #158                // String The shortest path is made up of
       9: invokevirtual #162                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: invokestatic  #164                // Method getGraph:()Lday12/Graph;
      15: invokevirtual #167                // Method day12/Graph.findShortestPathWithDijkstra:()I
      18: invokevirtual #170                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      21: ldc           #172                // String  steps
      23: invokevirtual #162                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      26: invokevirtual #176                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      29: getstatic     #182                // Field java/lang/System.out:Ljava/io/PrintStream;
      32: swap
      33: invokevirtual #188                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      36: new           #154                // class java/lang/StringBuilder
      39: dup
      40: invokespecial #156                // Method java/lang/StringBuilder."<init>":()V
      43: ldc           #190                // String The shortest hiking path is made up of
      45: invokevirtual #162                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      48: invokestatic  #164                // Method getGraph:()Lday12/Graph;
      51: invokevirtual #193                // Method day12/Graph.findShortestPathWithBFS:()I
      54: invokevirtual #170                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      57: ldc           #172                // String  steps
      59: invokevirtual #162                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      62: invokevirtual #176                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      65: getstatic     #182                // Field java/lang/System.out:Ljava/io/PrintStream;
      68: swap
      69: invokevirtual #188                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      72: return

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