-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add puzzle solution for 2023, day 18
- Loading branch information
Showing
16 changed files
with
1,011 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
plugins { | ||
val kotlinVersion: String by System.getProperties() | ||
val koverVersion: String by System.getProperties() | ||
|
||
kotlin("jvm") version kotlinVersion | ||
id("org.jetbrains.kotlinx.kover") version koverVersion | ||
} | ||
|
||
dependencies { | ||
val assertjVersion: String by properties | ||
val junitJupiterVersion: String by properties | ||
val junitPlatformVersion: String by properties | ||
|
||
implementation(project(":common:geometry")) | ||
testImplementation("org.assertj:assertj-core:$assertjVersion") | ||
testImplementation("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion") | ||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion") | ||
testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitPlatformVersion") | ||
} |
31 changes: 31 additions & 0 deletions
31
year2023/day18/dig/src/main/kotlin/com/curtislb/adventofcode/year2023/day18/dig/DigPlan.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.curtislb.adventofcode.year2023.day18.dig | ||
|
||
import com.curtislb.adventofcode.common.geometry.Point | ||
import com.curtislb.adventofcode.common.geometry.polygonArea | ||
|
||
/** | ||
* A dig plan that consists of a list of instructions for digging out a lava lagoon. | ||
* | ||
* @property instructions The ordered list of instructions in the dig plan. | ||
* | ||
* @constructor Creates a new instance of [DigPlan] with the specified [instructions]. | ||
*/ | ||
class DigPlan(private val instructions: List<Instruction>) { | ||
/** | ||
* Calculates the area of the lava lagoon produced by following the dig plan instructions. | ||
*/ | ||
fun calculateArea(): Long { | ||
// Keep track of the polygon perimeter and vertices produced by the dig plan | ||
var perimeter = 0L | ||
var position = Point.ORIGIN | ||
val vertices = mutableListOf<Point>() | ||
for (instruction in instructions) { | ||
perimeter += instruction.distance | ||
position = position.move(instruction.direction, instruction.distance) | ||
vertices.add(position) | ||
} | ||
|
||
// Calculate the interior area, and add a correction for the perimeter squares | ||
return polygonArea(vertices) + (perimeter / 2L) + 1L | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
...023/day18/dig/src/main/kotlin/com/curtislb/adventofcode/year2023/day18/dig/Instruction.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.curtislb.adventofcode.year2023.day18.dig | ||
|
||
import com.curtislb.adventofcode.common.geometry.Direction | ||
|
||
/** | ||
* A single instruction that may appear in a [DigPlan]. | ||
* | ||
* @property direction The direction to move, relative to the current position. | ||
* @property distance The number of meters to move while digging out one-meter cubes. | ||
*/ | ||
data class Instruction(val direction: Direction, val distance: Int) { | ||
init { | ||
require(!direction.isDiagonal()) { "Direction must be cardinal: $direction" } | ||
} | ||
|
||
companion object { | ||
/** | ||
* A regex used to parse instruction parameters from a single line of a dig plan. | ||
*/ | ||
private val INSTRUCTION_REGEX = Regex("""([UDLR]) (\d+) \(#([0-9a-f]{5})([0-3])\)""") | ||
|
||
/** | ||
* Returns an [Instruction] with a [direction] and [distance] read from the given [string]. | ||
* | ||
* The [string] must have the following format, where `directionChar` is a single character | ||
* (`U`, `D`, `L`, or `R`) corresponding to a cardinal [Direction], `directionInt` is a | ||
* decimal integer, `distanceHex` is a 5-digit hexadecimal number, and `directionHex` is a | ||
* digit corresponding to a cardinal [Direction] (0 to [Direction.RIGHT], 1 to | ||
* [Direction.DOWN], 2 to [Direction.LEFT], or 3 to [Direction.UP]): | ||
* | ||
* ``` | ||
* $directionChar $distanceInt (#${distanceHex}${directionHex}) | ||
* ``` | ||
* | ||
* If [useHexCode] is `false`, the direction for the instruction will be parsed from | ||
* `directionChar` and the [distance] will be parsed from `distanceInt`. If [useHexCode] is | ||
* `true`, the [direction] will be parsed from `directionHex` and the [distance] will be | ||
* parsed from `distanceHex`. | ||
* | ||
* @throws IllegalArgumentException If [string] is formatted incorrectly. | ||
*/ | ||
fun fromString(string: String, useHexCode: Boolean = false): Instruction { | ||
val matchResult = INSTRUCTION_REGEX.matchEntire(string) | ||
require(matchResult != null) { "Malformed instruction string: $string" } | ||
|
||
val direction: Direction | ||
val distance: Int | ||
if (useHexCode) { | ||
// Read direction and distance from the third (hex code) token | ||
val (_, _, distanceHex, directionHex) = matchResult.destructured | ||
direction = when (directionHex) { | ||
"0" -> Direction.RIGHT | ||
"1" -> Direction.DOWN | ||
"2" -> Direction.LEFT | ||
"3" -> Direction.UP | ||
else -> error("Invalid direction hex string: $directionHex") | ||
} | ||
distance = distanceHex.toInt(radix = 16) | ||
} else { | ||
// Read direction and distance from first two tokens | ||
val (directionString, distanceString, _, _) = matchResult.destructured | ||
direction = Direction.fromChar(directionString[0]) | ||
distance = distanceString.toInt() | ||
} | ||
|
||
return Instruction(direction, distance) | ||
} | ||
} | ||
} |
Oops, something went wrong.