Advent Of Code Kotlin (AocKt) 0.2.1 Help

Workflow

After setting up your project template, or configuring your own, this is the place to start learning all about using AocKt!

This tutorial goes very in-depth to cover all the bases, and also be more accessible to beginners. Don't be discouraged by its length, you only need it for the first run, after which it will become reflex.

Good luck!

Prerequisite: Project Structure

AocKt runs entirely locally, by reading files on disk. For each puzzle, you will end up with five files, explained later. For reference, they will be distributed as such:

projectDir ├── inputs │ └── aockt │ └── y2015 │ └── d01 │ └── input.txt │ └── solution_part1.txt │ └── solution_part2.txt ├── solutions │ └── aockt │ └── y2015 │ └── Y2015D01.kt └── tests └── aockt └── y2015 └── Y2015D01Test.kt
projectDir ├── src/main/kotlin │ └── aockt │ └── y2015 │ └── Y2015D01.kt ├── src/test/kotlin │ └── aockt │ └── y2015 │ └── Y2015D01Test.kt └── src/test/resources └── aockt └── y2015 └── d01 └── input.txt └── solution_part1.txt └── solution_part2.txt
  • Your implementations go into solutions. While it is not a requirement to split them into packages by year or have a specific naming convention, doing so helps with organising.

  • Unit tests go into tests and should have the same structure as your solutions.

  • Your puzzle inputs go into inputs. For these, the format is enforced:

    • Each day has a directory as a base path: /aockt/y[year]/d[twoDigitDay]

    • In that directory, the input is in the input.txt file.

    • The solutions use solution_part1.txt and solution_part2.txt. They are added in as discovered.

Step 0: Read And Understand The Puzzle

Have a thorough read of the puzzle. The devil's in the details, and also have a look at your puzzle input. Sometimes you'll get extra insight by observing patterns in inputs!

After you think you have a clear initial understanding, move on.

Step 1: Get Your Puzzle Input

Copy your puzzle input and paste it in inputs/aockt/y2015/d01/input.txt.

Step 2: Create Your Solution Stubs

Create a class or object for your solution that implements the Solution type.

In your solutions, create:

package aockt.y2015 import io.github.jadarma.aockt.core.Solution object Y2015D01 : Solution

Following the same logic, create its tests analog:

package aockt.y2015 import io.github.jadarma.aockt.test.AdventDay import io.github.jadarma.aockt.test.AdventSpec @AdventDay(2015, 1, "Not Quite Lisp") class Y2015D01Test : AdventSpec<Y2015D01>({})

Step 3: Define your Test Cases

Inside the AdventSpec's constructor, you pass in the configuration DSL. Each puzzle part has its own context.

Let's start with part one:

package aockt.y2015 import io.github.jadarma.aockt.test.AdventDay import io.github.jadarma.aockt.test.AdventSpec @AdventDay(2015, 1, "Not Quite Lisp") class Y2015D01Test : AdventSpec<Y2015D01>({ partOne() })

Like many other puzzles, this day provides you with example inputs and outputs to test your solution.

If that is the case, you can define them in a lambda. The syntax is "string" shouldOutput "output", the output can be a string, or a number, it will be checked against its string representation. For multiple inputs, listOf("string") shouldAllOutput "output" is synonymous.

package aockt.y2015 import io.github.jadarma.aockt.test.AdventDay import io.github.jadarma.aockt.test.AdventSpec @AdventDay(2015, 1, "Not Quite Lisp") class Y2015D01Test : AdventSpec<Y2015D01>({ partOne { listOf("(())", "()()") shouldAllOutput 0 listOf("(((", "(()(()(", "))(((((") shouldAllOutput 3 listOf("())", "))(") shouldAllOutput -1 listOf(")))", ")())())") shouldAllOutput -3 } })

It is recommended you use the Kotest IntelliJ Plugin, so you can run the test via the gutter icon.

Your first run should look like this:

Results of the initial run.

Each example has its own test, and since you added your input, it also tests against that.

Step 4: Implement Your Solution

Go back to your solution and implement partOne. The function can return anything representable by a string. In practical terms, it will always be either a string or an integer.

Have a try at the problem:

package aockt.y2015 import io.github.jadarma.aockt.core.Solution object Y2015D01 : Solution { override fun partOne(input: String): Int = spoilers() }

Step 5: Test Your Solution

Run the test again as you go.

Results of the second run.

Hmm, seems like we're missing something. Clicking on each example will show us the actual versus expected result. In this case, seems we have a sign flip issue.

Results of the third run.

That was it!

Step 5: Submit Your Answer

Now that you're confident your solution is correct, run it on your own input (by reverting the executionMode if you set it earlier).

Results of user input.

Your solution gave an answer, but you don't know if it's correct. Go back to the website and submit it.

Congratulations on collecting the first star!

If not, try to look at what's special in your input, or hunt down any bugs.

Once you have verified the right answer, paste it in inputs/aockt/y2015/d01/solution_part1.txt. Now, when you run the test, your code will be tested against the known answer:

Results of verified solution.

Step 6: Tackle Part Two

There is one more star to be gained. The website will give you a second task based on the same puzzle.

You can ignore part one tests for now, and set partOne(enabled = false).

Then repeat the same steps:

  • Implement fun partTwo(input: String) in your solution.

  • Define your test with partTwo() and define any new examples.

  • Run the tests until you get a solution candidate.

  • After getting the right answer, save it to solution_part2.txt.

Congratulations on collecting both stars! ⭐⭐

Step 7: Refactor Fearlessly (and Optionally)

After completing the puzzle, your test should look like this:

package aockt.y2015 import io.github.jadarma.aockt.test.AdventDay import io.github.jadarma.aockt.test.AdventSpec @AdventDay(2015, 1, "Not Quite Lisp") class Y2015D01Test : AdventSpec<Y2015D01>({ partOne { listOf("(())", "()()") shouldAllOutput 0 listOf("(((", "(()(()(") shouldAllOutput 3 listOf("())", "))(") shouldAllOutput -1 listOf(")))", ")())())") shouldAllOutput -3 } partTwo { ")" shouldOutput 1 "()())" shouldOutput 5 } })

And your test runs like this:

Results of both verified solutions.

Now you can save your changes, clean up your code, refactor some lines, if that's your thing. Run tests often, they will help you know when you made a logic-altering change.

That's it! Now relax and get ready for the next day!

Last modified: 17 November 2024