diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a8da543
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+### Gradle template
+.gradle
+gradle/
+**/build/
+!src/**/build/
+
+### JetBrains template
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+.idea/misc.xml
+
+**viz/
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..d612e6a
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,16 @@
+plugins {
+ id 'org.jetbrains.kotlin.jvm' version '1.7.21'
+ id 'application'
+}
+
+repositories {
+ mavenCentral()
+}
+
+compileKotlin {
+ kotlinOptions.jvmTarget = '1.8'
+}
+
+dependencies {
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..7fc6f1f
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+kotlin.code.style=official
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..2fe81a7
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,183 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..62bd9b9
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,103 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/local.properties b/local.properties
new file mode 100644
index 0000000..e69de29
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..d2cf46f
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'AdventofCode2022'
diff --git a/src/main/kotlin/Base.kt b/src/main/kotlin/Base.kt
new file mode 100644
index 0000000..1e75900
--- /dev/null
+++ b/src/main/kotlin/Base.kt
@@ -0,0 +1,63 @@
+
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
+import java.io.File
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.ExperimentalTime
+import kotlin.time.measureTime
+import kotlin.time.measureTimedValue
+
+private fun getInputFile(): File {
+ val name = Throwable().stackTrace.first { it.className.contains("day") }.fileName
+ val day = name.substringBefore("_").removePrefix("Day").padStart(2, '0')
+ val part = name.substringAfter("_").removeSuffix(".kt")
+ val file = File("src/main/kotlin/day$day/input$part.txt")
+ return if (file.readText().isBlank()) {
+ File("src/main/kotlin/day$day/input1.txt")
+ } else file
+}
+
+private fun getInput(): String {
+ return getInputFile().readText().trim()
+}
+
+fun printInput(input: String) {
+ if (input.contains("\n")) {
+ if (input.lines().size >= 10) {
+ println("Input:")
+ println(input.lines().take(2).joinToString("\n"))
+ println("[> not showing ${input.lines().size - 4} lines <]")
+ println(input.lines().takeLast(2).joinToString("\n"))
+ } else {
+ println("Input:\n$input")
+ }
+ } else {
+ println("Input: $input")
+ }
+}
+
+@OptIn(ExperimentalTime::class)
+fun solve(additionalTiming: Boolean = false, solve: (List) -> Any?) {
+ val input = getInput()
+ printInput(input)
+ val (answer, duration) = measureTimedValue {
+ solve(input.lines()).toString()
+ }
+ val time = "${String.format("%.3f", duration.inWholeMicroseconds / 1000.0)}ms"
+ if (answer != "kotlin.Unit") {
+ println("Out: $answer [$time]")
+ Toolkit.getDefaultToolkit().systemClipboard.setContents(StringSelection(answer), null)
+ Thread.sleep(200) // Wait so the system has chance to notice the clipboard change
+ } else {
+ println("No answer [$time]")
+ }
+
+ if (additionalTiming) {
+ println("Rerunning for timing")
+ val count = if (duration < 100.milliseconds) 1000 else 10
+ val fastest = List(count) {
+ measureTime { solve(input.lines()) }
+ }.minOrNull()!!
+ println("Fastest time: [${String.format("%.3f", fastest.inWholeMicroseconds / 1000.0)}ms]")
+ }
+}
diff --git a/src/main/kotlin/day01/Day1_1.kt b/src/main/kotlin/day01/Day1_1.kt
new file mode 100644
index 0000000..12897d1
--- /dev/null
+++ b/src/main/kotlin/day01/Day1_1.kt
@@ -0,0 +1,7 @@
+package day01
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day01/Day1_2.kt b/src/main/kotlin/day01/Day1_2.kt
new file mode 100644
index 0000000..12897d1
--- /dev/null
+++ b/src/main/kotlin/day01/Day1_2.kt
@@ -0,0 +1,7 @@
+package day01
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day01/input1.txt b/src/main/kotlin/day01/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day01/input2.txt b/src/main/kotlin/day01/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day02/Day2_1.kt b/src/main/kotlin/day02/Day2_1.kt
new file mode 100644
index 0000000..697a89a
--- /dev/null
+++ b/src/main/kotlin/day02/Day2_1.kt
@@ -0,0 +1,7 @@
+package day02
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day02/Day2_2.kt b/src/main/kotlin/day02/Day2_2.kt
new file mode 100644
index 0000000..697a89a
--- /dev/null
+++ b/src/main/kotlin/day02/Day2_2.kt
@@ -0,0 +1,7 @@
+package day02
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day02/input1.txt b/src/main/kotlin/day02/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day02/input2.txt b/src/main/kotlin/day02/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day03/Day3_1.kt b/src/main/kotlin/day03/Day3_1.kt
new file mode 100644
index 0000000..09f6d94
--- /dev/null
+++ b/src/main/kotlin/day03/Day3_1.kt
@@ -0,0 +1,7 @@
+package day03
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day03/Day3_2.kt b/src/main/kotlin/day03/Day3_2.kt
new file mode 100644
index 0000000..09f6d94
--- /dev/null
+++ b/src/main/kotlin/day03/Day3_2.kt
@@ -0,0 +1,7 @@
+package day03
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day03/input1.txt b/src/main/kotlin/day03/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day03/input2.txt b/src/main/kotlin/day03/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day04/Day4_1.kt b/src/main/kotlin/day04/Day4_1.kt
new file mode 100644
index 0000000..fb0ece9
--- /dev/null
+++ b/src/main/kotlin/day04/Day4_1.kt
@@ -0,0 +1,7 @@
+package day04
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day04/Day4_2.kt b/src/main/kotlin/day04/Day4_2.kt
new file mode 100644
index 0000000..fb0ece9
--- /dev/null
+++ b/src/main/kotlin/day04/Day4_2.kt
@@ -0,0 +1,7 @@
+package day04
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day04/input1.txt b/src/main/kotlin/day04/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day04/input2.txt b/src/main/kotlin/day04/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day05/Day5_1.kt b/src/main/kotlin/day05/Day5_1.kt
new file mode 100644
index 0000000..2147a38
--- /dev/null
+++ b/src/main/kotlin/day05/Day5_1.kt
@@ -0,0 +1,7 @@
+package day05
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day05/Day5_2.kt b/src/main/kotlin/day05/Day5_2.kt
new file mode 100644
index 0000000..2147a38
--- /dev/null
+++ b/src/main/kotlin/day05/Day5_2.kt
@@ -0,0 +1,7 @@
+package day05
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day05/input1.txt b/src/main/kotlin/day05/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day05/input2.txt b/src/main/kotlin/day05/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day06/Day6_1.kt b/src/main/kotlin/day06/Day6_1.kt
new file mode 100644
index 0000000..e127ad0
--- /dev/null
+++ b/src/main/kotlin/day06/Day6_1.kt
@@ -0,0 +1,7 @@
+package day06
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day06/Day6_2.kt b/src/main/kotlin/day06/Day6_2.kt
new file mode 100644
index 0000000..e127ad0
--- /dev/null
+++ b/src/main/kotlin/day06/Day6_2.kt
@@ -0,0 +1,7 @@
+package day06
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day06/input1.txt b/src/main/kotlin/day06/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day06/input2.txt b/src/main/kotlin/day06/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day07/Day7_1.kt b/src/main/kotlin/day07/Day7_1.kt
new file mode 100644
index 0000000..4cf1a66
--- /dev/null
+++ b/src/main/kotlin/day07/Day7_1.kt
@@ -0,0 +1,7 @@
+package day07
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day07/Day7_2.kt b/src/main/kotlin/day07/Day7_2.kt
new file mode 100644
index 0000000..4cf1a66
--- /dev/null
+++ b/src/main/kotlin/day07/Day7_2.kt
@@ -0,0 +1,7 @@
+package day07
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day07/input1.txt b/src/main/kotlin/day07/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day07/input2.txt b/src/main/kotlin/day07/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day08/Day8_1.kt b/src/main/kotlin/day08/Day8_1.kt
new file mode 100644
index 0000000..8680191
--- /dev/null
+++ b/src/main/kotlin/day08/Day8_1.kt
@@ -0,0 +1,7 @@
+package day08
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day08/Day8_2.kt b/src/main/kotlin/day08/Day8_2.kt
new file mode 100644
index 0000000..8680191
--- /dev/null
+++ b/src/main/kotlin/day08/Day8_2.kt
@@ -0,0 +1,7 @@
+package day08
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day08/input1.txt b/src/main/kotlin/day08/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day08/input2.txt b/src/main/kotlin/day08/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day09/Day9_1.kt b/src/main/kotlin/day09/Day9_1.kt
new file mode 100644
index 0000000..31d0b07
--- /dev/null
+++ b/src/main/kotlin/day09/Day9_1.kt
@@ -0,0 +1,7 @@
+package day09
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day09/Day9_2.kt b/src/main/kotlin/day09/Day9_2.kt
new file mode 100644
index 0000000..31d0b07
--- /dev/null
+++ b/src/main/kotlin/day09/Day9_2.kt
@@ -0,0 +1,7 @@
+package day09
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day09/input1.txt b/src/main/kotlin/day09/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day09/input2.txt b/src/main/kotlin/day09/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day10/Day10_1.kt b/src/main/kotlin/day10/Day10_1.kt
new file mode 100644
index 0000000..6845ba7
--- /dev/null
+++ b/src/main/kotlin/day10/Day10_1.kt
@@ -0,0 +1,7 @@
+package day10
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day10/Day10_2.kt b/src/main/kotlin/day10/Day10_2.kt
new file mode 100644
index 0000000..6845ba7
--- /dev/null
+++ b/src/main/kotlin/day10/Day10_2.kt
@@ -0,0 +1,7 @@
+package day10
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day10/input1.txt b/src/main/kotlin/day10/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day10/input2.txt b/src/main/kotlin/day10/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day11/Day11_1.kt b/src/main/kotlin/day11/Day11_1.kt
new file mode 100644
index 0000000..aaa1e38
--- /dev/null
+++ b/src/main/kotlin/day11/Day11_1.kt
@@ -0,0 +1,7 @@
+package day11
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day11/Day11_2.kt b/src/main/kotlin/day11/Day11_2.kt
new file mode 100644
index 0000000..aaa1e38
--- /dev/null
+++ b/src/main/kotlin/day11/Day11_2.kt
@@ -0,0 +1,7 @@
+package day11
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day11/input1.txt b/src/main/kotlin/day11/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day11/input2.txt b/src/main/kotlin/day11/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day12/Day12_1.kt b/src/main/kotlin/day12/Day12_1.kt
new file mode 100644
index 0000000..352fca0
--- /dev/null
+++ b/src/main/kotlin/day12/Day12_1.kt
@@ -0,0 +1,7 @@
+package day12
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day12/Day12_2.kt b/src/main/kotlin/day12/Day12_2.kt
new file mode 100644
index 0000000..352fca0
--- /dev/null
+++ b/src/main/kotlin/day12/Day12_2.kt
@@ -0,0 +1,7 @@
+package day12
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day12/input1.txt b/src/main/kotlin/day12/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day12/input2.txt b/src/main/kotlin/day12/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day13/Day13_1.kt b/src/main/kotlin/day13/Day13_1.kt
new file mode 100644
index 0000000..4bbacfb
--- /dev/null
+++ b/src/main/kotlin/day13/Day13_1.kt
@@ -0,0 +1,7 @@
+package day13
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day13/Day13_2.kt b/src/main/kotlin/day13/Day13_2.kt
new file mode 100644
index 0000000..4bbacfb
--- /dev/null
+++ b/src/main/kotlin/day13/Day13_2.kt
@@ -0,0 +1,7 @@
+package day13
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day13/input1.txt b/src/main/kotlin/day13/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day13/input2.txt b/src/main/kotlin/day13/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day14/Day14_1.kt b/src/main/kotlin/day14/Day14_1.kt
new file mode 100644
index 0000000..77dff57
--- /dev/null
+++ b/src/main/kotlin/day14/Day14_1.kt
@@ -0,0 +1,7 @@
+package day14
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day14/Day14_2.kt b/src/main/kotlin/day14/Day14_2.kt
new file mode 100644
index 0000000..77dff57
--- /dev/null
+++ b/src/main/kotlin/day14/Day14_2.kt
@@ -0,0 +1,7 @@
+package day14
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day14/input1.txt b/src/main/kotlin/day14/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day14/input2.txt b/src/main/kotlin/day14/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day15/Day15_1.kt b/src/main/kotlin/day15/Day15_1.kt
new file mode 100644
index 0000000..9cc1732
--- /dev/null
+++ b/src/main/kotlin/day15/Day15_1.kt
@@ -0,0 +1,7 @@
+package day15
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day15/Day15_2.kt b/src/main/kotlin/day15/Day15_2.kt
new file mode 100644
index 0000000..9cc1732
--- /dev/null
+++ b/src/main/kotlin/day15/Day15_2.kt
@@ -0,0 +1,7 @@
+package day15
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day15/input1.txt b/src/main/kotlin/day15/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day15/input2.txt b/src/main/kotlin/day15/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day16/Day16_1.kt b/src/main/kotlin/day16/Day16_1.kt
new file mode 100644
index 0000000..6f8f4fc
--- /dev/null
+++ b/src/main/kotlin/day16/Day16_1.kt
@@ -0,0 +1,7 @@
+package day16
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day16/Day16_2.kt b/src/main/kotlin/day16/Day16_2.kt
new file mode 100644
index 0000000..6f8f4fc
--- /dev/null
+++ b/src/main/kotlin/day16/Day16_2.kt
@@ -0,0 +1,7 @@
+package day16
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day16/input1.txt b/src/main/kotlin/day16/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day16/input2.txt b/src/main/kotlin/day16/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day17/Day17_1.kt b/src/main/kotlin/day17/Day17_1.kt
new file mode 100644
index 0000000..52836d8
--- /dev/null
+++ b/src/main/kotlin/day17/Day17_1.kt
@@ -0,0 +1,7 @@
+package day17
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day17/Day17_2.kt b/src/main/kotlin/day17/Day17_2.kt
new file mode 100644
index 0000000..52836d8
--- /dev/null
+++ b/src/main/kotlin/day17/Day17_2.kt
@@ -0,0 +1,7 @@
+package day17
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day17/input1.txt b/src/main/kotlin/day17/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day17/input2.txt b/src/main/kotlin/day17/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day18/Day18_1.kt b/src/main/kotlin/day18/Day18_1.kt
new file mode 100644
index 0000000..e887f71
--- /dev/null
+++ b/src/main/kotlin/day18/Day18_1.kt
@@ -0,0 +1,7 @@
+package day18
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day18/Day18_2.kt b/src/main/kotlin/day18/Day18_2.kt
new file mode 100644
index 0000000..e887f71
--- /dev/null
+++ b/src/main/kotlin/day18/Day18_2.kt
@@ -0,0 +1,7 @@
+package day18
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day18/input1.txt b/src/main/kotlin/day18/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day18/input2.txt b/src/main/kotlin/day18/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day19/Day19_1.kt b/src/main/kotlin/day19/Day19_1.kt
new file mode 100644
index 0000000..f2502a0
--- /dev/null
+++ b/src/main/kotlin/day19/Day19_1.kt
@@ -0,0 +1,7 @@
+package day19
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day19/Day19_2.kt b/src/main/kotlin/day19/Day19_2.kt
new file mode 100644
index 0000000..f2502a0
--- /dev/null
+++ b/src/main/kotlin/day19/Day19_2.kt
@@ -0,0 +1,7 @@
+package day19
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day19/input1.txt b/src/main/kotlin/day19/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day19/input2.txt b/src/main/kotlin/day19/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day20/Day20_1.kt b/src/main/kotlin/day20/Day20_1.kt
new file mode 100644
index 0000000..cb7f5aa
--- /dev/null
+++ b/src/main/kotlin/day20/Day20_1.kt
@@ -0,0 +1,7 @@
+package day20
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day20/Day20_2.kt b/src/main/kotlin/day20/Day20_2.kt
new file mode 100644
index 0000000..cb7f5aa
--- /dev/null
+++ b/src/main/kotlin/day20/Day20_2.kt
@@ -0,0 +1,7 @@
+package day20
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day20/input1.txt b/src/main/kotlin/day20/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day20/input2.txt b/src/main/kotlin/day20/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day21/Day21_1.kt b/src/main/kotlin/day21/Day21_1.kt
new file mode 100644
index 0000000..f7baa12
--- /dev/null
+++ b/src/main/kotlin/day21/Day21_1.kt
@@ -0,0 +1,7 @@
+package day21
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day21/Day21_2.kt b/src/main/kotlin/day21/Day21_2.kt
new file mode 100644
index 0000000..f7baa12
--- /dev/null
+++ b/src/main/kotlin/day21/Day21_2.kt
@@ -0,0 +1,7 @@
+package day21
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day21/input1.txt b/src/main/kotlin/day21/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day21/input2.txt b/src/main/kotlin/day21/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day22/Day22_1.kt b/src/main/kotlin/day22/Day22_1.kt
new file mode 100644
index 0000000..71b6696
--- /dev/null
+++ b/src/main/kotlin/day22/Day22_1.kt
@@ -0,0 +1,7 @@
+package day22
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day22/Day22_2.kt b/src/main/kotlin/day22/Day22_2.kt
new file mode 100644
index 0000000..71b6696
--- /dev/null
+++ b/src/main/kotlin/day22/Day22_2.kt
@@ -0,0 +1,7 @@
+package day22
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day22/input1.txt b/src/main/kotlin/day22/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day22/input2.txt b/src/main/kotlin/day22/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day23/Day23_1.kt b/src/main/kotlin/day23/Day23_1.kt
new file mode 100644
index 0000000..d391bc1
--- /dev/null
+++ b/src/main/kotlin/day23/Day23_1.kt
@@ -0,0 +1,7 @@
+package day23
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day23/Day23_2.kt b/src/main/kotlin/day23/Day23_2.kt
new file mode 100644
index 0000000..d391bc1
--- /dev/null
+++ b/src/main/kotlin/day23/Day23_2.kt
@@ -0,0 +1,7 @@
+package day23
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day23/input1.txt b/src/main/kotlin/day23/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day23/input2.txt b/src/main/kotlin/day23/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day24/Day24_1.kt b/src/main/kotlin/day24/Day24_1.kt
new file mode 100644
index 0000000..3b2495d
--- /dev/null
+++ b/src/main/kotlin/day24/Day24_1.kt
@@ -0,0 +1,7 @@
+package day24
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day24/Day24_2.kt b/src/main/kotlin/day24/Day24_2.kt
new file mode 100644
index 0000000..3b2495d
--- /dev/null
+++ b/src/main/kotlin/day24/Day24_2.kt
@@ -0,0 +1,7 @@
+package day24
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day24/input1.txt b/src/main/kotlin/day24/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day24/input2.txt b/src/main/kotlin/day24/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day25/Day25_1.kt b/src/main/kotlin/day25/Day25_1.kt
new file mode 100644
index 0000000..5d1830f
--- /dev/null
+++ b/src/main/kotlin/day25/Day25_1.kt
@@ -0,0 +1,7 @@
+package day25
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day25/Day25_2.kt b/src/main/kotlin/day25/Day25_2.kt
new file mode 100644
index 0000000..5d1830f
--- /dev/null
+++ b/src/main/kotlin/day25/Day25_2.kt
@@ -0,0 +1,7 @@
+package day25
+
+import solve
+
+fun main() = solve { lines ->
+
+}
diff --git a/src/main/kotlin/day25/input1.txt b/src/main/kotlin/day25/input1.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/day25/input2.txt b/src/main/kotlin/day25/input2.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/kotlin/utils/Geometry.kt b/src/main/kotlin/utils/Geometry.kt
new file mode 100644
index 0000000..8b6555e
--- /dev/null
+++ b/src/main/kotlin/utils/Geometry.kt
@@ -0,0 +1,235 @@
+package utils
+
+import utils.Direction.*
+import utils.Turn.*
+import kotlin.math.abs
+import kotlin.math.atan2
+import kotlin.math.pow
+import kotlin.math.sqrt
+
+data class Point(val x: Int, val y: Int) {
+
+ companion object {
+ val ORIGIN = Point(0, 0)
+ }
+
+ operator fun plus(other: Point): Point {
+ return Point(x + other.x, y + other.y)
+ }
+
+ operator fun minus(other: Point): Point {
+ return Point(x - other.x, y - other.y)
+ }
+
+ fun move(direction: Direction, distance: Int = 1) = when (direction) {
+ EAST -> Point(x + distance, y)
+ WEST -> Point(x - distance, y)
+ NORTH -> Point(x, y - distance)
+ SOUTH -> Point(x, y + distance)
+ }
+
+ fun move(direction: Direction8, distance: Int = 1) = when (direction) {
+ Direction8.NORTH -> Point(x, y - distance)
+ Direction8.NORTH_EAST -> Point(x + distance, y - distance)
+ Direction8.EAST -> Point(x + distance, y)
+ Direction8.SOUTH_EAST -> Point(x + distance, y + distance)
+ Direction8.SOUTH -> Point(x, y + distance)
+ Direction8.SOUTH_WEST -> Point(x - distance, y + distance)
+ Direction8.WEST -> Point(x - distance, y)
+ Direction8.NORTH_WEST -> Point(x - distance, y - distance)
+ }
+
+ fun manhattanDistanceTo(other: Point) = abs(x - other.x) + abs(y - other.y)
+
+ fun straightDistanceTo(other: Point) = sqrt((x - other.x).toDouble().pow(2) + (y - other.y).toDouble().pow(2))
+
+ fun getAdjacentSides(): List = listOf(
+ Point(x, y - 1), Point(x - 1, y), Point(x + 1, y), Point(x, y + 1),
+ )
+
+ fun getAdjacent(): List = listOf(
+ Point(x - 1, y - 1), Point(x, y - 1), Point(x + 1, y - 1),
+ Point(x - 1, y), Point(x + 1, y),
+ Point(x - 1, y + 1), Point(x, y + 1), Point(x + 1, y + 1),
+ )
+
+ fun isAdjacentSide(other: Point) = manhattanDistanceTo(other) == 1
+
+ fun angleTo(other: Point): Double {
+ val angle = Math.toDegrees(atan2((other.y - y).toDouble(), (other.x - x).toDouble())) + 90
+ return if (angle >= 0) angle else angle + 360
+ }
+}
+
+fun Map.printArea(visualization: (T) -> Char = { it.toString()[0] }) {
+ val xRange = keys.minOf { it.x }..keys.maxOf { it.x }
+ val yRange = keys.minOf { it.y }..keys.maxOf { it.y }
+ for (y in yRange) {
+ for (x in xRange) {
+ val value = get(Point(x, y))
+ if (value != null) {
+ print(visualization(value))
+ } else {
+ print(" ")
+ }
+ }
+ println()
+ }
+}
+
+@JvmName("printAreaBoolean")
+fun Map.printArea() {
+ printArea { if (it) '█' else ' ' }
+}
+
+@JvmName("printAreaChar")
+fun Map.printArea() {
+ printArea { it }
+}
+
+data class Vector3(val x: Int, val y: Int, val z: Int) {
+
+ companion object {
+ val ORIGIN = Vector3(0, 0, 0)
+ }
+
+ operator fun plus(other: Vector3): Vector3 {
+ return Vector3(x + other.x, y + other.y, z + other.z)
+ }
+
+ operator fun minus(other: Vector3): Vector3 {
+ return Vector3(x - other.x, y - other.y, z - other.z)
+ }
+
+ operator fun get(index: Int): Int = when (index) {
+ 0 -> x
+ 1 -> y
+ 2 -> z
+ else -> throw IllegalArgumentException()
+ }
+
+ fun getAdjacent(): List {
+ val adjacent = mutableListOf()
+ for (x in -1..1) {
+ for (y in -1..1) {
+ for (z in -1..1) {
+ if (x == 0 && y == 0 && z == 0) continue
+ adjacent += (Vector3(x, y, z) + this)
+ }
+ }
+ }
+ return adjacent
+ }
+}
+
+typealias VectorN = List
+
+fun VectorN.getAdjacent(): List> {
+ val adjacent = mutableListOf(this)
+ for (dimension in indices) {
+ adjacent += adjacent.flatMap {
+ listOf(
+ it.toMutableList().also { it[dimension] -= 1 },
+ it.toMutableList().also { it[dimension] += 1 }
+ )
+ }
+ }
+ return adjacent.filterNot { it == this }
+}
+
+enum class Turn {
+ RIGHT, LEFT;
+
+ override fun toString() = when (this) {
+ RIGHT -> "↻"
+ LEFT -> "↺"
+ }
+}
+
+enum class Direction {
+ NORTH, EAST, SOUTH, WEST;
+
+ fun rotate(turn: Turn, times: Int): Direction {
+ return (0 until (times % 4)).toList().fold(this) { acc, _ -> acc.rotate(turn) }
+ }
+
+ fun rotate(turn: Turn): Direction {
+ return if (turn == RIGHT) when (this) {
+ NORTH -> EAST
+ EAST -> SOUTH
+ SOUTH -> WEST
+ WEST -> NORTH
+ } else when (this) {
+ NORTH -> WEST
+ EAST -> NORTH
+ SOUTH -> EAST
+ WEST -> SOUTH
+ }
+ }
+
+ fun reverse() = when (this) {
+ NORTH -> SOUTH
+ SOUTH -> NORTH
+ WEST -> EAST
+ EAST -> WEST
+ }
+
+ override fun toString() = when (this) {
+ NORTH -> "↑"
+ EAST -> "→"
+ SOUTH -> "↓"
+ WEST -> "←"
+ }
+}
+
+enum class Direction8 {
+ NORTH, NORTH_EAST, EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, WEST, NORTH_WEST;
+
+ fun rotate(turn: Turn, times: Int): Direction8 {
+ return (0 until (times % 4)).toList().fold(this) { acc, _ -> acc.rotate(turn) }
+ }
+
+ fun rotate(turn: Turn): Direction8 {
+ return if (turn == RIGHT) when (this) {
+ NORTH -> NORTH_EAST
+ NORTH_EAST -> EAST
+ EAST -> SOUTH_EAST
+ SOUTH_EAST -> SOUTH
+ SOUTH -> SOUTH_WEST
+ SOUTH_WEST -> WEST
+ WEST -> NORTH_WEST
+ NORTH_WEST -> NORTH
+ } else when (this) {
+ NORTH -> NORTH_WEST
+ NORTH_EAST -> NORTH
+ EAST -> NORTH_EAST
+ SOUTH_EAST -> EAST
+ SOUTH -> SOUTH_EAST
+ SOUTH_WEST -> SOUTH
+ WEST -> SOUTH_WEST
+ NORTH_WEST -> WEST
+ }
+ }
+
+ fun reverse() = when (this) {
+ NORTH -> SOUTH
+ NORTH_EAST -> SOUTH_WEST
+ EAST -> WEST
+ SOUTH_EAST -> NORTH_WEST
+ SOUTH -> NORTH
+ SOUTH_WEST -> NORTH_EAST
+ WEST -> EAST
+ NORTH_WEST -> SOUTH_EAST
+ }
+
+ override fun toString() = when (this) {
+ NORTH -> "↑"
+ NORTH_EAST -> "↗"
+ EAST -> "→"
+ SOUTH_EAST -> "↘"
+ SOUTH -> "↓"
+ SOUTH_WEST -> "↙"
+ WEST -> "←"
+ NORTH_WEST -> "↖"
+ }
+}
diff --git a/src/main/kotlin/utils/Math.kt b/src/main/kotlin/utils/Math.kt
new file mode 100644
index 0000000..bcfd3b3
--- /dev/null
+++ b/src/main/kotlin/utils/Math.kt
@@ -0,0 +1,22 @@
+package utils
+
+fun List.getPermutations(): List> {
+ return if (size == 2) listOf(listOf(this[0], this[1]), listOf(this[1], this[0]))
+ else map { initial ->
+ (this - initial).getPermutations().map { permutation -> listOf(initial) + permutation }
+ }.flatten()
+}
+
+fun leastCommonMultiple(a: Int, b: Int): Int {
+ return a * b / greatestCommonDivisor(a, b)
+}
+
+tailrec fun greatestCommonDivisor(a: Int, b: Int): Int {
+ return if (b == 0) a
+ else greatestCommonDivisor(b, a % b)
+}
+
+tailrec fun greatestCommonDivisor(a: Long, b: Long): Long {
+ return if (b == 0L) a
+ else greatestCommonDivisor(b, a % b)
+}