Skip to content

Commit

Permalink
extracting utils, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
kgeri committed Dec 20, 2022
1 parent d904fb5 commit d63a309
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 103 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/me/gergo/Aoc01.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ fun main() {
.sumOf { it.calories })
}

class Elf {
private class Elf {
var calories = 0;
}
4 changes: 2 additions & 2 deletions src/main/kotlin/me/gergo/Aoc02.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun main() {
}

enum class Choice { Rock, Paper, Scissors }
data class Guide(val opponent: Choice, val my: Choice) {
private data class Guide(val opponent: Choice, val my: Choice) {
fun score(): Int = scoreFor(my) + scoreForOutcomeOf(opponent, my)

private fun scoreFor(c: Choice): Int = c.ordinal + 1
Expand All @@ -24,7 +24,7 @@ data class Guide(val opponent: Choice, val my: Choice) {
}
}

fun parseGuide(line: String): Guide {
private fun parseGuide(line: String): Guide {
val tokens = line.split(" ")
val opponent = when (tokens[0]) {
"A" -> Rock
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/me/gergo/Aoc02b.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ fun main() {

private val Choices = Choice.values()

enum class Result { Lose, Draw, Win }
data class Guide2(val opponent: Choice, val result: Result) {
private enum class Result { Lose, Draw, Win }
private data class Guide2(val opponent: Choice, val result: Result) {
fun score(): Int = scoreFor(pickChoiceFor(opponent, result)) + scoreFor(result)

private fun scoreFor(r: Result): Int = when (r) {
Expand All @@ -31,7 +31,7 @@ data class Guide2(val opponent: Choice, val result: Result) {
}
}

fun parseGuide2(line: String): Guide2 {
private fun parseGuide2(line: String): Guide2 {
val tokens = line.split(" ")
val opponent = when (tokens[0]) {
"A" -> Rock
Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/me/gergo/Aoc03.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ fun main() {
println(results)
}

data class Rucksack(val c1: String, val c2: String) {
private data class Rucksack(val c1: String, val c2: String) {
fun priorityOfSharedType() = priorityOf(sharedType()) // For Part One

private fun sharedType(): Char = c1.toCharArray().intersect(c2.toCharArray().toSet()).first()
}

fun parseRucksack(line: String): Rucksack {
private fun parseRucksack(line: String): Rucksack {
return Rucksack(line.substring(0, line.length / 2), line.substring(line.length / 2))
}

fun priorityOfSharedType(group: Iterable<Rucksack>): Int {
private fun priorityOfSharedType(group: Iterable<Rucksack>): Int {
val sharedType = group.map { (it.c1 + it.c2).toCharArray().toSet() }.reduce { acc, r -> acc.intersect(r) }.first()
return priorityOf(sharedType)
}

fun priorityOf(type: Char): Int {
private fun priorityOf(type: Char): Int {
val d = type.code
return if (d >= 'a'.code && d <= 'z'.code) d - 'a'.code + 1
else d - 'A'.code + 27
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/me/gergo/Aoc04.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ fun main() {
println(results)
}

data class Assignment(val first: IntRange, val second: IntRange) {
private data class Assignment(val first: IntRange, val second: IntRange) {
fun fullyContains() = first.minus(second).isEmpty() || second.minus(first).isEmpty()
fun overlaps() = first.minus(second).size < first.count() || second.minus(first).size < second.count()
}

fun parseAssignment(line: String): Assignment {
private fun parseAssignment(line: String): Assignment {
val ranges = line.split(",").map {
val range = it.split("-").map(String::toInt)
range[0]..range[1]
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/me/gergo/Aoc05.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ fun main() {
stacks.forEach { print(it.peek()) }
}

typealias CrateStack = Stack<Char>
private typealias CrateStack = Stack<Char>

data class Instruction(val quantity: Int, val fromStack: Int, val toStack: Int) {}
private data class Instruction(val quantity: Int, val fromStack: Int, val toStack: Int) {}

fun parseStacksAndInstructions(lines: List<String>): Pair<List<CrateStack>, List<Instruction>> {
private fun parseStacksAndInstructions(lines: List<String>): Pair<List<CrateStack>, List<Instruction>> {
val stacks = parseStacks(lines.subList(0, lines.indexOf("") - 1))
val instructions = lines.subList(lines.indexOf("") + 1, lines.size).map(::parseInstruction)
return Pair(stacks, instructions)
}

fun parseStacks(lines: List<String>): List<CrateStack> {
private fun parseStacks(lines: List<String>): List<CrateStack> {
val stackCount = (lines[0].length + 1) / 4
val result = List(stackCount) { Stack<Char>() }
for (i in lines.size - 1 downTo 0) {
Expand All @@ -41,7 +41,7 @@ fun parseStacks(lines: List<String>): List<CrateStack> {
return result
}

fun parseInstruction(line: String): Instruction {
private fun parseInstruction(line: String): Instruction {
val m = Regex("move (\\d+) from (\\d+) to (\\d+)").matchEntire(line)!!
return Instruction(m.groupValues[1].toInt(), m.groupValues[2].toInt(), m.groupValues[3].toInt())
}
14 changes: 7 additions & 7 deletions src/main/kotlin/me/gergo/Aoc07.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun main() {
println("To delete: $toDelete, totalSize=${toDelete.totalSize()}")
}

fun parseCommandLine(line: String): CommandLine {
private fun parseCommandLine(line: String): CommandLine {
return if (line == "$ ls") Ls
else if (line.startsWith("$ cd")) Cd(line.substring(5))
else if (line.startsWith("dir ")) DirectoryOutput(line.substring(4))
Expand All @@ -50,13 +50,13 @@ fun parseCommandLine(line: String): CommandLine {
}
}

sealed interface CommandLine
object Ls : CommandLine {}
data class Cd(val dirName: String) : CommandLine {}
data class DirectoryOutput(val name: String) : CommandLine {}
data class FileOutput(val name: String, val size: Int) : CommandLine {}
private sealed interface CommandLine
private object Ls : CommandLine {}
private data class Cd(val dirName: String) : CommandLine {}
private data class DirectoryOutput(val name: String) : CommandLine {}
private data class FileOutput(val name: String, val size: Int) : CommandLine {}

data class FileNode(val name: String, val size: Int, var parent: FileNode?, val children: MutableList<FileNode>) {
private data class FileNode(val name: String, val size: Int, var parent: FileNode?, val children: MutableList<FileNode>) {

fun isDirectory() = children.size > 0

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/me/gergo/Aoc08.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun main() {
println("Max scenic score: ${trees.maxScenicScore()}") // Part Two
}

class Trees(lines: List<String>) {
private class Trees(lines: List<String>) {
private val forest: Array<IntArray>
private val width: Int
private val height: Int
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/me/gergo/Aoc09.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ fun main() {
println("Positions visited by tail: ${ropeField.positionsVisitedByTail().count()}")
}

enum class Direction { L, R, U, D }
data class RopeStep(val dir: Direction, val steps: Int)
data class Position(val x: Int, val y: Int) {
private enum class Direction { L, R, U, D }
private data class RopeStep(val dir: Direction, val steps: Int)
private data class Position(val x: Int, val y: Int) {
fun distanceFrom(o: Position) = max(abs(x - o.x), abs(y - o.y))
}

class Rope(internal val knots: MutableList<Position>) {
private class Rope(internal val knots: MutableList<Position>) {

fun head() = knots[0]
fun tail() = knots[knots.size - 1]
Expand Down Expand Up @@ -56,7 +56,7 @@ class Rope(internal val knots: MutableList<Position>) {
}
}

class RopeField(private val width: Int, private val height: Int, ropeLength: Int) {
private class RopeField(private val width: Int, private val height: Int, ropeLength: Int) {
private val rope = Rope(MutableList(ropeLength) { Position(0, 0) })
private val tailPositions = mutableListOf<Position>()

Expand All @@ -81,7 +81,7 @@ class RopeField(private val width: Int, private val height: Int, ropeLength: Int
fun positionsVisitedByTail() = tailPositions.toSet()
}

fun parseRopeStep(line: String): RopeStep {
private fun parseRopeStep(line: String): RopeStep {
val (dir, steps) = line.split(" ")
return RopeStep(Direction.valueOf(dir), steps.toInt())
}
8 changes: 4 additions & 4 deletions src/main/kotlin/me/gergo/Aoc10.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ fun main() {
CRT(40, 6, cpu).draw()
}

sealed class Instr(val duration: Int)
object Noop : Instr(1)
data class Addx(val value: Int) : Instr(2)
private sealed class Instr(val duration: Int)
private object Noop : Instr(1)
private data class Addx(val value: Int) : Instr(2)

private class CPU(private val instructions: List<Instr>) {
private var instructionPointer = 0
Expand Down Expand Up @@ -56,7 +56,7 @@ private class CRT(private val width: Int, private val height: Int, private val c
}
}

fun parseInstr(line: String): Instr {
private fun parseInstr(line: String): Instr {
val tokens = line.split(" ")
return if (tokens[0] == "noop") Noop
else Addx(tokens[1].toInt())
Expand Down
15 changes: 1 addition & 14 deletions src/main/kotlin/me/gergo/Aoc11.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ private const val Rounds = 10000

/**
* Note: this only has Part Two, as I did Part One with a naiive solution that probably takes all the memory in the world, multiplying horribly large
* BigDecimals :) The trick in this one is to remember but delay the computation for as long as possible. As we're only really interested in whether
* BigDecimals :) The trick in this one is to remember to delay the computation for as long as possible. As we're only really interested in whether
* the result at the end of a long chain of operations is divisible by N, we can modulo N per every operation - but we must do that for each monkey
* individually, which means we must remember the computation chain (Items.operations in this implementation)!
*
Expand Down Expand Up @@ -38,19 +38,6 @@ fun main() {
println("Level of monkey business: $result")
}

fun lcm(a: Int, b: Int) = a * (b / gcd(a, b))

fun gcd(a: Int, b: Int): Int {
var a0 = a
var b0 = b
while (b0 > 0) {
val temp = b0
b0 = a0 % b0
a0 = temp
}
return a0
}

private class Monkey(val name: Int, val items: Queue<Item>, val operation: Operation, val divisor: Int, val throwToTrue: Int, val throwToFalse: Int) {
var inspections = 0L

Expand Down
54 changes: 0 additions & 54 deletions src/main/kotlin/me/gergo/Aoc12.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,58 +58,4 @@ private operator fun Array<CharArray>.set(c: Coordinate, value: Char) {
this[c.y][c.x] = value
}

data class Coordinate(val x: Int, val y: Int)

fun aStar(
start: Coordinate, goal: Coordinate,
neighborFn: (Coordinate) -> Sequence<Coordinate>,
heuristicFn: (Coordinate) -> Double,
distanceFn: (Coordinate, Coordinate) -> Double
): List<Coordinate> {
val openSet = mutableSetOf(start)
val cameFrom = mutableMapOf<Coordinate, Coordinate>()

val gScore = mutableMapOf<Coordinate, Double>()
gScore[start] = 0.0

val fScore = mutableMapOf<Coordinate, Double>()
fScore[start] = heuristicFn(start)

while (openSet.isNotEmpty()) {
val current = openSet.minBy { fScore.getOrDefault(it, POSITIVE_INFINITY) }
if (current == goal) {
// Path found, reconstructing
val result = mutableListOf(current)
var c: Coordinate? = current
while (true) {
c = cameFrom[c]
if (c == null) break
result.add(0, c)
}
return result
}

openSet.remove(current)
for (neighbor in neighborFn(current)) {
val tentativeGScore = gScore.getOrDefault(current, POSITIVE_INFINITY) + distanceFn(current, neighbor)
if (tentativeGScore < gScore.getOrDefault(neighbor, POSITIVE_INFINITY)) {
cameFrom[neighbor] = current
gScore[neighbor] = tentativeGScore
fScore[neighbor] = tentativeGScore + heuristicFn(neighbor)
openSet.add(neighbor)
}
}
}
return emptyList() // Path not found
}

fun neighbors(width: Int, height: Int, c: Coordinate) = sequence {
val x = c.x
val y = c.y
if (x > 0) yield(Coordinate(x - 1, y))
if (y + 1 < height) yield(Coordinate(x, y + 1))
if (x + 1 < width) yield(Coordinate(x + 1, y))
if (y > 0) yield(Coordinate(x, y - 1))
}

private fun manhattanDistance(a: Coordinate, b: Coordinate): Double = (abs(b.x - a.x) + abs(b.y - a.y)).toDouble()
15 changes: 15 additions & 0 deletions src/main/kotlin/me/gergo/coordinates.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package me.gergo

import kotlin.math.abs

data class Coordinate(val x: Int, val y: Int)

fun neighbors(width: Int, height: Int, c: Coordinate) = sequence {
val x = c.x
val y = c.y
if (x > 0) yield(Coordinate(x - 1, y))
if (y + 1 < height) yield(Coordinate(x, y + 1))
if (x + 1 < width) yield(Coordinate(x + 1, y))
if (y > 0) yield(Coordinate(x, y - 1))
}

14 changes: 14 additions & 0 deletions src/main/kotlin/me/gergo/math.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.gergo

fun lcm(a: Int, b: Int) = a * (b / gcd(a, b))

fun gcd(a: Int, b: Int): Int {
var a0 = a
var b0 = b
while (b0 > 0) {
val temp = b0
b0 = a0 % b0
a0 = temp
}
return a0
}
44 changes: 44 additions & 0 deletions src/main/kotlin/me/gergo/search.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package me.gergo

fun <N> aStar(
start: N, goal: N,
neighborFn: (N) -> Sequence<N>,
heuristicFn: (N) -> Double,
distanceFn: (N, N) -> Double
): List<N> {
val openSet = mutableSetOf(start)
val cameFrom = mutableMapOf<N, N>()

val gScore = mutableMapOf<N, Double>()
gScore[start] = 0.0

val fScore = mutableMapOf<N, Double>()
fScore[start] = heuristicFn(start)

while (openSet.isNotEmpty()) {
val current = openSet.minBy { fScore.getOrDefault(it, Double.POSITIVE_INFINITY) }
if (current == goal) {
// Path found, reconstructing
val result = mutableListOf(current)
var c: N? = current
while (true) {
c = cameFrom[c]
if (c == null) break
result.add(0, c)
}
return result
}

openSet.remove(current)
for (neighbor in neighborFn(current)) {
val tentativeGScore = gScore.getOrDefault(current, Double.POSITIVE_INFINITY) + distanceFn(current, neighbor)
if (tentativeGScore < gScore.getOrDefault(neighbor, Double.POSITIVE_INFINITY)) {
cameFrom[neighbor] = current
gScore[neighbor] = tentativeGScore
fScore[neighbor] = tentativeGScore + heuristicFn(neighbor)
openSet.add(neighbor)
}
}
}
return emptyList() // Path not found
}

0 comments on commit d63a309

Please sign in to comment.