package javagilde

// We willen expressies parsen, d.w.z 5*2 + 1
sealed class Expression {
    abstract fun evaluate(): Int
}

data class Multiplication(val left: Expression, val right: Expression): Expression() {
    override fun evaluate(): Int =
        left.evaluate() * right.evaluate()
}

data class Addition(val left: Expression, val right: Expression) : Expression() {
    override fun evaluate(): Int =
        left.evaluate() + right.evaluate()
}

data class Constant(val value: Int): Expression() {
    override fun evaluate(): Int =
        value
}

typealias Parser<T> = (String) -> List<Pair<T, String>>

fun parserA(input: String): List<Pair<Char, String>> {
    return if (input.startsWith('A')) {
        listOf('A' to input.drop(1))
    } else {
        emptyList()
    }}

fun character(target: Char): Parser<Char> = { input: String ->
        if (input.startsWith(target)) {
            listOf( target to input.drop(1))
        } else {
            emptyList()
        }
    }

//val parserA = character('A')

fun satisfy(predicate: (Char) -> Boolean): Parser<Char> = { input: String ->
        if (input.length > 0 && predicate(input[0])) {
                listOf(input[0] to input.drop(1))
        } else {
            emptyList()
        }
    }

val parserAorB = satisfy { it == 'A' || it == 'B'}

fun <T> or(p: Parser<T>, q: Parser<T>): Parser<T> = { input ->
    // How to implement?
    p(input) + q(input)
}

infix fun <T> Parser<T>.`|||`(p: Parser<T>): Parser<T> =
    or(this, p)

fun <S, T> and(p: Parser<S>, q: Parser<T>): Parser<Pair<S,T>> = {input ->
    p(input)
        .flatMap { (s, intermediate) ->
            q(intermediate).map { (t, rest) -> (s to t) to rest }
        }
}

infix fun <S, T> Parser<S>.`|&|`(p: Parser<T>): Parser<Pair<S, T>> =
    and(this, p)

fun <S, T> map(p: Parser<S>, transform: (S) -> T): Parser<T> = { input ->
    p(input)
        .map {(s, rest) -> transform(s) to rest }
}

infix fun <S, T> Parser<S>.`&|`(p: Parser<T>): Parser<T> =
    map(and(this, p)) {(_, t) -> t}

infix fun <S, T> Parser<S>.`|&`(p: Parser<T>): Parser<S> =
    map(and(this, p)) {(s, _) -> s}

fun <T> succeed(result: T): Parser<T> = {input ->
    listOf( result to input )
}

fun <T> lazy(p: () -> Parser<T>): Parser<T> = { input ->
    p()(input)
}

fun <T> many(p: Parser<T>): Parser<List<T>> =
    or(
        map(and(p, lazy {many(p)})) { (r, rs) -> listOf(r) + rs},
        succeed(emptyList())
    )

fun <T> many1(p: Parser<T>): Parser<List<T>> =
    map(p `|&|` many(p)) {(r,rs) -> listOf(r) + rs}

val digit: Parser<Int> =
    map(satisfy { c -> c in '0' .. '9'}) { it - '0' }

val number: Parser<Int> = map(many1(digit)) {
    it.fold(0) {acc, d -> 10*acc + d}
}

val constant: Parser<Expression> =
    map(number) {n -> Constant(n)}

fun multiplication(): Parser<Expression> =
    constant `|||` map(constant `|&` character('*') `|&|` lazy(::multiplication)) {
        (left, right) -> Multiplication(left, right)
    }

fun addition(): Parser<Expression> =
    multiplication() `|||` map(multiplication() `|&` character('+') `|&|` lazy(::addition)) {
        (left, right) -> Addition(left, right)
    }

fun expression() : Parser<Expression> =
    addition()

fun <T> just(p: Parser<T>): Parser<T> = {input ->
    p(input)
        .filter {(_, rest) -> rest.isEmpty() }
}

fun <T> parse(parser: Parser<T>, input: String): T? =
    just(parser)(input).get(0).first

fun main() {
    // 5*2 + 1
    val expr = parse(expression(), "5*2+1")//Addition(Multiplication(Constant(5), Constant(2)), Constant(1))
    println(expr)
    println(expr!!.evaluate())
}

Compiled from "final.kt"
final class javagilde.FinalKt$addition$1 extends kotlin.jvm.internal.FunctionReferenceImpl implements kotlin.jvm.functions.Function0<kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends javagilde.Expression, ? extends java.lang.String>>>> {
  public static final javagilde.FinalKt$addition$1 INSTANCE;

  javagilde.FinalKt$addition$1();
    Code:
       0: aload_0
       1: iconst_0
       2: ldc           #11                 // class javagilde/FinalKt
       4: ldc           #13                 // String addition
       6: ldc           #15                 // String addition()Lkotlin/jvm/functions/Function1;
       8: iconst_1
       9: invokespecial #18                 // Method kotlin/jvm/internal/FunctionReferenceImpl."<init>":(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
      12: return

  public final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> invoke();
    Code:
       0: invokestatic  #25                 // Method javagilde/FinalKt.addition:()Lkotlin/jvm/functions/Function1;
       3: areturn

  public java.lang.Object invoke();
    Code:
       0: aload_0
       1: invokevirtual #28                 // Method invoke:()Lkotlin/jvm/functions/Function1;
       4: areturn

  static {};
    Code:
       0: new           #2                  // class javagilde/FinalKt$addition$1
       3: dup
       4: invokespecial #31                 // Method "<init>":()V
       7: putstatic     #34                 // Field INSTANCE:Ljavagilde/FinalKt$addition$1;
      10: return
}

Compiled from "final.kt"
final class javagilde.FinalKt$multiplication$1 extends kotlin.jvm.internal.FunctionReferenceImpl implements kotlin.jvm.functions.Function0<kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends javagilde.Expression, ? extends java.lang.String>>>> {
  public static final javagilde.FinalKt$multiplication$1 INSTANCE;

  javagilde.FinalKt$multiplication$1();
    Code:
       0: aload_0
       1: iconst_0
       2: ldc           #11                 // class javagilde/FinalKt
       4: ldc           #13                 // String multiplication
       6: ldc           #15                 // String multiplication()Lkotlin/jvm/functions/Function1;
       8: iconst_1
       9: invokespecial #18                 // Method kotlin/jvm/internal/FunctionReferenceImpl."<init>":(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
      12: return

  public final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> invoke();
    Code:
       0: invokestatic  #25                 // Method javagilde/FinalKt.multiplication:()Lkotlin/jvm/functions/Function1;
       3: areturn

  public java.lang.Object invoke();
    Code:
       0: aload_0
       1: invokevirtual #28                 // Method invoke:()Lkotlin/jvm/functions/Function1;
       4: areturn

  static {};
    Code:
       0: new           #2                  // class javagilde/FinalKt$multiplication$1
       3: dup
       4: invokespecial #31                 // Method "<init>":()V
       7: putstatic     #34                 // Field INSTANCE:Ljavagilde/FinalKt$multiplication$1;
      10: return
}

Compiled from "final.kt"
public final class javagilde.FinalKt {
  private static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Character, java.lang.String>>> parserAorB;

