Skip to content

Commit

Permalink
day 18 and 19, as well as empty files for days 20-25
Browse files Browse the repository at this point in the history
  • Loading branch information
norganos committed Dec 19, 2023
1 parent 0b7bbe1 commit 32089ce
Show file tree
Hide file tree
Showing 16 changed files with 392 additions and 83 deletions.
99 changes: 25 additions & 74 deletions src/main/kotlin/de/linkel/aoc/Day18.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@ package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import de.linkel.aoc.utils.grid.Grid
import de.linkel.aoc.utils.grid.Point
import jakarta.inject.Singleton
import kotlin.math.max
import kotlin.math.min
import kotlin.math.abs

@Singleton
class Day18: AbstractLinesAdventDay<Long>() {
override val day = 18

data class Cube(
val dirIn: Char,
val dirOut: Char
)
data class Point(
val x: Long,
val y: Long
)
) {
override fun toString(): String = "${x}x${y}"
}
interface Vector {
val deltaX: Long
val deltaY: Long
Expand All @@ -39,17 +34,10 @@ class Day18: AbstractLinesAdventDay<Long>() {
): Vector
operator fun Point.plus(vector: Vector): Point = Point(this.x + vector.deltaX, this.y + vector.deltaY)
operator fun Vector.times(factor: Long): Vector = GenericVector(this.deltaX * factor, this.deltaY * factor)
operator fun Vector.plus(vector: Vector): Vector = GenericVector(this.deltaX + vector.deltaX, this.deltaY + vector.deltaY)

override fun process(part: QuizPart, lines: Sequence<String>): Long {
val origin = Point(0L,0L)
val map = mutableMapOf<Point, Cube>()
var minX = 0L
var minY = 0L
var maxX = 0L
var maxY = 0L
// val map = Grid<Cube>(origin, Dimension(1,1))
map[origin] = Cube('0','?')
lines.fold(origin) { pos, line ->
return lines.map { line ->
val (dir, len) = if (part == QuizPart.A) {
val token = line.split(' ')
val dir = Direction.valueOf(token[0])
Expand All @@ -61,63 +49,26 @@ class Day18: AbstractLinesAdventDay<Long>() {
val dir = Direction.entries[hex[5].digitToInt()]
dir to len
}
val dest = pos + dir * len
// map.stretchTo(dest)
(1L..len).forEach {
map[pos + dir * it] = Cube(line[0], line[0])
}
minX = min(minX, dest.x)
minY = min(minY, dest.y)
maxX = max(maxX, dest.x)
maxY = max(maxY, dest.y)
map[pos] = map[pos]!!.copy(dirOut = line[0])
dest
dir * len
}.let {
solve(it.toList())
}
}

var insides = 0L
(minY..maxY)
.forEach { y ->
// var upIn = false
// var downOut = false
var inside = false
(minX..maxX)
.forEach { x ->
val p = Point(x, y)
if (map[p] != null) {
// if (map[p]!!.dirIn == 'D' || map[p]!!.dirOut == 'U')
if (map[p]!!.dirIn == 'U' || map[p]!!.dirOut == 'D')
inside = !inside
// if (map[p]!!.dirIn == 'U')
// upIn = !upIn
// if (map[p]!!.dirOut == 'D')
// downOut = !downOut
} else if (inside) {
// } else if (upIn != downOut) {
insides++
// map[p] = Cube('#', '#')
}
}
}
private fun points(digPlan: List<Vector>): List<Point> =
digPlan.runningFold(Point(0, 0)) { acc, shiftVector ->
acc + shiftVector
}

return insides + map.size
}
fun printMap(grid: Grid<Cube>) {
println(
buildString {
(grid.area.y until (grid.area.y + grid.area.height))
.forEach { y ->
(grid.area.x until (grid.area.x + grid.area.width))
.forEach { x ->
val p = Point(x, y)
if (grid[p] != null) {
append(grid[p]!!.dirIn)
} else {
append('.')
}
}
append('\n')
}
}
)
}
private fun perimeterPoints(vectors: List<Vector>): Long =
vectors.sumOf { abs(it.deltaX) + abs(it.deltaY) } // Manhattan Distance is ok here because we only have 90 degree turns

private fun shoelaceFormula(corners: List<Point>): Long =
corners.zipWithNext().sumOf { (a, b) -> a.x * b.y - a.y * b.x } / 2

private fun pickTheorem(area: Long, perimeter: Long): Long =
area + perimeter / 2L + 1L

private fun solve(digPlan: List<Vector>): Long
= pickTheorem(shoelaceFormula(points(digPlan)), perimeterPoints(digPlan))
}
167 changes: 164 additions & 3 deletions src/main/kotlin/de/linkel/aoc/Day19.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,174 @@ package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import de.linkel.aoc.utils.iterables.intersect
import jakarta.inject.Singleton
import java.math.BigInteger

@Singleton
class Day19: AbstractLinesAdventDay<Int>() {
class Day19: AbstractLinesAdventDay<BigInteger>() {
override val day = 19

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
enum class Op(val char: Char, val lambda: (value: Int, threshold: Int) -> Boolean) {
GT('>', { v, t -> v > t }),
LT('<', { v, t -> v < t })
}

data class Rule(
val prop: String,
val op: Op,
val threshold: Int,
val dest: String
) {
fun matches(part: Map<String,Int>): Boolean = op.lambda(part[prop]!!, threshold)

fun validRange(): IntRange {
return when(op) {
Op.GT -> (threshold + 1)..4000
Op.LT -> 1..<threshold
}
}
fun invalidRange(): IntRange {
return when(op) {
Op.GT -> 1..(threshold)
Op.LT -> (threshold)..4000
}
}
}

data class Workflow(
val rules: List<Rule>,
val otherwise: String
) {
fun process(part: Map<String,Int>): String {
for (rule in rules) {
if (rule.matches(part))
return rule.dest
}
return otherwise
}
}

override fun process(part: QuizPart, lines: Sequence<String>): BigInteger {
val iterator = lines.iterator()
val rulePattern = Regex("([xmas])([<>])([0-9]+):([a-zAR]+)")
val workflows = iterator
.asSequence()
.takeWhile { it.isNotEmpty() }
.associate { line ->
val name = line.substringBefore("{")
val ruleStrings = line.substringAfter("{").substringBefore("}").split(",")
val rules = ruleStrings.dropLast(1)
.map { token ->
val match = rulePattern.matchEntire(token) ?: throw Exception("$token does not match rule regex")
Rule(match.groupValues[1], Op.entries.first { it.char == match.groupValues[2][0]}, match.groupValues[3].toInt(), match.groupValues[4])
}
val otherwise = ruleStrings.last()
name to Workflow(rules, otherwise)
}
return if (part == QuizPart.A) {
iterator
.asSequence()
.map { line ->
line.substring(1, line.length - 1).split(",")
.associate { it.substringBefore("=") to it.substringAfter("=").toInt() }
}
.map { machinePart ->
var dest = "in"
while (dest != "A" && dest != "R") {
dest = workflows[dest]!!.process(machinePart)
// println ("$machinePart to $dest")
}
machinePart to dest
}
.filter { (_, dest) -> dest == "A" }
.sumOf { (machinePart, _) -> machinePart.values.sum() }
.toBigInteger()
} else {
searchPathes(workflows, listOf("in"), mapOf("x" to 1..4000, "m" to 1..4000, "a" to 1..4000, "s" to 1..4000))
.sumOf {
vc -> vc.values.fold(BigInteger.ONE) { p, r -> p * (r.last - r.first + 1).toBigInteger() }
}
// listOf("x","m","a","s")
// .map { prop ->
// prop to validConstraints.fold(listOf(1..4000)) { existing, constraint ->
// val range = constraint[prop]!!
// buildList {
// existing
// .sortedBy { it.first }
// .forEach { r ->
// if (r.last < range.first || r.first > range.last || r == range) {
// add(r)
// } else {
// add(r.first until range.first)
// add(max(r.first, range.first)..min(r.last, range.last))
// add((range.last + 1)..r.last)
// }
// }
// }
// .filter { !it.isEmpty() }
// }
// }
// .map { prop ->
// prop.second
// .map {
// prop.first to it
// }
// }
// .combinations()
// .filter { combination ->
// validConstraints.any { constraint ->
// combination.all { prop ->
// prop.second.first >= constraint[prop.first]!!.first && prop.second.last <= constraint[prop.first]!!.last
// }
// }
// }
// .map { combination ->
// combination.fold(BigInteger.ONE) { product, prop -> product * (prop.second.last - prop.second.first + 1).toBigInteger()}
// }
// .sumOf { it }
}
}
fun Map<String,IntRange>.constraintBy(rule: Rule): Map<String,IntRange> {
val base = this
return buildMap {
putAll(base)
if (base.containsKey(rule.prop)) {
put(rule.prop, base[rule.prop]!!.intersect(rule.validRange()))
} else {
put(rule.prop, rule.validRange())
}
}
}
fun Map<String,IntRange>.constraintByNot(rule: Rule): Map<String,IntRange> {
val base = this
return buildMap {
putAll(base)
if (base.containsKey(rule.prop)) {
put(rule.prop, base[rule.prop]!!.intersect(rule.invalidRange()))
} else {
put(rule.prop, rule.invalidRange())
}
}
}

fun searchPathes(workflows: Map<String, Workflow>, path: List<String>, constraints: Map<String,IntRange>): Set<Map<String, IntRange>> {
return if (path.last() == "A") {
setOf(constraints)
} else if (constraints.any { it.value.isEmpty() }) {
emptySet()
} else if (path.last() == "R") {
emptySet()
} else {
buildSet {
val wf = workflows[path.last()] ?: throw Exception("workflow ${path.last()} not found")
var otherwise = constraints
for (r in wf.rules) {
addAll(searchPathes(workflows, path + r.dest, otherwise.constraintBy(r)))
otherwise = otherwise.constraintByNot(r)
}
addAll(searchPathes(workflows, path + wf.otherwise, otherwise))
}
}
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day20.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day20: AbstractLinesAdventDay<Int>() {
override val day = 20

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day21.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day21: AbstractLinesAdventDay<Int>() {
override val day = 21

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day22.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day22: AbstractLinesAdventDay<Int>() {
override val day = 22

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day23.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day23: AbstractLinesAdventDay<Int>() {
override val day = 23

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day24.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day24: AbstractLinesAdventDay<Int>() {
override val day = 24

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/de/linkel/aoc/Day25.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package de.linkel.aoc

import de.linkel.aoc.base.AbstractLinesAdventDay
import de.linkel.aoc.base.QuizPart
import jakarta.inject.Singleton

@Singleton
class Day25: AbstractLinesAdventDay<Int>() {
override val day = 25

override fun process(part: QuizPart, lines: Sequence<String>): Int {
return 0
}
}
Loading

0 comments on commit 32089ce

Please sign in to comment.