package frc.kyberlib.math

import kotlin.math.pow
import kotlin.math.sqrt

/**
 * Representation and calculator of a polynomial
 */
class Polynomial(
    vararg val coeffs: Double,
    private val variableName: Char = 'x'
) {

    companion object {
        fun regress(args: DoubleArray, outputs: DoubleArray, order: Int = 1): Polynomial {
            var n = order
            val datasetSize = args.size
            val X = DoubleArray(2 * n + 1)
            for (i in 0 until 2 * n + 1) {
                X[i] = 0.0
                for (j in 0 until datasetSize) X[i] =
                    X[i] + args[j].pow(i.toDouble()) //consecutive positions of the array will store N,sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
            }
            val B = Array(n + 1) { DoubleArray(n + 2) }
            val a =
                DoubleArray(n + 1) //B is the Normal matrix(augmented) that will store the equations, 'a' is for value of the final coefficients

            for (i in 0..n) for (j in 0..n) B[i][j] =
                X[i + j] //Build the Normal matrix by storing the corresponding coefficients at the right positions except the last column of the matrix

            val Y =
                DoubleArray(n + 1) //Array to store the values of sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)

            for (i in 0 until n + 1) {
                Y[i] = 0.0
                for (j in 0 until datasetSize) Y[i] =
                    Y[i] + args[j].pow(i.toDouble()) * outputs[j] //consecutive positions will store sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)
            }
            for (i in 0..n) B[i][n + 1] =
                Y[i] //load the values of Y as the last column of B(Normal Matrix but augmented)

            n += 1
            for (i in 0 until n)  //From now Gaussian Elimination starts(can be ignored) to solve the set of linear equations (Pivotisation)
                for (k in i + 1 until n) if (B[i][i] < B[k][i]) for (j in 0..n) {
                    val temp = B[i][j]
                    B[i][j] = B[k][j]
                    B[k][j] = temp
                }

            for (i in 0 until n - 1)  //loop to perform the gauss elimination
                for (k in i + 1 until n) {
                    val t = B[k][i] / B[i][i]
                    for (j in 0..n) B[k][j] =
                        B[k][j] - t * B[i][j] //make the elements below the pivot elements equal to zero or elimnate the variables
                }
            for (i in n - 1 downTo 0)  //back-substitution
            {                        //args is an array whose values correspond to the values of args,outputs,z..
                a[i] = B[i][n] //make the variable to be calculated equal to the rhs of the last equation
                for (j in 0 until n) if (j != i) //then subtract all the lhs values except the coefficient of the variable whose value                                   is being calculated
                    a[i] = a[i] - B[i][j] * a[j]
                a[i] = a[i] / B[i][i] //now finally divide the rhs by the coefficient of the variable to be calculated
            }
            a.reverse()
            return Polynomial(*a)
        }
    }

    val degree = coeffs.size

    /**
     * Solve the polynomial for the given value
     */
    fun eval(x: Double): Double {
        var total = 0.0
        for (i in coeffs.indices) {
            total += coeffs[i] * x.pow(coeffs.size - i - 1)
        }
        return total
    }

    operator fun get(x: Double) = eval(x)

    fun r(data: DoubleArray, actualResults: DoubleArray): Double {
        val n = data.size
        return (n * (data.zip(actualResults).sumOf { it.first * it.second }) - data.sum() * actualResults.sum()) /
                sqrt(n * (data.sumOf { it * it } - data.sum())) / n * (actualResults.sumOf { it * it } - actualResults.sum())
    }

    override fun toString(): String {
        var s = ""
        for (i in coeffs.indices) {
            s += "${coeffs[i]}$variableName^${coeffs.size - i - 1}"
            if (i < coeffs.size - 1 && coeffs[i + 1] >= 0.0) s += "+"
        }
        return s
    }
}

Compiled from "Polynomial.kt"
public final class frc.kyberlib.math.Polynomial {
  public static final frc.kyberlib.math.Polynomial$Companion Companion;

  private final double[] coeffs;

  private final char variableName;

  private final int degree;

  public frc.kyberlib.math.Polynomial(double[], char);
    Code:
       0: aload_1
       1: ldc           #9                  // String coeffs
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokespecial #18                 // Method java/lang/Object."<init>":()V
      10: aload_0
      11: aload_1
      12: putfield      #21                 // Field coeffs:[D
      15: aload_0
      16: iload_2
      17: putfield      #25                 // Field variableName:C
      20: aload_0
      21: aload_0
      22: getfield      #21                 // Field coeffs:[D
      25: arraylength
      26: putfield      #29                 // Field degree:I
      29: return

  public frc.kyberlib.math.Polynomial(double[], char, int, kotlin.jvm.internal.DefaultConstructorMarker);
    Code:
       0: iload_3
       1: iconst_2
       2: iand
       3: ifeq          9
       6: bipush        120
       8: istore_2
       9: aload_0
      10: aload_1
      11: iload_2
      12: invokespecial #34                 // Method "<init>":([DC)V
      15: return

  public final double[] getCoeffs();
    Code:
       0: aload_0
       1: getfield      #21                 // Field coeffs:[D
       4: areturn

  public final int getDegree();
    Code:
       0: aload_0
       1: getfield      #29                 // Field degree:I
       4: ireturn

  public final double eval(double);
    Code:
       0: dconst_0
       1: dstore_3
       2: iconst_0
       3: istore        5
       5: aload_0
       6: getfield      #21                 // Field coeffs:[D
       9: arraylength
      10: istore        6
      12: iload         5
      14: iload         6
      16: if_icmpge     51
      19: dload_3
      20: aload_0
      21: getfield      #21                 // Field coeffs:[D
      24: iload         5
      26: daload
      27: dload_1
      28: aload_0
      29: getfield      #21                 // Field coeffs:[D
      32: arraylength
      33: iload         5
      35: isub
      36: iconst_1
      37: isub
      38: i2d
      39: invokestatic  #46                 // Method java/lang/Math.pow:(DD)D
      42: dmul
      43: dadd
      44: dstore_3
      45: iinc          5, 1
      48: goto          12
      51: dload_3
      52: dreturn

  public final double get(double);
    Code:
       0: aload_0
       1: dload_1
       2: invokevirtual #53                 // Method eval:(D)D
       5: dreturn

  public final double r(double[], double[]);
    Code:
       0: aload_1
       1: ldc           #57                 // String data
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #59                 // String actualResults
       9: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_1
      13: arraylength
      14: istore_3
      15: iload_3
      16: i2d
      17: aload_1
      18: aload_2
      19: invokestatic  #65                 // Method kotlin/collections/ArraysKt.zip:([D[D)Ljava/util/List;
      22: checkcast     #67                 // class java/lang/Iterable
      25: astore        4
      27: dstore        14
      29: dconst_0
      30: dstore        5
      32: aload         4
      34: invokeinterface #71,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      39: astore        7
      41: aload         7
      43: invokeinterface #77,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      48: ifeq          109
      51: aload         7
      53: invokeinterface #81,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      58: astore        8
      60: dload         5
      62: aload         8
      64: checkcast     #83                 // class kotlin/Pair
      67: astore        9
      69: dstore        16
      71: iconst_0
      72: istore        10
      74: aload         9
      76: invokevirtual #86                 // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      79: checkcast     #88                 // class java/lang/Number
      82: invokevirtual #92                 // Method java/lang/Number.doubleValue:()D
      85: aload         9
      87: invokevirtual #95                 // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      90: checkcast     #88                 // class java/lang/Number
      93: invokevirtual #92                 // Method java/lang/Number.doubleValue:()D
      96: dmul
      97: dstore        18
      99: dload         16
     101: dload         18
     103: dadd
     104: dstore        5
     106: goto          41
     109: dload         5
     111: dstore        16
     113: dload         14
     115: dload         16
     117: dmul
     118: aload_1
     119: invokestatic  #99                 // Method kotlin/collections/ArraysKt.sum:([D)D
     122: aload_2
     123: invokestatic  #99                 // Method kotlin/collections/ArraysKt.sum:([D)D
     126: dmul
     127: dsub
     128: iload_3
     129: i2d
     130: aload_1
     131: astore        4
     133: dstore        16
     135: dstore        14
     137: dconst_0
     138: dstore        5
     140: iconst_0
     141: istore        7
     143: aload         4
     145: arraylength
     146: istore        8
     148: iload         7
     150: iload         8
     152: if_icmpge     193
     155: aload         4
     157: iload         7
     159: daload
     160: dstore        9
     162: dload         5
     164: dload         9
     166: dstore        11
     168: dstore        18
     170: iconst_0
     171: istore        13
     173: dload         11
     175: dload         11
     177: dmul
     178: dstore        20
     180: dload         18
     182: dload         20
     184: dadd
     185: dstore        5
     187: iinc          7, 1
     190: goto          148
     193: dload         5
     195: dstore        18
     197: dload         14
     199: dload         16
     201: dload         18
     203: aload_1
     204: invokestatic  #99                 // Method kotlin/collections/ArraysKt.sum:([D)D
     207: dsub
     208: dmul
     209: invokestatic  #102                // Method java/lang/Math.sqrt:(D)D
     212: ddiv
     213: iload_3
     214: i2d
     215: ddiv
     216: aload_2
     217: astore        4
     219: dstore        14
     221: dconst_0
     222: dstore        5
     224: iconst_0
     225: istore        7
     227: aload         4
     229: arraylength
     230: istore        8
     232: iload         7
     234: iload         8
     236: if_icmpge     277
     239: aload         4
     241: iload         7
     243: daload
     244: dstore        9
     246: dload         5
     248: dload         9
     250: dstore        11
     252: dstore        16
     254: iconst_0
     255: istore        13
     257: dload         11
     259: dload         11
     261: dmul
     262: dstore        18
     264: dload         16
     266: dload         18
     268: dadd
     269: dstore        5
     271: iinc          7, 1
     274: goto          232
     277: dload         5
     279: dstore        16
     281: dload         14
     283: dload         16
     285: aload_2
     286: invokestatic  #99                 // Method kotlin/collections/ArraysKt.sum:([D)D
     289: dsub
     290: dmul
     291: dreturn