  private static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Integer, java.lang.String>>> digit;

  private static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Integer, java.lang.String>>> number;

  private static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> constant;

  public static final java.util.List<kotlin.Pair<java.lang.Character, java.lang.String>> parserA(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/CharSequence
      10: bipush        65
      12: iconst_0
      13: iconst_2
      14: aconst_null
      15: invokestatic  #24                 // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
      18: ifeq          40
      21: bipush        65
      23: invokestatic  #30                 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      26: aload_0
      27: iconst_1
      28: invokestatic  #34                 // Method kotlin/text/StringsKt.drop:(Ljava/lang/String;I)Ljava/lang/String;
      31: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      34: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      37: goto          43
      40: invokestatic  #50                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      43: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Character, java.lang.String>>> character(char);
    Code:
       0: iload_0
       1: invokedynamic #74,  0             // InvokeDynamic #0:invoke:(C)Lkotlin/jvm/functions/Function1;
       6: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Character, java.lang.String>>> satisfy(kotlin.jvm.functions.Function1<? super java.lang.Character, java.lang.Boolean>);
    Code:
       0: aload_0
       1: ldc           #81                 // String predicate
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #88,  0             // InvokeDynamic #1:invoke:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      12: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Character, java.lang.String>>> getParserAorB();
    Code:
       0: getstatic     #95                 // Field parserAorB:Lkotlin/jvm/functions/Function1;
       3: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> or(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #102                // String q
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokedynamic #109,  0            // InvokeDynamic #2:invoke:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      19: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> |||(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #112                // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #100                // String p
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokestatic  #114                // Method or:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      17: areturn

  public static final <S, T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<kotlin.Pair<S, T>, java.lang.String>>> and(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends S, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #102                // String q
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokedynamic #122,  0            // InvokeDynamic #3:invoke:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      19: areturn

  public static final <S, T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<kotlin.Pair<S, T>, java.lang.String>>> |&|(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends S, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #112                // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #100                // String p
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokestatic  #125                // Method and:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      17: areturn

  public static final <S, T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> map(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends S, java.lang.String>>>, kotlin.jvm.functions.Function1<? super S, ? extends T>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #130                // String transform
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokedynamic #135,  0            // InvokeDynamic #4:invoke:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      19: areturn

  public static final <S, T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> &|(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends S, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #112                // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #100                // String p
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokestatic  #125                // Method and:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      17: invokedynamic #145,  0            // InvokeDynamic #5:invoke:()Lkotlin/jvm/functions/Function1;
      22: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      25: areturn

  public static final <S, T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<S, java.lang.String>>> |&(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends S, java.lang.String>>>, kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #112                // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #100                // String p
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: aload_1
      14: invokestatic  #125                // Method and:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      17: invokedynamic #155,  0            // InvokeDynamic #6:invoke:()Lkotlin/jvm/functions/Function1;
      22: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      25: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> succeed(T);
    Code:
       0: aload_0
       1: invokedynamic #166,  0            // InvokeDynamic #7:invoke:(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
       6: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> lazy(kotlin.jvm.functions.Function0<? extends kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #178,  0            // InvokeDynamic #8:invoke:(Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function1;
      12: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.util.List<T>, java.lang.String>>> many(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_0
       8: invokedynamic #191,  0            // InvokeDynamic #9:invoke:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0;
      13: invokestatic  #193                // Method lazy:(Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function1;
      16: invokestatic  #125                // Method and:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      19: invokedynamic #200,  0            // InvokeDynamic #10:invoke:()Lkotlin/jvm/functions/Function1;
      24: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      27: invokestatic  #50                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      30: invokestatic  #202                // Method succeed:(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
      33: invokestatic  #114                // Method or:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      36: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.util.List<T>, java.lang.String>>> many1(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_0
       8: invokestatic  #205                // Method many:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      11: invokestatic  #207                // Method "|&|":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      14: invokedynamic #212,  0            // InvokeDynamic #11:invoke:()Lkotlin/jvm/functions/Function1;
      19: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      22: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Integer, java.lang.String>>> getDigit();
    Code:
       0: getstatic     #217                // Field digit:Lkotlin/jvm/functions/Function1;
       3: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<java.lang.Integer, java.lang.String>>> getNumber();
    Code:
       0: getstatic     #221                // Field number:Lkotlin/jvm/functions/Function1;
       3: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> getConstant();
    Code:
       0: getstatic     #226                // Field constant:Lkotlin/jvm/functions/Function1;
       3: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> multiplication();
    Code:
       0: getstatic     #226                // Field constant:Lkotlin/jvm/functions/Function1;
       3: getstatic     #226                // Field constant:Lkotlin/jvm/functions/Function1;
       6: bipush        42
       8: invokestatic  #229                // Method character:(C)Lkotlin/jvm/functions/Function1;
      11: invokestatic  #231                // Method "|&":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      14: getstatic     #237                // Field javagilde/FinalKt$multiplication$1.INSTANCE:Ljavagilde/FinalKt$multiplication$1;
      17: checkcast     #239                // class kotlin/jvm/functions/Function0
      20: invokestatic  #193                // Method lazy:(Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function1;
      23: invokestatic  #207                // Method "|&|":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      26: invokedynamic #246,  0            // InvokeDynamic #12:invoke:()Lkotlin/jvm/functions/Function1;
      31: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      34: invokestatic  #248                // Method "|||":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      37: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> addition();
    Code:
       0: invokestatic  #251                // Method multiplication:()Lkotlin/jvm/functions/Function1;
       3: invokestatic  #251                // Method multiplication:()Lkotlin/jvm/functions/Function1;
       6: bipush        43
       8: invokestatic  #229                // Method character:(C)Lkotlin/jvm/functions/Function1;
      11: invokestatic  #231                // Method "|&":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      14: getstatic     #256                // Field javagilde/FinalKt$addition$1.INSTANCE:Ljavagilde/FinalKt$addition$1;
      17: checkcast     #239                // class kotlin/jvm/functions/Function0
      20: invokestatic  #193                // Method lazy:(Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function1;
      23: invokestatic  #207                // Method "|&|":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      26: invokedynamic #263,  0            // InvokeDynamic #13:invoke:()Lkotlin/jvm/functions/Function1;
      31: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      34: invokestatic  #248                // Method "|||":(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      37: areturn

  public static final kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<javagilde.Expression, java.lang.String>>> expression();
    Code:
       0: invokestatic  #266                // Method addition:()Lkotlin/jvm/functions/Function1;
       3: areturn

  public static final <T> kotlin.jvm.functions.Function1<java.lang.String, java.util.List<kotlin.Pair<T, java.lang.String>>> just(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>);
    Code:
       0: aload_0
       1: ldc           #100                // String p
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokedynamic #273,  0            // InvokeDynamic #14:invoke:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      12: areturn

  public static final <T> T parse(kotlin.jvm.functions.Function1<? super java.lang.String, ? extends java.util.List<? extends kotlin.Pair<? extends T, java.lang.String>>>, java.lang.String);
    Code:
       0: aload_0
       1: ldc_w         #279                // String parser
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_1
       8: ldc           #10                 // String input
      10: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      13: aload_0
      14: invokestatic  #281                // Method just:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      17: aload_1
      18: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      23: checkcast     #53                 // class java/util/List
      26: iconst_0
      27: invokeinterface #289,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      32: checkcast     #291                // class kotlin/Pair
      35: invokevirtual #294                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      38: areturn

  public static final void main();
    Code:
       0: invokestatic  #298                // Method expression:()Lkotlin/jvm/functions/Function1;
       3: ldc_w         #300                // String 5*2+1
       6: invokestatic  #302                // Method parse:(Lkotlin/jvm/functions/Function1;Ljava/lang/String;)Ljava/lang/Object;
       9: checkcast     #304                // class javagilde/Expression
      12: astore_0
      13: getstatic     #310                // Field java/lang/System.out:Ljava/io/PrintStream;
      16: aload_0
      17: invokevirtual #316                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      20: aload_0
      21: dup
      22: invokestatic  #319                // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      25: invokevirtual #323                // Method javagilde/Expression.evaluate:()I
      28: istore_1
      29: getstatic     #310                // Field java/lang/System.out:Ljava/io/PrintStream;
      32: iload_1
      33: invokevirtual #326                // Method java/io/PrintStream.println:(I)V
      36: return

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

  private static final java.util.List character$lambda$0(char, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: checkcast     #18                 // class java/lang/CharSequence
      10: iload_0
      11: iconst_0
      12: iconst_2
      13: aconst_null
      14: invokestatic  #24                 // Method kotlin/text/StringsKt.startsWith$default:(Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
      17: ifeq          38
      20: iload_0
      21: invokestatic  #30                 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      24: aload_1
      25: iconst_1
      26: invokestatic  #34                 // Method kotlin/text/StringsKt.drop:(Ljava/lang/String;I)Ljava/lang/String;
      29: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      32: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      35: goto          41
      38: invokestatic  #50                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      41: areturn

  private static final java.util.List satisfy$lambda$1(kotlin.jvm.functions.Function1, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: invokevirtual #339                // Method java/lang/String.length:()I
      10: ifle          58
      13: aload_0
      14: aload_1
      15: iconst_0
      16: invokevirtual #343                // Method java/lang/String.charAt:(I)C
      19: invokestatic  #30                 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      22: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      27: checkcast     #345                // class java/lang/Boolean
      30: invokevirtual #349                // Method java/lang/Boolean.booleanValue:()Z
      33: ifeq          58
      36: aload_1
      37: iconst_0
      38: invokevirtual #343                // Method java/lang/String.charAt:(I)C
      41: invokestatic  #30                 // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      44: aload_1
      45: iconst_1
      46: invokestatic  #34                 // Method kotlin/text/StringsKt.drop:(Ljava/lang/String;I)Ljava/lang/String;
      49: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      52: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      55: goto          61
      58: invokestatic  #50                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      61: areturn

  private static final boolean parserAorB$lambda$2(char);
    Code:
       0: iload_0
       1: bipush        65
       3: if_icmpeq     12
       6: iload_0
       7: bipush        66
       9: if_icmpne     16
      12: iconst_1
      13: goto          17
      16: iconst_0
      17: ireturn

  private static final java.util.List or$lambda$3(kotlin.jvm.functions.Function1, kotlin.jvm.functions.Function1, java.lang.String);
    Code:
       0: aload_2
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_2
       8: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      13: checkcast     #355                // class java/util/Collection
      16: aload_1
      17: aload_2
      18: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      23: checkcast     #357                // class java/lang/Iterable
      26: invokestatic  #361                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
      29: areturn

  private static final java.util.List and$lambda$6(kotlin.jvm.functions.Function1, kotlin.jvm.functions.Function1, java.lang.String);
    Code:
       0: aload_2
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_2
       8: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      13: checkcast     #357                // class java/lang/Iterable
      16: astore_3
      17: nop
      18: iconst_0
      19: istore        4
      21: aload_3
      22: astore        5
      24: new           #365                // class java/util/ArrayList
      27: dup
      28: invokespecial #368                // Method java/util/ArrayList."<init>":()V
      31: checkcast     #355                // class java/util/Collection
      34: astore        6
      36: iconst_0
      37: istore        7
      39: aload         5
      41: invokeinterface #372,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      46: astore        8
      48: aload         8
      50: invokeinterface #377,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      55: ifeq          242
      58: aload         8
      60: invokeinterface #380,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      65: astore        9
      67: aload         9
      69: checkcast     #291                // class kotlin/Pair
      72: astore        10
      74: iconst_0
      75: istore        11
      77: aload         10
      79: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      82: astore        12
      84: aload         10
      86: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      89: checkcast     #336                // class java/lang/String
      92: astore        13
      94: aload_1
      95: aload         13
      97: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
     102: checkcast     #357                // class java/lang/Iterable
     105: astore        14
     107: iconst_0
     108: istore        15
     110: aload         14
     112: astore        16
     114: new           #365                // class java/util/ArrayList
     117: dup
     118: aload         14
     120: bipush        10
     122: invokestatic  #390                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     125: invokespecial #392                // Method java/util/ArrayList."<init>":(I)V
     128: checkcast     #355                // class java/util/Collection
     131: astore        17
     133: iconst_0
     134: istore        18
     136: aload         16
     138: invokeinterface #372,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     143: astore        19
     145: aload         19
     147: invokeinterface #377,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     152: ifeq          219
     155: aload         19
     157: invokeinterface #380,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     162: astore        20
     164: aload         17
     166: aload         20
     168: checkcast     #291                // class kotlin/Pair
     171: astore        21
     173: astore        22
     175: iconst_0
     176: istore        23
     178: aload         21
     180: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
     183: astore        24
     185: aload         21
     187: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
     190: checkcast     #336                // class java/lang/String
     193: astore        25
     195: aload         12
     197: aload         24
     199: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     202: aload         25
     204: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     207: aload         22
     209: swap
     210: invokeinterface #396,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     215: pop
     216: goto          145
     219: aload         17
     221: checkcast     #53                 // class java/util/List
     224: nop
     225: checkcast     #357                // class java/lang/Iterable
     228: nop
     229: astore        10
     231: aload         6
     233: aload         10
     235: invokestatic  #400                // Method kotlin/collections/CollectionsKt.addAll:(Ljava/util/Collection;Ljava/lang/Iterable;)Z
     238: pop
     239: goto          48
     242: aload         6
     244: checkcast     #53                 // class java/util/List
     247: nop
     248: areturn

  private static final java.util.List map$lambda$8(kotlin.jvm.functions.Function1, kotlin.jvm.functions.Function1, java.lang.String);
    Code:
       0: aload_2
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_2
       8: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      13: checkcast     #357                // class java/lang/Iterable
      16: astore_3
      17: nop
      18: iconst_0
      19: istore        4
      21: aload_3
      22: astore        5
      24: new           #365                // class java/util/ArrayList
      27: dup
      28: aload_3
      29: bipush        10
      31: invokestatic  #390                // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      34: invokespecial #392                // Method java/util/ArrayList."<init>":(I)V
      37: checkcast     #355                // class java/util/Collection
      40: astore        6
      42: iconst_0
      43: istore        7
      45: aload         5
      47: invokeinterface #372,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      52: astore        8
      54: aload         8
      56: invokeinterface #377,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      61: ifeq          129
      64: aload         8
      66: invokeinterface #380,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      71: astore        9
      73: aload         6
      75: aload         9
      77: checkcast     #291                // class kotlin/Pair
      80: astore        10
      82: astore        14
      84: iconst_0
      85: istore        11
      87: aload         10
      89: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      92: astore        12
      94: aload         10
      96: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      99: checkcast     #336                // class java/lang/String
     102: astore        13
     104: aload_1
     105: aload         12
     107: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
     112: aload         13
     114: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     117: aload         14
     119: swap
     120: invokeinterface #396,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     125: pop
     126: goto          54
     129: aload         6
     131: checkcast     #53                 // class java/util/List
     134: nop
     135: areturn

  private static final java.lang.Object __$lambda$9(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      11: astore_1
      12: aload_1
      13: areturn

  private static final java.lang.Object __$lambda$10(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      11: astore_1
      12: aload_1
      13: areturn

  private static final java.util.List succeed$lambda$11(java.lang.Object, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_1
       8: invokestatic  #40                 // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      11: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      14: areturn

  private static final java.util.List lazy$lambda$12(kotlin.jvm.functions.Function0, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokeinterface #428,  1          // InterfaceMethod kotlin/jvm/functions/Function0.invoke:()Ljava/lang/Object;
      12: checkcast     #283                // class kotlin/jvm/functions/Function1
      15: aload_1
      16: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      21: checkcast     #53                 // class java/util/List
      24: areturn

  private static final kotlin.jvm.functions.Function1 many$lambda$13(kotlin.jvm.functions.Function1);
    Code:
       0: aload_0
       1: invokestatic  #205                // Method many:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
       4: areturn

  private static final java.util.List many$lambda$14(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      11: astore_1
      12: aload_0
      13: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      16: checkcast     #53                 // class java/util/List
      19: astore_2
      20: aload_1
      21: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      24: checkcast     #355                // class java/util/Collection
      27: aload_2
      28: checkcast     #357                // class java/lang/Iterable
      31: invokestatic  #361                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
      34: areturn

  private static final java.util.List many1$lambda$15(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      11: astore_1
      12: aload_0
      13: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      16: checkcast     #53                 // class java/util/List
      19: astore_2
      20: aload_1
      21: invokestatic  #46                 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
      24: checkcast     #355                // class java/util/Collection
      27: aload_2
      28: checkcast     #357                // class java/lang/Iterable
      31: invokestatic  #361                // Method kotlin/collections/CollectionsKt.plus:(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
      34: areturn

  private static final boolean digit$lambda$16(char);
    Code:
       0: bipush        48
       2: iload_0
       3: if_icmpgt     20
       6: iload_0
       7: bipush        58
       9: if_icmpge     16
      12: iconst_1
      13: goto          21
      16: iconst_0
      17: goto          21
      20: iconst_0
      21: ireturn

  private static final int digit$lambda$17(char);
    Code:
       0: iload_0
       1: bipush        48
       3: isub
       4: ireturn

  private static final int number$lambda$19(java.util.List);
    Code:
       0: aload_0
       1: ldc_w         #438                // String it
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: checkcast     #357                // class java/lang/Iterable
      11: astore_1
      12: iconst_0
      13: istore_2
      14: iconst_0
      15: istore_3
      16: iload_2
      17: istore        4
      19: aload_1
      20: invokeinterface #372,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      25: astore        5
      27: aload         5
      29: invokeinterface #377,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      34: ifeq          76
      37: aload         5
      39: invokeinterface #380,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      44: astore        6
      46: iload         4
      48: aload         6
      50: checkcast     #440                // class java/lang/Number
      53: invokevirtual #443                // Method java/lang/Number.intValue:()I
      56: istore        7
      58: istore        8
      60: iconst_0
      61: istore        9
      63: bipush        10
      65: iload         8
      67: imul
      68: iload         7
      70: iadd
      71: istore        4
      73: goto          27
      76: iload         4
      78: ireturn

  private static final javagilde.Constant constant$lambda$20(int);
    Code:
       0: new           #455                // class javagilde/Constant
       3: dup
       4: iload_0
       5: invokespecial #456                // Method javagilde/Constant."<init>":(I)V
       8: areturn

  private static final javagilde.Multiplication multiplication$lambda$21(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      11: checkcast     #304                // class javagilde/Expression
      14: astore_1
      15: aload_0
      16: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      19: checkcast     #304                // class javagilde/Expression
      22: astore_2
      23: new           #459                // class javagilde/Multiplication
      26: dup
      27: aload_1
      28: aload_2
      29: invokespecial #462                // Method javagilde/Multiplication."<init>":(Ljavagilde/Expression;Ljavagilde/Expression;)V
      32: areturn

  private static final javagilde.Addition addition$lambda$22(kotlin.Pair);
    Code:
       0: aload_0
       1: ldc_w         #425                // String <destruct>
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: invokevirtual #383                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      11: checkcast     #304                // class javagilde/Expression
      14: astore_1
      15: aload_0
      16: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      19: checkcast     #304                // class javagilde/Expression
      22: astore_2
      23: new           #466                // class javagilde/Addition
      26: dup
      27: aload_1
      28: aload_2
      29: invokespecial #467                // Method javagilde/Addition."<init>":(Ljavagilde/Expression;Ljavagilde/Expression;)V
      32: areturn

  private static final java.util.List just$lambda$24(kotlin.jvm.functions.Function1, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #10                 // String input
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_1
       8: invokeinterface #285,  2          // InterfaceMethod kotlin/jvm/functions/Function1.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
      13: checkcast     #357                // class java/lang/Iterable
      16: astore_2
      17: nop
      18: iconst_0
      19: istore_3
      20: aload_2
      21: astore        4
      23: new           #365                // class java/util/ArrayList
      26: dup
      27: invokespecial #368                // Method java/util/ArrayList."<init>":()V
      30: checkcast     #355                // class java/util/Collection
      33: astore        5
      35: iconst_0
      36: istore        6
      38: aload         4
      40: invokeinterface #372,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      45: astore        7
      47: aload         7
      49: invokeinterface #377,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
      54: ifeq          121
      57: aload         7
      59: invokeinterface #380,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      64: astore        8
      66: aload         8
      68: checkcast     #291                // class kotlin/Pair
      71: astore        9
      73: iconst_0
      74: istore        10
      76: aload         9
      78: invokevirtual #386                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      81: checkcast     #336                // class java/lang/String
      84: astore        11
      86: aload         11
      88: checkcast     #18                 // class java/lang/CharSequence
      91: invokeinterface #468,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      96: ifne          103
      99: iconst_1
     100: goto          104
     103: iconst_0
     104: nop
     105: ifeq          47
     108: aload         5
     110: aload         8
     112: invokeinterface #396,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     117: pop
     118: goto          47
     121: aload         5
     123: checkcast     #53                 // class java/util/List
     126: nop
     127: areturn

  static {};
    Code:
       0: invokedynamic #480,  0            // InvokeDynamic #15:invoke:()Lkotlin/jvm/functions/Function1;
       5: invokestatic  #482                // Method satisfy:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
       8: putstatic     #95                 // Field parserAorB:Lkotlin/jvm/functions/Function1;
      11: invokedynamic #486,  0            // InvokeDynamic #16:invoke:()Lkotlin/jvm/functions/Function1;
      16: invokestatic  #482                // Method satisfy:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      19: invokedynamic #492,  0            // InvokeDynamic #17:invoke:()Lkotlin/jvm/functions/Function1;
      24: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      27: putstatic     #217                // Field digit:Lkotlin/jvm/functions/Function1;
      30: getstatic     #217                // Field digit:Lkotlin/jvm/functions/Function1;
      33: invokestatic  #494                // Method many1:(Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      36: invokedynamic #500,  0            // InvokeDynamic #18:invoke:()Lkotlin/jvm/functions/Function1;
      41: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      44: putstatic     #221                // Field number:Lkotlin/jvm/functions/Function1;
      47: getstatic     #221                // Field number:Lkotlin/jvm/functions/Function1;
      50: invokedynamic #506,  0            // InvokeDynamic #19:invoke:()Lkotlin/jvm/functions/Function1;
      55: invokestatic  #147                // Method map:(Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1;
      58: putstatic     #226                // Field constant:Lkotlin/jvm/functions/Function1;
      61: return
}


package day4

class Day4 {
    fun getOrganizer(filename: String): SupplyOrganizer {
        val readLines = this::class.java.getResourceAsStream(filename).bufferedReader().readLines()

        return SupplyOrganizer(readLines)
    }
}

class SupplyOrganizer(input: List<String>) {
    val elfPairs = input.map { ElfPair(it) }

    val fullyContained = elfPairs.count { it.fullyContains }
    val overlapped = elfPairs.count { it.overlaps }
}

data class ElfPair(val input: String) {
    private val firstSection = AssignedSection(input.split(",").first())
    private val secondSection = AssignedSection(input.split(",").last())

    val fullyContains = firstSection.sections.intersect(secondSection.sections) == firstSection.sections
            || secondSection.sections.intersect(firstSection.sections) == secondSection.sections

    val overlaps = firstSection.sections.intersect(secondSection.sections).isNotEmpty()

    override fun toString(): String {
        return "ElfPair[${firstSection.range}][${secondSection.range}][fullyContains=$fullyContains][overlaps=$overlaps]"
    }
}

data class AssignedSection(val input: String) {
    val from = input.split("-")[0].toInt()
    val to = input.split("-")[1].toInt()
    val range = (from..to)
    val sections = range.toSet()

    override fun toString(): String {
        return "AssignedSection[$range]"
    }

}

fun main() {
    val organizerTest = Day4().getOrganizer("/day4_test.txt")
    val organizerInput = Day4().getOrganizer("/day4_input.txt")
    //println("elfpairs: ${organizerTest.elfPairs}")

    organizerInput.elfPairs.filter { !it.fullyContains }.forEach { println(it)}

    println("Part 1 test: ${organizerTest.fullyContained}")
    println("Part 1 input: ${organizerInput.fullyContained}")
    println("Part 1 test: ${organizerTest.overlapped}")
    println("Part 1 input: ${organizerInput.overlapped}")
}

Compiled from "Day4.kt"
public final class day4.Day4 {
  public day4.Day4();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final day4.SupplyOrganizer getOrganizer(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String filename
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #25                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      10: aload_1
      11: invokevirtual #31                 // Method java/lang/Class.getResourceAsStream:(Ljava/lang/String;)Ljava/io/InputStream;
      14: dup
      15: ldc           #33                 // String getResourceAsStream(...)
      17: invokestatic  #36                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      20: astore_3
      21: getstatic     #42                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      24: astore        4
      26: new           #44                 // class java/io/InputStreamReader
      29: dup
      30: aload_3
      31: aload         4
      33: invokespecial #47                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      36: checkcast     #49                 // class java/io/Reader
      39: astore        5
      41: sipush        8192
      44: istore        6
      46: aload         5
      48: instanceof    #51                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         5
      56: checkcast     #51                 // class java/io/BufferedReader
      59: goto          73
      62: new           #51                 // class java/io/BufferedReader
      65: dup
      66: aload         5
      68: iload         6
      70: invokespecial #54                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      73: checkcast     #49                 // class java/io/Reader
      76: invokestatic  #60                 // Method kotlin/io/TextStreamsKt.readLines:(Ljava/io/Reader;)Ljava/util/List;
      79: astore_2
      80: new           #62                 // class day4/SupplyOrganizer
      83: dup
      84: aload_2
      85: invokespecial #65                 // Method day4/SupplyOrganizer."<init>":(Ljava/util/List;)V
      88: areturn
}

Compiled from "Day4.kt"
public final class day4.Day4Kt {
  public static final void main();
    Code:
       0: new           #8                  // class day4/Day4
       3: dup
       4: invokespecial #11                 // Method day4/Day4."<init>":()V
       7: ldc           #13                 // String /day4_test.txt
       9: invokevirtual #17                 // Method day4/Day4.getOrganizer:(Ljava/lang/String;)Lday4/SupplyOrganizer;
      12: astore_0
      13: new           #8                  // class day4/Day4
      16: dup
      17: invokespecial #11                 // Method day4/Day4."<init>":()V
      20: ldc           #19                 // String /day4_input.txt
      22: invokevirtual #17                 // Method day4/Day4.getOrganizer:(Ljava/lang/String;)Lday4/SupplyOrganizer;
      25: astore_1
      26: aload_1
      27: invokevirtual #25                 // Method day4/SupplyOrganizer.getElfPairs:()Ljava/util/List;
      30: checkcast     #27                 // class java/lang/Iterable
      33: astore_2
      34: iconst_0
      35: istore_3
      36: aload_2
      37: astore        4
      39: new           #29                 // class java/util/ArrayList
      42: dup
      43: invokespecial #30                 // Method java/util/ArrayList."<init>":()V
      46: checkcast     #32                 // class java/util/Collection
      49: astore        5
      51: iconst_0
      52: istore        6
      54: aload         4
      56: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      61: astore        7
      63: aload         7
      65: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      70: ifeq          121
      73: aload         7
      75: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      80: astore        8
      82: aload         8
      84: checkcast     #48                 // class day4/ElfPair
      87: astore        9
      89: iconst_0
      90: istore        10
      92: aload         9
      94: invokevirtual #51                 // Method day4/ElfPair.getFullyContains:()Z
      97: ifne          104
     100: iconst_1
     101: goto          105
     104: iconst_0
     105: ifeq          63
     108: aload         5
     110: aload         8
     112: invokeinterface #55,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     117: pop
     118: goto          63
     121: aload         5
     123: checkcast     #57                 // class java/util/List
     126: nop
     127: checkcast     #27                 // class java/lang/Iterable
     130: astore_2
     131: nop
     132: iconst_0
     133: istore_3
     134: aload_2
     135: invokeinterface #36,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     140: astore        4
     142: aload         4
     144: invokeinterface #42,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     149: ifeq          184
     152: aload         4
     154: invokeinterface #46,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     159: astore        5
     161: aload         5
     163: checkcast     #48                 // class day4/ElfPair
     166: astore        6
     168: iconst_0
     169: istore        7
     171: getstatic     #63                 // Field java/lang/System.out:Ljava/io/PrintStream;
     174: aload         6
     176: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     179: nop
     180: nop
     181: goto          142
     184: nop
     185: new           #71                 // class java/lang/StringBuilder
     188: dup
     189: invokespecial #72                 // Method java/lang/StringBuilder."<init>":()V
     192: ldc           #74                 // String Part 1 test:
     194: invokevirtual #78                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     197: aload_0
     198: invokevirtual #82                 // Method day4/SupplyOrganizer.getFullyContained:()I
     201: invokevirtual #85                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     204: invokevirtual #89                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     207: getstatic     #63                 // Field java/lang/System.out:Ljava/io/PrintStream;
     210: swap
     211: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     214: new           #71                 // class java/lang/StringBuilder
     217: dup
     218: invokespecial #72                 // Method java/lang/StringBuilder."<init>":()V
     221: ldc           #91                 // String Part 1 input:
     223: invokevirtual #78                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     226: aload_1
     227: invokevirtual #82                 // Method day4/SupplyOrganizer.getFullyContained:()I
     230: invokevirtual #85                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     233: invokevirtual #89                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     236: getstatic     #63                 // Field java/lang/System.out:Ljava/io/PrintStream;
     239: swap
     240: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     243: new           #71                 // class java/lang/StringBuilder
     246: dup
     247: invokespecial #72                 // Method java/lang/StringBuilder."<init>":()V
     250: ldc           #74                 // String Part 1 test:
     252: invokevirtual #78                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     255: aload_0
     256: invokevirtual #94                 // Method day4/SupplyOrganizer.getOverlapped:()I
     259: invokevirtual #85                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     262: invokevirtual #89                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     265: getstatic     #63                 // Field java/lang/System.out:Ljava/io/PrintStream;
     268: swap
     269: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     272: new           #71                 // class java/lang/StringBuilder
     275: dup
     276: invokespecial #72                 // Method java/lang/StringBuilder."<init>":()V
     279: ldc           #91                 // String Part 1 input:
     281: invokevirtual #78                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     284: aload_1
     285: invokevirtual #94                 // Method day4/SupplyOrganizer.getOverlapped:()I
     288: invokevirtual #85                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     291: invokevirtual #89                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     294: getstatic     #63                 // Field java/lang/System.out:Ljava/io/PrintStream;
     297: swap
     298: invokevirtual #69                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     301: return

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


package day3

class Day3 {
    fun getOrganizer(filename: String): RucksackOrganizer {
        val readLines = this::class.java.getResourceAsStream(filename).bufferedReader().readLines()

        return RucksackOrganizer(readLines)
    }
}

data class RucksackOrganizer(val input: List<String>) {
    val rucksacks = input.map { Rucksack(it) }

    val elfGroups = createElfGroups(listOf(), rucksacks)

    private fun createElfGroups(accumulator: List<ElfGroup>, input: List<Rucksack>): List<ElfGroup> {
        if (input.isEmpty()) return accumulator

        return createElfGroups(accumulator + ElfGroup(input.take(3)), input.drop(3))
    }

    val part1Score = rucksacks.sumOf { it.score() }
    val part2Score = elfGroups.sumOf { it.score() }
}

data class ElfGroup(val rucksacks: List<Rucksack>) {

    val badge = rucksacks[0].types.intersect(rucksacks[1].types).intersect(rucksacks[2].types).first()

    fun score() = badge.day3Score()

    override fun toString(): String {
        return "[${rucksacks[0].input}][${rucksacks[1].input}][${rucksacks[2].input}][badge=$badge]"
    }
}

data class Rucksack(val input: String) {
    private val compartment1 = input.take(input.length / 2)
    private val compartment2 = input.takeLast(input.length / 2)

    private val duplicate = compartment1.toList().toSet().intersect(compartment2.toList().toSet()).first()

    val types = input.toList().toSet()

    fun score(): Int {
        return duplicate.day3Score()
    }
    override fun toString(): String {
        return "[Compartment1=$compartment1][Compartment2 = $compartment2][duplicate = $duplicate][score = ${score()}]"
    }
}

fun Char.day3Score(): Int {
    return if (this.isLowerCase()) {
        this.toInt() - 96
    } else {
        this.toInt() - 38
    }
}

fun main() {
    val rucksackOrganizerTest = Day3().getOrganizer("/day3_test.txt")
    val rucksackOrganizerInput = Day3().getOrganizer("/day3_input.txt")

    //rucksackOrganizer.rucksacks.forEach { println(it) }
    println("Part 1 score: ${rucksackOrganizerTest.part1Score}")
    println("Part 1 score: ${rucksackOrganizerInput.part1Score}")
    println("Part 2 score: ${rucksackOrganizerTest.part2Score}")
    println("Part 2 score: ${rucksackOrganizerInput.part2Score}")

    //println("ElfGroups: ${rucksackOrganizerTest.elfGroups}")
}

Compiled from "Day3.kt"
public final class day3.Day3 {
  public day3.Day3();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final day3.RucksackOrganizer getOrganizer(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String filename
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #25                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      10: aload_1
      11: invokevirtual #31                 // Method java/lang/Class.getResourceAsStream:(Ljava/lang/String;)Ljava/io/InputStream;
      14: dup
      15: ldc           #33                 // String getResourceAsStream(...)
      17: invokestatic  #36                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      20: astore_3
      21: getstatic     #42                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      24: astore        4
      26: new           #44                 // class java/io/InputStreamReader
      29: dup
      30: aload_3
      31: aload         4
      33: invokespecial #47                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      36: checkcast     #49                 // class java/io/Reader
      39: astore        5
      41: sipush        8192
      44: istore        6
      46: aload         5
      48: instanceof    #51                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         5
      56: checkcast     #51                 // class java/io/BufferedReader
      59: goto          73
      62: new           #51                 // class java/io/BufferedReader
      65: dup
      66: aload         5
      68: iload         6
      70: invokespecial #54                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      73: checkcast     #49                 // class java/io/Reader
      76: invokestatic  #60                 // Method kotlin/io/TextStreamsKt.readLines:(Ljava/io/Reader;)Ljava/util/List;
      79: astore_2
      80: new           #62                 // class day3/RucksackOrganizer
      83: dup
      84: aload_2
      85: invokespecial #65                 // Method day3/RucksackOrganizer."<init>":(Ljava/util/List;)V
      88: areturn
}

Compiled from "Day3.kt"
public final class day3.Day3Kt {
  public static final int day3Score(char);
    Code:
       0: iload_0
       1: invokestatic  #12                 // Method java/lang/Character.isLowerCase:(C)Z
       4: ifeq          14
       7: iload_0
       8: bipush        96
      10: isub
      11: goto          18
      14: iload_0
      15: bipush        38
      17: isub
      18: ireturn

  public static final void main();
    Code:
       0: new           #18                 // class day3/Day3
       3: dup
       4: invokespecial #21                 // Method day3/Day3."<init>":()V
       7: ldc           #23                 // String /day3_test.txt
       9: invokevirtual #27                 // Method day3/Day3.getOrganizer:(Ljava/lang/String;)Lday3/RucksackOrganizer;
      12: astore_0
      13: new           #18                 // class day3/Day3
      16: dup
      17: invokespecial #21                 // Method day3/Day3."<init>":()V
      20: ldc           #29                 // String /day3_input.txt
      22: invokevirtual #27                 // Method day3/Day3.getOrganizer:(Ljava/lang/String;)Lday3/RucksackOrganizer;
      25: astore_1
      26: new           #31                 // class java/lang/StringBuilder
      29: dup
      30: invokespecial #32                 // Method java/lang/StringBuilder."<init>":()V
      33: ldc           #34                 // String Part 1 score:
      35: invokevirtual #38                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      38: aload_0
      39: invokevirtual #44                 // Method day3/RucksackOrganizer.getPart1Score:()I
      42: invokevirtual #47                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      45: invokevirtual #51                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      48: getstatic     #57                 // Field java/lang/System.out:Ljava/io/PrintStream;
      51: swap
      52: invokevirtual #63                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      55: new           #31                 // class java/lang/StringBuilder
      58: dup
      59: invokespecial #32                 // Method java/lang/StringBuilder."<init>":()V
      62: ldc           #34                 // String Part 1 score:
      64: invokevirtual #38                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      67: aload_1
      68: invokevirtual #44                 // Method day3/RucksackOrganizer.getPart1Score:()I
      71: invokevirtual #47                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      74: invokevirtual #51                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      77: getstatic     #57                 // Field java/lang/System.out:Ljava/io/PrintStream;
      80: swap
      81: invokevirtual #63                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      84: new           #31                 // class java/lang/StringBuilder
      87: dup
      88: invokespecial #32                 // Method java/lang/StringBuilder."<init>":()V
      91: ldc           #65                 // String Part 2 score:
      93: invokevirtual #38                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      96: aload_0
      97: invokevirtual #68                 // Method day3/RucksackOrganizer.getPart2Score:()I
     100: invokevirtual #47                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     103: invokevirtual #51                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     106: getstatic     #57                 // Field java/lang/System.out:Ljava/io/PrintStream;
     109: swap
     110: invokevirtual #63                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     113: new           #31                 // class java/lang/StringBuilder
     116: dup
     117: invokespecial #32                 // Method java/lang/StringBuilder."<init>":()V
     120: ldc           #65                 // String Part 2 score:
     122: invokevirtual #38                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     125: aload_1
     126: invokevirtual #68                 // Method day3/RucksackOrganizer.getPart2Score:()I
     129: invokevirtual #47                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
     132: invokevirtual #51                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     135: getstatic     #57                 // Field java/lang/System.out:Ljava/io/PrintStream;
     138: swap
     139: invokevirtual #63                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     142: return

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


package day2

import java.lang.IllegalArgumentException

class Day2 {
    fun getGameStore(filename: String): GameStore {
        val readLines = this::class.java.getResourceAsStream(filename).bufferedReader().readLines()

        return GameStore(
            readLines.map { Round(Shape.fromString(it[0]), Shape.fromString(it[2])) },
            readLines.map { Round(Shape.fromString(it[0]), Shape.fromStringv2(Shape.fromString(it[0]), it[2])) }
        )
    }
}

sealed class Shape {
    abstract fun score(): Int
    abstract fun winShape(): Shape
    abstract fun drawShape(): Shape
    abstract fun loseShape(): Shape

    object Rock: Shape() {
        override fun score(): Int = 1
        override fun winShape(): Shape = Paper
        override fun drawShape(): Shape = Rock
        override fun loseShape(): Shape = Scissors
    }
    object Paper: Shape() {
        override fun score(): Int = 2
        override fun winShape(): Shape = Scissors
        override fun drawShape(): Shape = Paper
        override fun loseShape(): Shape = Rock
    }
    object Scissors: Shape() {
        override fun score(): Int = 3
        override fun winShape(): Shape = Rock
        override fun drawShape(): Shape = Scissors
        override fun loseShape(): Shape = Paper
    }

    companion object {
        fun fromString(input: Char): Shape {
            return when(input) {
                'A' -> Rock
                'B' -> Paper
                'C' -> Scissors
                'Y' -> Paper
                'X' -> Rock
                'Z' -> Scissors
                else -> throw IllegalArgumentException("Unknown shape $input")
            }
        }

        fun fromStringv2(opponent: Shape, input: Char): Shape {
            return when(input) {
                'Y' -> opponent.drawShape()
                'X' -> opponent.loseShape()
                'Z' -> opponent.winShape()
                else -> throw IllegalArgumentException("Unknown shape $input")
            }
        }
    }
}

class Round(private val opponent: Shape, private val you: Shape) {
    override fun toString(): String {
        return "$opponent vs $you"
    }

    private fun shapeScore(): Int = you.score()

    private fun roundScore(): Int {
        return when(opponent) {
            Shape.Paper -> when(you) {
                Shape.Paper -> 3
                Shape.Rock -> 0
                Shape.Scissors -> 6
            }
            Shape.Rock -> when(you) {
                Shape.Paper -> 6
                Shape.Rock -> 3
                Shape.Scissors -> 0
            }
            Shape.Scissors -> when(you) {
                Shape.Paper -> 0
                Shape.Rock -> 6
                Shape.Scissors -> 3
            }
        }
    }

    fun score(): Int = roundScore() + shapeScore()
}

class GameStore(val roundList: List<Round>, val roundListPart2: List<Round>) {

    fun score(): Int = roundList.sumOf { it.score() }
    fun scorePart2(): Int = roundListPart2.sumOf { it.score() }
}

fun main() {
    println(Day2().getGameStore("/day2_test.txt").score())
    println(Day2().getGameStore("/day2_input.txt").score())

    println(Day2().getGameStore("/day2_test.txt").scorePart2())
    println(Day2().getGameStore("/day2_input.txt").scorePart2())
}

Compiled from "Day2.kt"
public final class day2.Day2 {
  public day2.Day2();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final day2.GameStore getGameStore(java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String filename
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokevirtual #25                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      10: aload_1
      11: invokevirtual #31                 // Method java/lang/Class.getResourceAsStream:(Ljava/lang/String;)Ljava/io/InputStream;
      14: dup
      15: ldc           #33                 // String getResourceAsStream(...)
      17: invokestatic  #36                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      20: astore_3
      21: getstatic     #42                 // Field kotlin/text/Charsets.UTF_8:Ljava/nio/charset/Charset;
      24: astore        4
      26: new           #44                 // class java/io/InputStreamReader
      29: dup
      30: aload_3
      31: aload         4
      33: invokespecial #47                 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V
      36: checkcast     #49                 // class java/io/Reader
      39: astore        5
      41: sipush        8192
      44: istore        6
      46: aload         5
      48: instanceof    #51                 // class java/io/BufferedReader
      51: ifeq          62
      54: aload         5
      56: checkcast     #51                 // class java/io/BufferedReader
      59: goto          73
      62: new           #51                 // class java/io/BufferedReader
      65: dup
      66: aload         5
      68: iload         6
      70: invokespecial #54                 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;I)V
      73: checkcast     #49                 // class java/io/Reader
      76: invokestatic  #60                 // Method kotlin/io/TextStreamsKt.readLines:(Ljava/io/Reader;)Ljava/util/List;
      79: astore_2
      80: aload_2
      81: checkcast     #62                 // class java/lang/Iterable
      84: astore_3
      85: iconst_0
      86: istore        4
      88: aload_3
      89: astore        5
      91: new           #64                 // class java/util/ArrayList
      94: dup
      95: aload_3
      96: bipush        10
      98: invokestatic  #70                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     101: invokespecial #73                 // Method java/util/ArrayList."<init>":(I)V
     104: checkcast     #75                 // class java/util/Collection
     107: astore        6
     109: iconst_0
     110: istore        7
     112: aload         5
     114: invokeinterface #79,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     119: astore        8
     121: aload         8
     123: invokeinterface #85,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     128: ifeq          197
     131: aload         8
     133: invokeinterface #89,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     138: astore        9
     140: aload         6
     142: aload         9
     144: checkcast     #91                 // class java/lang/String
     147: astore        10
     149: astore        12
     151: iconst_0
     152: istore        11
     154: new           #93                 // class day2/Round
     157: dup
     158: getstatic     #99                 // Field day2/Shape.Companion:Lday2/Shape$Companion;
     161: aload         10
     163: iconst_0
     164: invokevirtual #103                // Method java/lang/String.charAt:(I)C
     167: invokevirtual #109                // Method day2/Shape$Companion.fromString:(C)Lday2/Shape;
     170: getstatic     #99                 // Field day2/Shape.Companion:Lday2/Shape$Companion;
     173: aload         10
     175: iconst_2
     176: invokevirtual #103                // Method java/lang/String.charAt:(I)C
     179: invokevirtual #109                // Method day2/Shape$Companion.fromString:(C)Lday2/Shape;
     182: invokespecial #112                // Method day2/Round."<init>":(Lday2/Shape;Lday2/Shape;)V
     185: aload         12
     187: swap
     188: invokeinterface #116,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     193: pop
     194: goto          121
     197: aload         6
     199: checkcast     #118                // class java/util/List
     202: nop
     203: aload_2
     204: checkcast     #62                 // class java/lang/Iterable
     207: astore_3
     208: astore        12
     210: iconst_0
     211: istore        4
     213: aload_3
     214: astore        5
     216: new           #64                 // class java/util/ArrayList
     219: dup
     220: aload_3
     221: bipush        10
     223: invokestatic  #70                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
     226: invokespecial #73                 // Method java/util/ArrayList."<init>":(I)V
     229: checkcast     #75                 // class java/util/Collection
     232: astore        6
     234: iconst_0
     235: istore        7
     237: aload         5
     239: invokeinterface #79,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     244: astore        8
     246: aload         8
     248: invokeinterface #85,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     253: ifeq          334
     256: aload         8
     258: invokeinterface #89,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     263: astore        9
     265: aload         6
     267: aload         9
     269: checkcast     #91                 // class java/lang/String
     272: astore        10
     274: astore        13
     276: iconst_0
     277: istore        11
     279: new           #93                 // class day2/Round
     282: dup
     283: getstatic     #99                 // Field day2/Shape.Companion:Lday2/Shape$Companion;
     286: aload         10
     288: iconst_0
     289: invokevirtual #103                // Method java/lang/String.charAt:(I)C
     292: invokevirtual #109                // Method day2/Shape$Companion.fromString:(C)Lday2/Shape;
     295: getstatic     #99                 // Field day2/Shape.Companion:Lday2/Shape$Companion;
     298: getstatic     #99                 // Field day2/Shape.Companion:Lday2/Shape$Companion;
     301: aload         10
     303: iconst_0
     304: invokevirtual #103                // Method java/lang/String.charAt:(I)C
     307: invokevirtual #109                // Method day2/Shape$Companion.fromString:(C)Lday2/Shape;
     310: aload         10
     312: iconst_2
     313: invokevirtual #103                // Method java/lang/String.charAt:(I)C
     316: invokevirtual #122                // Method day2/Shape$Companion.fromStringv2:(Lday2/Shape;C)Lday2/Shape;
     319: invokespecial #112                // Method day2/Round."<init>":(Lday2/Shape;Lday2/Shape;)V
     322: aload         13
     324: swap
     325: invokeinterface #116,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     330: pop
     331: goto          246
     334: aload         6
     336: checkcast     #118                // class java/util/List
     339: nop
     340: aload         12
     342: swap
     343: astore        14
     345: astore        15
     347: new           #124                // class day2/GameStore
     350: dup
     351: aload         15
     353: aload         14
     355: invokespecial #127                // Method day2/GameStore."<init>":(Ljava/util/List;Ljava/util/List;)V
     358: areturn
}

Compiled from "Day2.kt"
public final class day2.Day2Kt {
  public static final void main();
    Code:
       0: new           #8                  // class day2/Day2
       3: dup
       4: invokespecial #11                 // Method day2/Day2."<init>":()V
       7: ldc           #13                 // String /day2_test.txt
       9: invokevirtual #17                 // Method day2/Day2.getGameStore:(Ljava/lang/String;)Lday2/GameStore;
      12: invokevirtual #23                 // Method day2/GameStore.score:()I
      15: istore_0
      16: getstatic     #29                 // Field java/lang/System.out:Ljava/io/PrintStream;
      19: iload_0
      20: invokevirtual #35                 // Method java/io/PrintStream.println:(I)V
      23: new           #8                  // class day2/Day2
      26: dup
      27: invokespecial #11                 // Method day2/Day2."<init>":()V
      30: ldc           #37                 // String /day2_input.txt
      32: invokevirtual #17                 // Method day2/Day2.getGameStore:(Ljava/lang/String;)Lday2/GameStore;
      35: invokevirtual #23                 // Method day2/GameStore.score:()I
      38: istore_0
      39: getstatic     #29                 // Field java/lang/System.out:Ljava/io/PrintStream;
      42: iload_0
      43: invokevirtual #35                 // Method java/io/PrintStream.println:(I)V
      46: new           #8                  // class day2/Day2
      49: dup
      50: invokespecial #11                 // Method day2/Day2."<init>":()V
      53: ldc           #13                 // String /day2_test.txt
      55: invokevirtual #17                 // Method day2/Day2.getGameStore:(Ljava/lang/String;)Lday2/GameStore;
      58: invokevirtual #40                 // Method day2/GameStore.scorePart2:()I
      61: istore_0
      62: getstatic     #29                 // Field java/lang/System.out:Ljava/io/PrintStream;
      65: iload_0
      66: invokevirtual #35                 // Method java/io/PrintStream.println:(I)V
      69: new           #8                  // class day2/Day2
      72: dup
      73: invokespecial #11                 // Method day2/Day2."<init>":()V
      76: ldc           #37                 // String /day2_input.txt
      78: invokevirtual #17                 // Method day2/Day2.getGameStore:(Ljava/lang/String;)Lday2/GameStore;
      81: invokevirtual #40                 // Method day2/GameStore.scorePart2:()I
      84: istore_0
      85: getstatic     #29                 // Field java/lang/System.out:Ljava/io/PrintStream;
      88: iload_0
      89: invokevirtual #35                 // Method java/io/PrintStream.println:(I)V
      92: return

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