  public java.lang.String toString();
    Code:
       0: ldc           #113                // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: aload_0
       6: getfield      #21                 // Field coeffs:[D
       9: arraylength
      10: istore_3
      11: iload_2
      12: iload_3
      13: if_icmpge     114
      16: new           #115                // class java/lang/StringBuilder
      19: dup
      20: invokespecial #116                // Method java/lang/StringBuilder."<init>":()V
      23: aload_1
      24: invokevirtual #120                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: aload_0
      28: getfield      #21                 // Field coeffs:[D
      31: iload_2
      32: daload
      33: invokevirtual #123                // Method java/lang/StringBuilder.append:(D)Ljava/lang/StringBuilder;
      36: aload_0
      37: getfield      #25                 // Field variableName:C
      40: invokevirtual #126                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      43: bipush        94
      45: invokevirtual #126                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      48: aload_0
      49: getfield      #21                 // Field coeffs:[D
      52: arraylength
      53: iload_2
      54: isub
      55: iconst_1
      56: isub
      57: invokevirtual #129                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      60: invokevirtual #131                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      63: astore_1
      64: iload_2
      65: aload_0
      66: getfield      #21                 // Field coeffs:[D
      69: arraylength
      70: iconst_1
      71: isub
      72: if_icmpge     108
      75: aload_0
      76: getfield      #21                 // Field coeffs:[D
      79: iload_2
      80: iconst_1
      81: iadd
      82: daload
      83: dconst_0
      84: dcmpl
      85: iflt          108
      88: new           #115                // class java/lang/StringBuilder
      91: dup
      92: invokespecial #116                // Method java/lang/StringBuilder."<init>":()V
      95: aload_1
      96: invokevirtual #120                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      99: bipush        43
     101: invokevirtual #126                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     104: invokevirtual #131                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     107: astore_1
     108: iinc          2, 1
     111: goto          11
     114: aload_1
     115: areturn

  static {};
    Code:
       0: new           #138                // class frc/kyberlib/math/Polynomial$Companion
       3: dup
       4: aconst_null
       5: invokespecial #141                // Method frc/kyberlib/math/Polynomial$Companion."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
       8: putstatic     #145                // Field Companion:Lfrc/kyberlib/math/Polynomial$Companion;
      11: return
}

Compiled from "Polynomial.kt"
public final class frc.kyberlib.math.Polynomial$Companion {
  private frc.kyberlib.math.Polynomial$Companion();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final frc.kyberlib.math.Polynomial regress(double[], double[], int);
    Code:
       0: aload_1
       1: ldc           #15                 // String args
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #23                 // String outputs
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iload_3
      13: istore        4
      15: aload_1
      16: arraylength
      17: istore        5
      19: iconst_2
      20: iload         4
      22: imul
      23: iconst_1
      24: iadd
      25: newarray       double
      27: astore        6
      29: iconst_0
      30: istore        7
      32: iconst_2
      33: iload         4
      35: imul
      36: iconst_1
      37: iadd
      38: istore        8
      40: iload         7
      42: iload         8
      44: if_icmpge     96
      47: aload         6
      49: iload         7
      51: dconst_0
      52: dastore
      53: iconst_0
      54: istore        9
      56: iload         9
      58: iload         5
      60: if_icmpge     90
      63: aload         6
      65: iload         7
      67: aload         6
      69: iload         7
      71: daload
      72: aload_1
      73: iload         9
      75: daload
      76: iload         7
      78: i2d
      79: invokestatic  #29                 // Method java/lang/Math.pow:(DD)D
      82: dadd
      83: dastore
      84: iinc          9, 1
      87: goto          56
      90: iinc          7, 1
      93: goto          40
      96: iconst_0
      97: istore        8
      99: iload         4
     101: iconst_1
     102: iadd
     103: istore        9
     105: iload         9
     107: anewarray     #31                 // class "[D"
     110: astore        10
     112: iload         8
     114: iload         9
     116: if_icmpge     140
     119: iload         8
     121: istore        11
     123: aload         10
     125: iload         11
     127: iload         4
     129: iconst_2
     130: iadd
     131: newarray       double
     133: aastore
     134: iinc          8, 1
     137: goto          112
     140: aload         10
     142: astore        7
     144: iload         4
     146: iconst_1
     147: iadd
     148: newarray       double
     150: astore        8
     152: iconst_0
     153: istore        9
     155: iload         4
     157: istore        10
     159: iload         9
     161: iload         10
     163: if_icmpgt     222
     166: iconst_0
     167: istore        11
     169: iload         4
     171: istore        12
     173: iload         11
     175: iload         12
     177: if_icmpgt     209
     180: aload         7
     182: iload         9
     184: aaload
     185: iload         11
     187: aload         6
     189: iload         9
     191: iload         11
     193: iadd
     194: daload
     195: dastore
     196: iload         11
     198: iload         12
     200: if_icmpeq     209
     203: iinc          11, 1
     206: goto          180
     209: iload         9
     211: iload         10
     213: if_icmpeq     222
     216: iinc          9, 1
     219: goto          166
     222: iload         4
     224: iconst_1
     225: iadd
     226: newarray       double
     228: astore        9
     230: iconst_0
     231: istore        10
     233: iload         4
     235: iconst_1
     236: iadd
     237: istore        11
     239: iload         10
     241: iload         11
     243: if_icmpge     300
     246: aload         9
     248: iload         10
     250: dconst_0
     251: dastore
     252: iconst_0
     253: istore        12
     255: iload         12
     257: iload         5
     259: if_icmpge     294
     262: aload         9
     264: iload         10
     266: aload         9
     268: iload         10
     270: daload
     271: aload_1
     272: iload         12
     274: daload
     275: iload         10
     277: i2d
     278: invokestatic  #29                 // Method java/lang/Math.pow:(DD)D
     281: aload_2
     282: iload         12
     284: daload
     285: dmul
     286: dadd
     287: dastore
     288: iinc          12, 1
     291: goto          255
     294: iinc          10, 1
     297: goto          239
     300: iconst_0
     301: istore        10
     303: iload         4
     305: istore        11
     307: iload         10
     309: iload         11
     311: if_icmpgt     342
     314: aload         7
     316: iload         10
     318: aaload
     319: iload         4
     321: iconst_1
     322: iadd
     323: aload         9
     325: iload         10
     327: daload
     328: dastore
     329: iload         10
     331: iload         11
     333: if_icmpeq     342
     336: iinc          10, 1
     339: goto          314
     342: iinc          4, 1
     345: iconst_0
     346: istore        10
     348: iload         4
     350: istore        11
     352: iload         10
     354: iload         11
     356: if_icmpge     471
     359: iload         10
     361: iconst_1
     362: iadd
     363: istore        12
     365: iload         4
     367: istore        13
     369: iload         12
     371: iload         13
     373: if_icmpge     465
     376: aload         7
     378: iload         10
     380: aaload
     381: iload         10
     383: daload
     384: aload         7
     386: iload         12
     388: aaload
     389: iload         10
     391: daload
     392: dcmpg
     393: ifge          459
     396: iconst_0
     397: istore        14
     399: iload         4
     401: istore        15
     403: iload         14
     405: iload         15
     407: if_icmpgt     459
     410: aload         7
     412: iload         10
     414: aaload
     415: iload         14
     417: daload
     418: dstore        16
     420: aload         7
     422: iload         10
     424: aaload
     425: iload         14
     427: aload         7
     429: iload         12
     431: aaload
     432: iload         14
     434: daload
     435: dastore
     436: aload         7
     438: iload         12
     440: aaload
     441: iload         14
     443: dload         16
     445: dastore
     446: iload         14
     448: iload         15
     450: if_icmpeq     459
     453: iinc          14, 1
     456: goto          410
     459: iinc          12, 1
     462: goto          369
     465: iinc          10, 1
     468: goto          352
     471: iconst_0
     472: istore        10
     474: iload         4
     476: iconst_1
     477: isub
     478: istore        11
     480: iload         10
     482: iload         11
     484: if_icmpge     590
     487: iload         10
     489: iconst_1
     490: iadd
     491: istore        12
     493: iload         4
     495: istore        13
     497: iload         12
     499: iload         13
     501: if_icmpge     584
     504: aload         7
     506: iload         12
     508: aaload
     509: iload         10
     511: daload
     512: aload         7
     514: iload         10
     516: aaload
     517: iload         10
     519: daload
     520: ddiv
     521: dstore        14
     523: iconst_0
     524: istore        16
     526: iload         4
     528: istore        17
     530: iload         16
     532: iload         17
     534: if_icmpgt     578
     537: aload         7
     539: iload         12
     541: aaload
     542: iload         16
     544: aload         7
     546: iload         12
     548: aaload
     549: iload         16
     551: daload
     552: dload         14
     554: aload         7
     556: iload         10
     558: aaload
     559: iload         16
     561: daload
     562: dmul
     563: dsub
     564: dastore
     565: iload         16
     567: iload         17
     569: if_icmpeq     578
     572: iinc          16, 1
     575: goto          537
     578: iinc          12, 1
     581: goto          497
     584: iinc          10, 1
     587: goto          480
     590: iload         4
     592: iconst_1
     593: isub
     594: istore        10
     596: iconst_m1
     597: iload         10
     599: if_icmpge     692
     602: aload         8
     604: iload         10
     606: aload         7
     608: iload         10
     610: aaload
     611: iload         4
     613: daload
     614: dastore
     615: iconst_0
     616: istore        11
     618: iload         4
     620: istore        12
     622: iload         11
     624: iload         12
     626: if_icmpge     667
     629: iload         11
     631: iload         10
     633: if_icmpeq     661
     636: aload         8
     638: iload         10
     640: aload         8
     642: iload         10
     644: daload
     645: aload         7
     647: iload         10
     649: aaload
     650: iload         11
     652: daload
     653: aload         8
     655: iload         11
     657: daload
     658: dmul
     659: dsub
     660: dastore
     661: iinc          11, 1
     664: goto          622
     667: aload         8
     669: iload         10
     671: aload         8
     673: iload         10
     675: daload
     676: aload         7
     678: iload         10
     680: aaload
     681: iload         10
     683: daload
     684: ddiv
     685: dastore
     686: iinc          10, -1
     689: goto          596
     692: aload         8
     694: invokestatic  #37                 // Method kotlin/collections/ArraysKt.reverse:([D)V
     697: new           #39                 // class frc/kyberlib/math/Polynomial
     700: dup
     701: aload         8
     703: aload         8
     705: arraylength
     706: invokestatic  #45                 // Method java/util/Arrays.copyOf:([DI)[D
     709: iconst_0
     710: iconst_2
     711: aconst_null
     712: invokespecial #48                 // Method frc/kyberlib/math/Polynomial."<init>":([DCILkotlin/jvm/internal/DefaultConstructorMarker;)V
     715: areturn

  public static frc.kyberlib.math.Polynomial regress$default(frc.kyberlib.math.Polynomial$Companion, double[], double[], int, int, java.lang.Object);
    Code:
       0: iload         4
       2: iconst_4
       3: iand
       4: ifeq          9
       7: iconst_1
       8: istore_3
       9: aload_0
      10: aload_1
      11: aload_2
      12: iload_3
      13: invokevirtual #68                 // Method regress:([D[DI)Lfrc/kyberlib/math/Polynomial;
      16: areturn

  public frc.kyberlib.math.Polynomial$Companion(kotlin.jvm.internal.DefaultConstructorMarker);
    Code:
       0: aload_0
       1: invokespecial #70                 // Method "<init>":()V
       4: return
}


package structures

/**
 *
 * data structure: directed graph with weights
 *
 * description: made up of vertices connected by edges that have direction and weight
 *
 */

class GraphWithWeights<T> {

    private val data = linkedMapOf<Vertex<T>, MutableList<VertexConnection<T>>>()

    /**
     * adds a new vertex with a value [value]
     */
    fun addVertex(value: T) = data.putIfAbsent(Vertex(value), mutableListOf())

    /**
     * removes a vertex by value [value] from a graph
     */
    fun removeVertex(value: T) {
        val removingVertex = Vertex(value)
        data.values.forEach { list ->
            list.removeIf { it.vertex == removingVertex }
        }
        data.remove(removingVertex)
    }

    /**
     * adds an edge between two vertices, that have values [value1], [value2]
     */
    fun addEdge(value1: T, value2: T, cost: Int) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.add(VertexConnection(vertex2, cost))
    }

    /**
     * removes an edge between two vertices, that have values [value1], [value2]
     */
    fun removeEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.removeIf { it.vertex == vertex2 }
    }

    /**
     * returns the associated vertices and their weights with the given vertex value [value]
     */
    fun connectedVertexesWithWeights(value: T) = data[Vertex(value)] ?: listOf()

    /**
     * implementation of Dijkstra's algorithm, returns pairs of a vertex and the minimum weight needed to get to that vertex (the starting vertex is the first added)
     */
    fun dijkstraAlgorithm(): Map<Vertex<T>, Int> {
        val unvisitedVertexes = linkedMapOf<Vertex<T>, Int>()
        data.keys.forEach { vertex ->
            unvisitedVertexes[vertex] = Int.MAX_VALUE
        }

        val visitedVertexes = linkedMapOf<Vertex<T>, Int>()
        var minimumCost = 0

        var currentVertex = unvisitedVertexes.keys.firstOrNull() ?: return visitedVertexes
        while(unvisitedVertexes.isNotEmpty()) {
            val neighbourVertexConnections = data[currentVertex] ?: emptyList()
            for (neighbourVertexConnection in neighbourVertexConnections) {
                val neighbourVertex = neighbourVertexConnection.vertex
                if (!unvisitedVertexes.contains(neighbourVertex)) continue

                val newCost = minimumCost + neighbourVertexConnection.cost
                val neighbourVertexCost = unvisitedVertexes[neighbourVertex] ?: Int.MAX_VALUE
                if (neighbourVertexCost > newCost) {
                    unvisitedVertexes[neighbourVertex] = newCost
                }
            }
            visitedVertexes[currentVertex] = minimumCost
            unvisitedVertexes.remove(currentVertex)
            val nextUnvisitedEntry = unvisitedVertexes.entries
                .filter { it.value != Int.MAX_VALUE }
                .minByOrNull { it.value } ?: return visitedVertexes
            currentVertex = nextUnvisitedEntry.key
            minimumCost = nextUnvisitedEntry.value
        }
        return visitedVertexes
    }

}

/**
 * helper class for defining graph weights
 */
data class VertexConnection<T>(val vertex: Vertex<T>, val cost: Int)

Compiled from "GraphWithWeights.kt"
public final class structures.GraphWithWeights<T> {
  private final java.util.LinkedHashMap<structures.Vertex<T>, java.util.List<structures.VertexConnection<T>>> data;

  public structures.GraphWithWeights();
    Code:
       0: aload_0
       1: invokespecial #9                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: new           #11                 // class java/util/LinkedHashMap
       8: dup
       9: invokespecial #12                 // Method java/util/LinkedHashMap."<init>":()V
      12: putfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      15: return

  public final java.util.List<structures.VertexConnection<T>> addVertex(T);
    Code:
       0: aload_0
       1: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
       4: new           #24                 // class structures/Vertex
       7: dup
       8: aload_1
       9: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      12: new           #29                 // class java/util/ArrayList
      15: dup
      16: invokespecial #30                 // Method java/util/ArrayList."<init>":()V
      19: checkcast     #32                 // class java/util/List
      22: invokevirtual #36                 // Method java/util/LinkedHashMap.putIfAbsent:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      25: checkcast     #32                 // class java/util/List
      28: areturn

  public final void removeVertex(T);
    Code:
       0: new           #24                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore_2
       9: aload_0
      10: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      13: invokevirtual #44                 // Method java/util/LinkedHashMap.values:()Ljava/util/Collection;
      16: dup
      17: ldc           #46                 // String <get-values>(...)
      19: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      22: checkcast     #54                 // class java/lang/Iterable
      25: astore_3
      26: iconst_0
      27: istore        4
      29: aload_3
      30: invokeinterface #58,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      35: astore        5
      37: aload         5
      39: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      44: ifeq          90
      47: aload         5
      49: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      54: astore        6
      56: aload         6
      58: checkcast     #32                 // class java/util/List
      61: astore        7
      63: iconst_0
      64: istore        8
      66: aload         7
      68: aload_2
      69: invokedynamic #88,  0             // InvokeDynamic #0:invoke:(Lstructures/Vertex;)Lkotlin/jvm/functions/Function1;
      74: invokedynamic #99,  0             // InvokeDynamic #1:test:(Lkotlin/jvm/functions/Function1;)Ljava/util/function/Predicate;
      79: invokeinterface #103,  2          // InterfaceMethod java/util/List.removeIf:(Ljava/util/function/Predicate;)Z
      84: pop
      85: nop
      86: nop
      87: goto          37
      90: nop
      91: aload_0
      92: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      95: aload_2
      96: invokevirtual #106                // Method java/util/LinkedHashMap.remove:(Ljava/lang/Object;)Ljava/lang/Object;
      99: pop
     100: return

  public final void addEdge(T, T, int);
    Code:
       0: new           #24                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore        4
      10: new           #24                 // class structures/Vertex
      13: dup
      14: aload_2
      15: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      18: astore        5
      20: aload_0
      21: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      24: aload         4
      26: invokevirtual #122                // Method java/util/LinkedHashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
      29: checkcast     #32                 // class java/util/List
      32: dup
      33: ifnull        55
      36: new           #124                // class structures/VertexConnection
      39: dup
      40: aload         5
      42: iload_3
      43: invokespecial #127                // Method structures/VertexConnection."<init>":(Lstructures/Vertex;I)V
      46: invokeinterface #130,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      51: pop
      52: goto          56
      55: pop
      56: return

  public final void removeEdge(T, T);
    Code:
       0: new           #24                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore_3
       9: new           #24                 // class structures/Vertex
      12: dup
      13: aload_2
      14: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      17: astore        4
      19: aload_0
      20: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      23: aload_3
      24: invokevirtual #122                // Method java/util/LinkedHashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
      27: checkcast     #32                 // class java/util/List
      30: dup
      31: ifnull        55
      34: aload         4
      36: invokedynamic #143,  0            // InvokeDynamic #2:invoke:(Lstructures/Vertex;)Lkotlin/jvm/functions/Function1;
      41: invokedynamic #148,  0            // InvokeDynamic #3:test:(Lkotlin/jvm/functions/Function1;)Ljava/util/function/Predicate;
      46: invokeinterface #103,  2          // InterfaceMethod java/util/List.removeIf:(Ljava/util/function/Predicate;)Z
      51: pop
      52: goto          56
      55: pop
      56: return

  public final java.util.List<structures.VertexConnection<T>> connectedVertexesWithWeights(T);
    Code:
       0: aload_0
       1: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
       4: new           #24                 // class structures/Vertex
       7: dup
       8: aload_1
       9: invokespecial #27                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      12: invokevirtual #122                // Method java/util/LinkedHashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
      15: checkcast     #32                 // class java/util/List
      18: dup
      19: ifnonnull     26
      22: pop
      23: invokestatic  #156                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      26: areturn

  public final java.util.Map<structures.Vertex<T>, java.lang.Integer> dijkstraAlgorithm();
    Code:
       0: new           #11                 // class java/util/LinkedHashMap
       3: dup
       4: invokespecial #12                 // Method java/util/LinkedHashMap."<init>":()V
       7: astore_1
       8: aload_0
       9: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
      12: invokevirtual #163                // Method java/util/LinkedHashMap.keySet:()Ljava/util/Set;
      15: dup
      16: ldc           #165                // String <get-keys>(...)
      18: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      21: checkcast     #54                 // class java/lang/Iterable
      24: astore_2
      25: iconst_0
      26: istore_3
      27: aload_2
      28: invokeinterface #58,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      33: astore        4
      35: aload         4
      37: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      42: ifeq          86
      45: aload         4
      47: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      52: astore        5
      54: aload         5
      56: checkcast     #24                 // class structures/Vertex
      59: astore        6
      61: iconst_0
      62: istore        7
      64: aload_1
      65: checkcast     #167                // class java/util/Map
      68: aload         6
      70: ldc           #168                // int 2147483647
      72: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      75: invokeinterface #177,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      80: pop
      81: nop
      82: nop
      83: goto          35
      86: nop
      87: new           #11                 // class java/util/LinkedHashMap
      90: dup
      91: invokespecial #12                 // Method java/util/LinkedHashMap."<init>":()V
      94: astore_2
      95: iconst_0
      96: istore_3
      97: aload_1
      98: invokevirtual #163                // Method java/util/LinkedHashMap.keySet:()Ljava/util/Set;
     101: dup
     102: ldc           #165                // String <get-keys>(...)
     104: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     107: checkcast     #54                 // class java/lang/Iterable
     110: invokestatic  #181                // Method kotlin/collections/CollectionsKt.firstOrNull:(Ljava/lang/Iterable;)Ljava/lang/Object;
     113: checkcast     #24                 // class structures/Vertex
     116: dup
     117: ifnonnull     126
     120: pop
     121: aload_2
     122: checkcast     #167                // class java/util/Map
     125: areturn
     126: astore        4
     128: aload_1
     129: checkcast     #167                // class java/util/Map
     132: invokeinterface #184,  1          // InterfaceMethod java/util/Map.isEmpty:()Z
     137: ifne          144
     140: iconst_1
     141: goto          145
     144: iconst_0
     145: ifeq          656
     148: aload_0
     149: getfield      #16                 // Field data:Ljava/util/LinkedHashMap;
     152: aload         4
     154: invokevirtual #122                // Method java/util/LinkedHashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
     157: checkcast     #32                 // class java/util/List
     160: dup
     161: ifnonnull     168
     164: pop
     165: invokestatic  #156                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
     168: astore        5
     170: aload         5
     172: invokeinterface #185,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     177: astore        6
     179: aload         6
     181: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     186: ifeq          286
     189: aload         6
     191: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     196: checkcast     #124                // class structures/VertexConnection
     199: astore        7
     201: aload         7
     203: invokevirtual #189                // Method structures/VertexConnection.getVertex:()Lstructures/Vertex;
     206: astore        8
     208: aload_1
     209: checkcast     #167                // class java/util/Map
     212: aload         8
     214: invokeinterface #192,  2          // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
     219: ifeq          179
     222: iload_3
     223: aload         7
     225: invokevirtual #196                // Method structures/VertexConnection.getCost:()I
     228: iadd
     229: istore        9
     231: aload_1
     232: aload         8
     234: invokevirtual #122                // Method java/util/LinkedHashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
     237: checkcast     #170                // class java/lang/Integer
     240: dup
     241: ifnull        250
     244: invokevirtual #199                // Method java/lang/Integer.intValue:()I
     247: goto          253
     250: pop
     251: ldc           #168                // int 2147483647
     253: istore        10
     255: iload         10
     257: iload         9
     259: if_icmple     179
     262: iload         9
     264: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     267: astore        12
     269: aload_1
     270: checkcast     #167                // class java/util/Map
     273: aload         8
     275: aload         12
     277: invokeinterface #177,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     282: pop
     283: goto          179
     286: iload_3
     287: invokestatic  #174                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     290: astore        7
     292: aload_2
     293: checkcast     #167                // class java/util/Map
     296: aload         4
     298: aload         7
     300: invokeinterface #177,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     305: pop
     306: aload_1
     307: aload         4
     309: invokevirtual #106                // Method java/util/LinkedHashMap.remove:(Ljava/lang/Object;)Ljava/lang/Object;
     312: pop
     313: aload_1
     314: invokevirtual #202                // Method java/util/LinkedHashMap.entrySet:()Ljava/util/Set;
     317: dup
     318: ldc           #204                // String <get-entries>(...)
     320: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     323: checkcast     #54                 // class java/lang/Iterable
     326: astore        8
     328: nop
     329: iconst_0
     330: istore        9
     332: aload         8
     334: astore        10
     336: new           #29                 // class java/util/ArrayList
     339: dup
     340: invokespecial #30                 // Method java/util/ArrayList."<init>":()V
     343: checkcast     #206                // class java/util/Collection
     346: astore        11
     348: iconst_0
     349: istore        12
     351: aload         10
     353: invokeinterface #58,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     358: astore        13
     360: aload         13
     362: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     367: ifeq          440
     370: aload         13
     372: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     377: astore        14
     379: aload         14
     381: checkcast     #208                // class java/util/Map$Entry
     384: astore        15
     386: iconst_0
     387: istore        16
     389: aload         15
     391: invokeinterface #211,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     396: checkcast     #170                // class java/lang/Integer
     399: ldc           #168                // int 2147483647
     401: istore        17
     403: dup
     404: ifnonnull     411
     407: pop
     408: goto          419
     411: invokevirtual #199                // Method java/lang/Integer.intValue:()I
     414: iload         17
     416: if_icmpeq     423
     419: iconst_1
     420: goto          424
     423: iconst_0
     424: ifeq          360
     427: aload         11
     429: aload         14
     431: invokeinterface #212,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     436: pop
     437: goto          360
     440: aload         11
     442: checkcast     #32                 // class java/util/List
     445: nop
     446: checkcast     #54                 // class java/lang/Iterable
     449: astore        8
     451: nop
     452: iconst_0
     453: istore        9
     455: aload         8
     457: invokeinterface #58,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     462: astore        10
     464: aload         10
     466: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     471: ifne          478
     474: aconst_null
     475: goto          600
     478: aload         10
     480: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     485: astore        11
     487: aload         10
     489: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     494: ifne          502
     497: aload         11
     499: goto          600
     502: aload         11
     504: checkcast     #208                // class java/util/Map$Entry
     507: astore        12
     509: iconst_0
     510: istore        13
     512: aload         12
     514: invokeinterface #211,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     519: dup
     520: ldc           #214                // String <get-value>(...)
     522: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     525: checkcast     #216                // class java/lang/Number
     528: invokevirtual #217                // Method java/lang/Number.intValue:()I
     531: istore        12
     533: aload         10
     535: invokeinterface #68,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     540: astore        13
     542: aload         13
     544: checkcast     #208                // class java/util/Map$Entry
     547: astore        14
     549: iconst_0
     550: istore        15
     552: aload         14
     554: invokeinterface #211,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     559: dup
     560: ldc           #214                // String <get-value>(...)
     562: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     565: checkcast     #216                // class java/lang/Number
     568: invokevirtual #217                // Method java/lang/Number.intValue:()I
     571: istore        14
     573: iload         12
     575: iload         14
     577: if_icmple     588
     580: aload         13
     582: astore        11
     584: iload         14
     586: istore        12
     588: aload         10
     590: invokeinterface #64,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     595: ifne          533
     598: aload         11
     600: checkcast     #208                // class java/util/Map$Entry
     603: dup
     604: ifnonnull     613
     607: pop
     608: aload_2
     609: checkcast     #167                // class java/util/Map
     612: areturn
     613: astore        6
     615: aload         6
     617: invokeinterface #220,  1          // InterfaceMethod java/util/Map$Entry.getKey:()Ljava/lang/Object;
     622: dup
     623: ldc           #222                // String <get-key>(...)
     625: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     628: checkcast     #24                 // class structures/Vertex
     631: astore        4
     633: aload         6
     635: invokeinterface #211,  1          // InterfaceMethod java/util/Map$Entry.getValue:()Ljava/lang/Object;
     640: dup
     641: ldc           #214                // String <get-value>(...)
     643: invokestatic  #52                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     646: checkcast     #216                // class java/lang/Number
     649: invokevirtual #217                // Method java/lang/Number.intValue:()I
     652: istore_3
     653: goto          128
     656: aload_2
     657: checkcast     #167                // class java/util/Map
     660: areturn

  private static final boolean removeVertex$lambda$2$lambda$0(structures.Vertex, structures.VertexConnection);
    Code:
       0: aload_1
       1: ldc           #255                // String it
       3: invokestatic  #258                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: invokevirtual #189                // Method structures/VertexConnection.getVertex:()Lstructures/Vertex;
      10: aload_0
      11: invokestatic  #262                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      14: ireturn

  private static final boolean removeVertex$lambda$2$lambda$1(kotlin.jvm.functions.Function1, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: invokeinterface #267,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
       7: checkcast     #269                // class java/lang/Boolean
      10: invokevirtual #272                // Method java/lang/Boolean.booleanValue:()Z
      13: ireturn

  private static final boolean removeEdge$lambda$3(structures.Vertex, structures.VertexConnection);
    Code:
       0: aload_1
       1: ldc           #255                // String it
       3: invokestatic  #258                // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: invokevirtual #189                // Method structures/VertexConnection.getVertex:()Lstructures/Vertex;
      10: aload_0
      11: invokestatic  #262                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      14: ireturn

  private static final boolean removeEdge$lambda$4(kotlin.jvm.functions.Function1, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: invokeinterface #267,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
       7: checkcast     #269                // class java/lang/Boolean
      10: invokevirtual #272                // Method java/lang/Boolean.booleanValue:()Z
      13: ireturn
}


package structures

import java.util.LinkedList
import kotlin.collections.LinkedHashSet

/**
 *
 * data structure: undirected graph without weights
 *
 * description: made up of vertices connected by edges
 *
 */

class Graph<T> {

    private val data = mutableMapOf<Vertex<T>, MutableList<Vertex<T>>>()

    /**
     * adds a new vertex with a value [value]
     */
    fun addVertex(value: T) = data.putIfAbsent(Vertex(value), mutableListOf())

    /**
     * removes a vertex by value [value] from a graph
     */
    fun removeVertex(value: T) {
        val removingVertex = Vertex(value)
        data.values.forEach { list ->
            list.remove(removingVertex)
        }
        data.remove(removingVertex)
    }

    /**
     * adds an edge between two vertices, that have values [value1], [value2]
     */
    fun addEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.add(vertex2)
        data[vertex2]?.add(vertex1)
    }

    /**
     * removes an edge between two vertices, that have values [value1], [value2]
     */
    fun removeEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.remove(vertex2)
        data[vertex2]?.remove(vertex1)
    }

    /**
     * returns the associated vertices with the given vertex value [value]
     */
    fun connectedVertexes(value: T) = data[Vertex(value)] ?: listOf()

    /**
     * traversal of the graph in depth, returns all vertices of the graph
     */
    fun depthFirstTraversal() : List<Vertex<T>> {
        val visited = LinkedHashSet<Vertex<T>>()
        val queue = LinkedList<Vertex<T>>()
        val firstVertex = data.keys.firstOrNull() ?: return emptyList()
        queue.push(firstVertex)
        while (queue.isNotEmpty()) {
            val vertex = queue.poll()
            if (!visited.contains(vertex)) {
                visited.add(vertex)
                queue.addAll(data[vertex] ?: listOf())
            }
        }
        return visited.toList()
    }

    /**
     * traversal of the graph in breadth, returns all vertices of the graph
     */
    fun breadthFirstTraversal() : List<Vertex<T>> {
        val visited = LinkedHashSet<Vertex<T>>()
        val queue = LinkedList<Vertex<T>>()
        val firstVertex = data.keys.firstOrNull() ?: return emptyList()
        queue.add(firstVertex)
        visited.add(firstVertex)
        while (queue.isNotEmpty()) {
            val vertex = queue.poll()
            data[vertex]?.forEach { v ->
                if (!visited.contains(v)) {
                    visited.add(v)
                    queue.add(v)
                }
            }
        }
        return visited.toList()
    }

}

/**
 * graph vertex model
 */
data class Vertex<T>(val value: T)

Compiled from "Graph.kt"
public final class structures.Graph<T> {
  private final java.util.Map<structures.Vertex<T>, java.util.List<structures.Vertex<T>>> data;

  public structures.Graph();
    Code:
       0: aload_0
       1: invokespecial #9                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: new           #11                 // class java/util/LinkedHashMap
       8: dup
       9: invokespecial #12                 // Method java/util/LinkedHashMap."<init>":()V
      12: checkcast     #14                 // class java/util/Map
      15: putfield      #18                 // Field data:Ljava/util/Map;
      18: return

  public final java.util.List<structures.Vertex<T>> addVertex(T);
    Code:
       0: aload_0
       1: getfield      #18                 // Field data:Ljava/util/Map;
       4: new           #26                 // class structures/Vertex
       7: dup
       8: aload_1
       9: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      12: new           #31                 // class java/util/ArrayList
      15: dup
      16: invokespecial #32                 // Method java/util/ArrayList."<init>":()V
      19: checkcast     #34                 // class java/util/List
      22: invokeinterface #38,  3           // InterfaceMethod java/util/Map.putIfAbsent:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
      27: checkcast     #34                 // class java/util/List
      30: areturn

  public final void removeVertex(T);
    Code:
       0: new           #26                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore_2
       9: aload_0
      10: getfield      #18                 // Field data:Ljava/util/Map;
      13: invokeinterface #46,  1           // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
      18: checkcast     #48                 // class java/lang/Iterable
      21: astore_3
      22: iconst_0
      23: istore        4
      25: aload_3
      26: invokeinterface #52,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      31: astore        5
      33: aload         5
      35: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      40: ifeq          76
      43: aload         5
      45: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      50: astore        6
      52: aload         6
      54: checkcast     #34                 // class java/util/List
      57: astore        7
      59: iconst_0
      60: istore        8
      62: aload         7
      64: aload_2
      65: invokeinterface #66,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
      70: pop
      71: nop
      72: nop
      73: goto          33
      76: nop
      77: aload_0
      78: getfield      #18                 // Field data:Ljava/util/Map;
      81: aload_2
      82: invokeinterface #69,  2           // InterfaceMethod java/util/Map.remove:(Ljava/lang/Object;)Ljava/lang/Object;
      87: pop
      88: return

  public final void addEdge(T, T);
    Code:
       0: new           #26                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore_3
       9: new           #26                 // class structures/Vertex
      12: dup
      13: aload_2
      14: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      17: astore        4
      19: aload_0
      20: getfield      #18                 // Field data:Ljava/util/Map;
      23: aload_3
      24: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      29: checkcast     #34                 // class java/util/List
      32: dup
      33: ifnull        47
      36: aload         4
      38: invokeinterface #88,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      43: pop
      44: goto          48
      47: pop
      48: aload_0
      49: getfield      #18                 // Field data:Ljava/util/Map;
      52: aload         4
      54: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      59: checkcast     #34                 // class java/util/List
      62: dup
      63: ifnull        76
      66: aload_3
      67: invokeinterface #88,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      72: pop
      73: goto          77
      76: pop
      77: return

  public final void removeEdge(T, T);
    Code:
       0: new           #26                 // class structures/Vertex
       3: dup
       4: aload_1
       5: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
       8: astore_3
       9: new           #26                 // class structures/Vertex
      12: dup
      13: aload_2
      14: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      17: astore        4
      19: aload_0
      20: getfield      #18                 // Field data:Ljava/util/Map;
      23: aload_3
      24: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      29: checkcast     #34                 // class java/util/List
      32: dup
      33: ifnull        47
      36: aload         4
      38: invokeinterface #66,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
      43: pop
      44: goto          48
      47: pop
      48: aload_0
      49: getfield      #18                 // Field data:Ljava/util/Map;
      52: aload         4
      54: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      59: checkcast     #34                 // class java/util/List
      62: dup
      63: ifnull        76
      66: aload_3
      67: invokeinterface #66,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
      72: pop
      73: goto          77
      76: pop
      77: return

  public final java.util.List<structures.Vertex<T>> connectedVertexes(T);
    Code:
       0: aload_0
       1: getfield      #18                 // Field data:Ljava/util/Map;
       4: new           #26                 // class structures/Vertex
       7: dup
       8: aload_1
       9: invokespecial #29                 // Method structures/Vertex."<init>":(Ljava/lang/Object;)V
      12: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      17: checkcast     #34                 // class java/util/List
      20: dup
      21: ifnonnull     28
      24: pop
      25: invokestatic  #101                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      28: areturn

  public final java.util.List<structures.Vertex<T>> depthFirstTraversal();
    Code:
       0: new           #105                // class java/util/LinkedHashSet
       3: dup
       4: invokespecial #106                // Method java/util/LinkedHashSet."<init>":()V
       7: astore_1
       8: new           #108                // class java/util/LinkedList
      11: dup
      12: invokespecial #109                // Method java/util/LinkedList."<init>":()V
      15: astore_2
      16: aload_0
      17: getfield      #18                 // Field data:Ljava/util/Map;
      20: invokeinterface #113,  1          // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set;
      25: checkcast     #48                 // class java/lang/Iterable
      28: invokestatic  #117                // Method kotlin/collections/CollectionsKt.firstOrNull:(Ljava/lang/Iterable;)Ljava/lang/Object;
      31: checkcast     #26                 // class structures/Vertex
      34: dup
      35: ifnonnull     43
      38: pop
      39: invokestatic  #101                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      42: areturn
      43: astore_3
      44: aload_2
      45: aload_3
      46: invokevirtual #120                // Method java/util/LinkedList.push:(Ljava/lang/Object;)V
      49: aload_2
      50: checkcast     #122                // class java/util/Collection
      53: invokeinterface #125,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      58: ifne          65
      61: iconst_1
      62: goto          66
      65: iconst_0
      66: ifeq          133
      69: aload_2
      70: invokevirtual #128                // Method java/util/LinkedList.poll:()Ljava/lang/Object;
      73: checkcast     #26                 // class structures/Vertex
      76: astore        4
      78: aload_1
      79: aload         4
      81: invokevirtual #131                // Method java/util/LinkedHashSet.contains:(Ljava/lang/Object;)Z
      84: ifne          49
      87: aload_1
      88: aload         4
      90: invokevirtual #132                // Method java/util/LinkedHashSet.add:(Ljava/lang/Object;)Z
      93: pop
      94: aload_2
      95: aload_0
      96: getfield      #18                 // Field data:Ljava/util/Map;
      99: aload         4
     101: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
     106: checkcast     #34                 // class java/util/List
     109: dup
     110: ifnull        119
     113: checkcast     #122                // class java/util/Collection
     116: goto          126
     119: pop
     120: invokestatic  #101                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
     123: checkcast     #122                // class java/util/Collection
     126: invokevirtual #136                // Method java/util/LinkedList.addAll:(Ljava/util/Collection;)Z
     129: pop
     130: goto          49
     133: aload_1
     134: checkcast     #48                 // class java/lang/Iterable
     137: invokestatic  #140                // Method kotlin/collections/CollectionsKt.toList:(Ljava/lang/Iterable;)Ljava/util/List;
     140: areturn

  public final java.util.List<structures.Vertex<T>> breadthFirstTraversal();
    Code:
       0: new           #105                // class java/util/LinkedHashSet
       3: dup
       4: invokespecial #106                // Method java/util/LinkedHashSet."<init>":()V
       7: astore_1
       8: new           #108                // class java/util/LinkedList
      11: dup
      12: invokespecial #109                // Method java/util/LinkedList."<init>":()V
      15: astore_2
      16: aload_0
      17: getfield      #18                 // Field data:Ljava/util/Map;
      20: invokeinterface #113,  1          // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set;
      25: checkcast     #48                 // class java/lang/Iterable
      28: invokestatic  #117                // Method kotlin/collections/CollectionsKt.firstOrNull:(Ljava/lang/Iterable;)Ljava/lang/Object;
      31: checkcast     #26                 // class structures/Vertex
      34: dup
      35: ifnonnull     43
      38: pop
      39: invokestatic  #101                // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      42: areturn
      43: astore_3
      44: aload_2
      45: aload_3
      46: invokevirtual #148                // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
      49: pop
      50: aload_1
      51: aload_3
      52: invokevirtual #132                // Method java/util/LinkedHashSet.add:(Ljava/lang/Object;)Z
      55: pop
      56: aload_2
      57: checkcast     #122                // class java/util/Collection
      60: invokeinterface #125,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      65: ifne          72
      68: iconst_1
      69: goto          73
      72: iconst_0
      73: ifeq          186
      76: aload_2
      77: invokevirtual #128                // Method java/util/LinkedList.poll:()Ljava/lang/Object;
      80: checkcast     #26                 // class structures/Vertex
      83: astore        4
      85: aload_0
      86: getfield      #18                 // Field data:Ljava/util/Map;
      89: aload         4
      91: invokeinterface #85,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
      96: checkcast     #34                 // class java/util/List
      99: dup
     100: ifnull        181
     103: checkcast     #48                 // class java/lang/Iterable
     106: astore        5
     108: iconst_0
     109: istore        6
     111: aload         5
     113: invokeinterface #52,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     118: astore        7
     120: aload         7
     122: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     127: ifeq          177
     130: aload         7
     132: invokeinterface #62,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     137: astore        8
     139: aload         8
     141: checkcast     #26                 // class structures/Vertex
     144: astore        9
     146: iconst_0
     147: istore        10
     149: aload_1
     150: aload         9
     152: invokevirtual #131                // Method java/util/LinkedHashSet.contains:(Ljava/lang/Object;)Z
     155: ifne          172
     158: aload_1
     159: aload         9
     161: invokevirtual #132                // Method java/util/LinkedHashSet.add:(Ljava/lang/Object;)Z
     164: pop
     165: aload_2
     166: aload         9
     168: invokevirtual #148                // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
     171: pop
     172: nop
     173: nop
     174: goto          120
     177: nop
     178: goto          56
     181: pop
     182: nop
     183: goto          56
     186: aload_1
     187: checkcast     #48                 // class java/lang/Iterable
     190: invokestatic  #140                // Method kotlin/collections/CollectionsKt.toList:(Ljava/lang/Iterable;)Ljava/util/List;
     193: areturn
}


package structures

/**
 *
 * data structure: binary tree
 *
 * description: consists of nodes, each of which has a maximum of two children,
 * child nodes satisfy the following requirements:
 *  - the left child is less than the parent;
 *  - right child is larger than parent;
 *
 * average search time: log(n)
 * worst search time: n
 * because the situation is possible when the elements follow each other 1,2,3,4... and the tree takes the following form:
 *  1
 *   \
 *    2
 *     \
 *      3
 *       \
 *        4
 * the same complexity is true for adding and removing nodes
 *
 */

class BinaryTree {

    /**
     * binary tree root
     */
    private var root: Node? = null

    /**
     * adds a new element [value] to the tree
     */
    fun add(value: Int) {
        fun addRec(current: Node?, value: Int) : Node {
            if (current == null) {
                return Node(value)
            }
            if (value < current.value()) {
                current.changeLeft(addRec(current.leftNode(), value))
            } else if (value > current.value()) {
                current.changeRight(addRec(current.rightNode(), value))
            }
            return current
        }

        root = addRec(root, value)
    }

    /**
     * checks the tree for emptiness and returns true if the tree does not contain any nodes
     */
    fun isEmpty() = root == null

    /**
     * removes an element [value] from the tree
     */
    fun remove(value: Int) {
        fun smallestValue(root: Node) : Int {
            return if (root.leftNode() == null) root.value() else smallestValue(root.leftNode()!!)
        }

        fun removeRec(current: Node?, value: Int) : Node? {
            if (current == null) {
                return null
            }

            if (value == current.value()) {
                if (current.leftNode() == null && current.rightNode() == null) {
                    return null
                }
                if (current.leftNode() == null) {
                    return current.rightNode()
                }
                if (current.rightNode() == null) {
                    return current.leftNode()
                }

                val smallestValue = smallestValue(current.rightNode()!!)
                current.changeValue(smallestValue)
                current.changeRight(removeRec(current.rightNode(), smallestValue))
                return current
            }

            if (value < current.value()) {
                current.changeLeft(removeRec(current.leftNode(), value))
            } else {
                current.changeRight(removeRec(current.rightNode(), value))
            }

            return current
        }

        root = removeRec(root, value)
    }

    /**
     * checks for the existence of an element [value] in the tree, returns true if the element exists
     */
    fun contains(value: Int) : Boolean {
        fun containsRec(current: Node?, value: Int) : Boolean {
            if (current == null) {
                return false
            }
            if (value == current.value()) {
                return true
            }
            return if (value < current.value()) {
                containsRec(current.leftNode(), value)
            } else {
                containsRec(current.rightNode(), value)
            }
        }

        return containsRec(root, value)
    }

    /**
     * traversal of the binary tree in depth
     *
     * first the left child, then the parent, then the right child
     *
     * @return returns the elements of the tree
     */
    fun traverseInOrder() : List<Int> {
        fun traverseInOrderRec(node: Node?, nodes: MutableList<Int>) {
            if (node != null) {
                traverseInOrderRec(node.leftNode(), nodes)
                nodes.add(node.value())
                traverseInOrderRec(node.rightNode(), nodes)
            }
        }

        return mutableListOf<Int>().apply {
            traverseInOrderRec(root, this)
        }
    }

    /**
     * traversal of the binary tree in depth
     *
     * parent first, then left and right children
     *
     * @return returns the elements of the tree
     */
    fun traversePreOrder() : List<Int> {
        fun traversePreOrderRec(node: Node?, nodes: MutableList<Int>) {
            if (node != null) {
                nodes.add(node.value())
                traversePreOrderRec(node.leftNode(), nodes)
                traversePreOrderRec(node.rightNode(), nodes)
            }
        }

        return mutableListOf<Int>().apply {
            traversePreOrderRec(root, this)
        }
    }

    /**
     * traversal of the binary tree in depth
     *
     * first the left and right children, then the parent
     *
     * @return returns the elements of the tree
     */
    fun traversePostOrder() : List<Int> {
        fun traversePostOrderRec(node: Node?, nodes: MutableList<Int>) {
            if (node != null) {
                traversePostOrderRec(node.leftNode(), nodes)
                traversePostOrderRec(node.rightNode(), nodes)
                nodes.add(node.value())
            }
        }

        return mutableListOf<Int>().apply {
            traversePostOrderRec(root, this)
        }
    }

    /**
     * traversal of the binary tree in breadth
     *
     * uses an additional data structure - a queue into which new tree
     * nodes are added until the last node is added
     *
     * @return returns the elements of the tree
     */
    fun traverseLevelOrder() : List<Int> {
        val root = this.root ?: return listOf()

        val queue = java.util.LinkedList<Node>()
        queue.add(root)

        val items = mutableListOf<Int>()

        while (queue.isNotEmpty()) {
            val node = queue.remove()
            items.add(node.value())

            node.leftNode()?.let(queue::add)
            node.rightNode()?.let(queue::add)
        }

        return items
    }

}

/**
 * represents a tree node
 *
 * @property value - node value
 * @property left - left child node
 * @property right - right child node
 */
class Node(
    private var value: Int,
    private var left: Node? = null,
    private var right: Node? = null
) {
    /**
     * returns the value of the node
     */
    fun value() = value

    /**
     * changes the value of a node
     */
    fun changeValue(value: Int) {
        this.value = value
    }

    /**
     * changes the left child node
     */
    fun changeLeft(left: Node?) {
        this.left = left
    }

    /**
     * changes the right child node
     */
    fun changeRight(right: Node?) {
        this.right = right
    }

    /**
     * returns the left child node
     */
    fun leftNode() = left

    /**
     * returns the right child node
     */
    fun rightNode() = right
}

Compiled from "BinaryTree.kt"
public final class structures.BinaryTree {
  private structures.Node root;

  public structures.BinaryTree();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final void add(int);
    Code:
       0: aload_0
       1: aload_0
       2: getfield      #16                 // Field root:Lstructures/Node;
       5: iload_1
       6: invokestatic  #20                 // Method add$addRec:(Lstructures/Node;I)Lstructures/Node;
       9: putfield      #16                 // Field root:Lstructures/Node;
      12: return

  public final boolean isEmpty();
    Code:
       0: aload_0
       1: getfield      #16                 // Field root:Lstructures/Node;
       4: ifnonnull     11
       7: iconst_1
       8: goto          12
      11: iconst_0
      12: ireturn

  public final void remove(int);
    Code:
       0: aload_0
       1: aload_0
       2: getfield      #16                 // Field root:Lstructures/Node;
       5: iload_1
       6: invokestatic  #28                 // Method remove$removeRec:(Lstructures/Node;I)Lstructures/Node;
       9: putfield      #16                 // Field root:Lstructures/Node;
      12: return

  public final boolean contains(int);
    Code:
       0: aload_0
       1: getfield      #16                 // Field root:Lstructures/Node;
       4: iload_1
       5: invokestatic  #34                 // Method contains$containsRec:(Lstructures/Node;I)Z
       8: ireturn

  public final java.util.List<java.lang.Integer> traverseInOrder();
    Code:
       0: new           #40                 // class java/util/ArrayList
       3: dup
       4: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
       7: checkcast     #43                 // class java/util/List
      10: astore_1
      11: aload_1
      12: astore_2
      13: iconst_0
      14: istore_3
      15: aload_0
      16: getfield      #16                 // Field root:Lstructures/Node;
      19: aload_2
      20: invokestatic  #47                 // Method traverseInOrder$traverseInOrderRec:(Lstructures/Node;Ljava/util/List;)V
      23: nop
      24: aload_1
      25: areturn

  public final java.util.List<java.lang.Integer> traversePreOrder();
    Code:
       0: new           #40                 // class java/util/ArrayList
       3: dup
       4: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
       7: checkcast     #43                 // class java/util/List
      10: astore_1
      11: aload_1
      12: astore_2
      13: iconst_0
      14: istore_3
      15: aload_0
      16: getfield      #16                 // Field root:Lstructures/Node;
      19: aload_2
      20: invokestatic  #54                 // Method traversePreOrder$traversePreOrderRec:(Lstructures/Node;Ljava/util/List;)V
      23: nop
      24: aload_1
      25: areturn

  public final java.util.List<java.lang.Integer> traversePostOrder();
    Code:
       0: new           #40                 // class java/util/ArrayList
       3: dup
       4: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
       7: checkcast     #43                 // class java/util/List
      10: astore_1
      11: aload_1
      12: astore_2
      13: iconst_0
      14: istore_3
      15: aload_0
      16: getfield      #16                 // Field root:Lstructures/Node;
      19: aload_2
      20: invokestatic  #60                 // Method traversePostOrder$traversePostOrderRec:(Lstructures/Node;Ljava/util/List;)V
      23: nop
      24: aload_1
      25: areturn

  public final java.util.List<java.lang.Integer> traverseLevelOrder();
    Code:
       0: aload_0
       1: getfield      #16                 // Field root:Lstructures/Node;
       4: dup
       5: ifnonnull     13
       8: pop
       9: invokestatic  #68                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      12: areturn
      13: astore_1
      14: new           #70                 // class java/util/LinkedList
      17: dup
      18: invokespecial #71                 // Method java/util/LinkedList."<init>":()V
      21: astore_2
      22: aload_2
      23: aload_1
      24: invokevirtual #74                 // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
      27: pop
      28: new           #40                 // class java/util/ArrayList
      31: dup
      32: invokespecial #41                 // Method java/util/ArrayList."<init>":()V
      35: checkcast     #43                 // class java/util/List
      38: astore_3
      39: aload_2
      40: checkcast     #76                 // class java/util/Collection
      43: invokeinterface #78,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
      48: ifne          55
      51: iconst_1
      52: goto          56
      55: iconst_0
      56: ifeq          138
      59: aload_2
      60: invokevirtual #81                 // Method java/util/LinkedList.remove:()Ljava/lang/Object;
      63: checkcast     #83                 // class structures/Node
      66: astore        4
      68: aload_3
      69: aload         4
      71: invokevirtual #86                 // Method structures/Node.value:()I
      74: invokestatic  #92                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      77: invokeinterface #93,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      82: pop
      83: aload         4
      85: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      88: dup
      89: ifnull        107
      92: astore        5
      94: iconst_0
      95: istore        6
      97: aload_2
      98: aload         5
     100: invokevirtual #74                 // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
     103: pop
     104: goto          109
     107: pop
     108: nop
     109: aload         4
     111: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
     114: dup
     115: ifnull        133
     118: astore        5
     120: iconst_0
     121: istore        6
     123: aload_2
     124: aload         5
     126: invokevirtual #74                 // Method java/util/LinkedList.add:(Ljava/lang/Object;)Z
     129: pop
     130: goto          39
     133: pop
     134: nop
     135: goto          39
     138: aload_3
     139: areturn

  private static final structures.Node add$addRec(structures.Node, int);
    Code:
       0: aload_0
       1: ifnonnull     18
       4: new           #83                 // class structures/Node
       7: dup
       8: iload_1
       9: aconst_null
      10: aconst_null
      11: bipush        6
      13: aconst_null
      14: invokespecial #110                // Method structures/Node."<init>":(ILstructures/Node;Lstructures/Node;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
      17: areturn
      18: iload_1
      19: aload_0
      20: invokevirtual #86                 // Method structures/Node.value:()I
      23: if_icmpge     41
      26: aload_0
      27: aload_0
      28: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      31: iload_1
      32: invokestatic  #20                 // Method add$addRec:(Lstructures/Node;I)Lstructures/Node;
      35: invokevirtual #114                // Method structures/Node.changeLeft:(Lstructures/Node;)V
      38: goto          61
      41: iload_1
      42: aload_0
      43: invokevirtual #86                 // Method structures/Node.value:()I
      46: if_icmple     61
      49: aload_0
      50: aload_0
      51: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      54: iload_1
      55: invokestatic  #20                 // Method add$addRec:(Lstructures/Node;I)Lstructures/Node;
      58: invokevirtual #117                // Method structures/Node.changeRight:(Lstructures/Node;)V
      61: aload_0
      62: areturn

  private static final int remove$smallestValue(structures.Node);
    Code:
       0: aload_0
       1: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
       4: ifnonnull     14
       7: aload_0
       8: invokevirtual #86                 // Method structures/Node.value:()I
      11: goto          25
      14: aload_0
      15: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      18: dup
      19: invokestatic  #126                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      22: invokestatic  #128                // Method remove$smallestValue:(Lstructures/Node;)I
      25: ireturn

  private static final structures.Node remove$removeRec(structures.Node, int);
    Code:
       0: aload_0
       1: ifnonnull     6
       4: aconst_null
       5: areturn
       6: iload_1
       7: aload_0
       8: invokevirtual #86                 // Method structures/Node.value:()I
      11: if_icmpne     85
      14: aload_0
      15: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      18: ifnonnull     30
      21: aload_0
      22: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      25: ifnonnull     30
      28: aconst_null
      29: areturn
      30: aload_0
      31: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      34: ifnonnull     42
      37: aload_0
      38: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      41: areturn
      42: aload_0
      43: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      46: ifnonnull     54
      49: aload_0
      50: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      53: areturn
      54: aload_0
      55: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      58: dup
      59: invokestatic  #126                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      62: invokestatic  #128                // Method remove$smallestValue:(Lstructures/Node;)I
      65: istore_2
      66: aload_0
      67: iload_2
      68: invokevirtual #131                // Method structures/Node.changeValue:(I)V
      71: aload_0
      72: aload_0
      73: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      76: iload_2
      77: invokestatic  #28                 // Method remove$removeRec:(Lstructures/Node;I)Lstructures/Node;
      80: invokevirtual #117                // Method structures/Node.changeRight:(Lstructures/Node;)V
      83: aload_0
      84: areturn
      85: iload_1
      86: aload_0
      87: invokevirtual #86                 // Method structures/Node.value:()I
      90: if_icmpge     108
      93: aload_0
      94: aload_0
      95: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      98: iload_1
      99: invokestatic  #28                 // Method remove$removeRec:(Lstructures/Node;I)Lstructures/Node;
     102: invokevirtual #114                // Method structures/Node.changeLeft:(Lstructures/Node;)V
     105: goto          120
     108: aload_0
     109: aload_0
     110: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
     113: iload_1
     114: invokestatic  #28                 // Method remove$removeRec:(Lstructures/Node;I)Lstructures/Node;
     117: invokevirtual #117                // Method structures/Node.changeRight:(Lstructures/Node;)V
     120: aload_0
     121: areturn

  private static final boolean contains$containsRec(structures.Node, int);
    Code:
       0: aload_0
       1: ifnonnull     6
       4: iconst_0
       5: ireturn
       6: iload_1
       7: aload_0
       8: invokevirtual #86                 // Method structures/Node.value:()I
      11: if_icmpne     16
      14: iconst_1
      15: ireturn
      16: iload_1
      17: aload_0
      18: invokevirtual #86                 // Method structures/Node.value:()I
      21: if_icmpge     35
      24: aload_0
      25: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      28: iload_1
      29: invokestatic  #34                 // Method contains$containsRec:(Lstructures/Node;I)Z
      32: goto          43
      35: aload_0
      36: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      39: iload_1
      40: invokestatic  #34                 // Method contains$containsRec:(Lstructures/Node;I)Z
      43: ireturn

  private static final void traverseInOrder$traverseInOrderRec(structures.Node, java.util.List<java.lang.Integer>);
    Code:
       0: aload_0
       1: ifnull        34
       4: aload_0
       5: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
       8: aload_1
       9: invokestatic  #47                 // Method traverseInOrder$traverseInOrderRec:(Lstructures/Node;Ljava/util/List;)V
      12: aload_1
      13: aload_0
      14: invokevirtual #86                 // Method structures/Node.value:()I
      17: invokestatic  #92                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      20: invokeinterface #93,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      25: pop
      26: aload_0
      27: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      30: aload_1
      31: invokestatic  #47                 // Method traverseInOrder$traverseInOrderRec:(Lstructures/Node;Ljava/util/List;)V
      34: return

  private static final void traversePreOrder$traversePreOrderRec(structures.Node, java.util.List<java.lang.Integer>);
    Code:
       0: aload_0
       1: ifnull        34
       4: aload_1
       5: aload_0
       6: invokevirtual #86                 // Method structures/Node.value:()I
       9: invokestatic  #92                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      12: invokeinterface #93,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      17: pop
      18: aload_0
      19: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
      22: aload_1
      23: invokestatic  #54                 // Method traversePreOrder$traversePreOrderRec:(Lstructures/Node;Ljava/util/List;)V
      26: aload_0
      27: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      30: aload_1
      31: invokestatic  #54                 // Method traversePreOrder$traversePreOrderRec:(Lstructures/Node;Ljava/util/List;)V
      34: return

  private static final void traversePostOrder$traversePostOrderRec(structures.Node, java.util.List<java.lang.Integer>);
    Code:
       0: aload_0
       1: ifnull        34
       4: aload_0
       5: invokevirtual #97                 // Method structures/Node.leftNode:()Lstructures/Node;
       8: aload_1
       9: invokestatic  #60                 // Method traversePostOrder$traversePostOrderRec:(Lstructures/Node;Ljava/util/List;)V
      12: aload_0
      13: invokevirtual #100                // Method structures/Node.rightNode:()Lstructures/Node;
      16: aload_1
      17: invokestatic  #60                 // Method traversePostOrder$traversePostOrderRec:(Lstructures/Node;Ljava/util/List;)V
      20: aload_1
      21: aload_0
      22: invokevirtual #86                 // Method structures/Node.value:()I
      25: invokestatic  #92                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      28: invokeinterface #93,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      33: pop
      34: return
}