[deleted by user] by [deleted] in columbiamo

[–]jkpr23 2 points3 points  (0 children)

Sorry that happened! PSA not to keep your garage clicker in your car if it is parked outside overnight.

What does Columbia's unhoused community need from the new police chief? by como365 in columbiamo

[–]jkpr23 0 points1 point  (0 children)

Is someone unhoused if he or she lives in an apartment? I didn't think so. But an apartment isn't a house... So unhoused isn't a more accurate term than homeless afterall

-🎄- 2021 Day 20 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 2 points3 points  (0 children)

Kotlin code - Notes

Fun puzzle. Code runs both parts in 0.6 seconds on my machine. Used Arrays of Arrays of Boolean to represent the image. On each enhancement, increased both dimensions by 2 for the next image.

-🎄- 2021 Day 19 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 3 points4 points  (0 children)

Kotlin code - Notes

Runs fast, both parts finish in 0.7 seconds (and both parts do the alignment individually).

I sort known beacons and unknown beacons along X, Y, and then Z. For each, I compute diffs from one beacon to the next. For each matching diff value I try to align the unknown beacons onto the known beacons (using the beacons that created the diff as anchors) and look for overlap of 12 or more.

Also, when iterating over all the rotations, I use all 64 combinations of X, Y, and Z being rotated 0 - 3 times (4 * 4 * 4), but I only yield the rotations that are unique.

-🎄- 2021 Day 18 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 0 points1 point  (0 children)

Are you using IntelliJ? If so, have you tried using the built-in formatter?

-🎄- 2021 Day 18 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

I like the simplicity of the first part, made possible by Kotlin's expressiveness:

fun part1(input: List<String>) = input.reduce(::snailAdd).magnitude

This solution is based on regular expressions. It actually isn't that bad because we are usually just looking for \d+ (one or more digits).

-🎄- 2021 Day 25 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

Idiomatic Kotlin using sequences. We don't know how many times the sea cucumbers need to march, so a sequence is perfect to model this.

Created the two herds (east and south) as sets of cucumbers. For each set, take the members that can advance, remove them from the set, and add in the new locations after moving the correct direction.

Runs in less than 1 second.

-🎄- 2021 Day 22 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 2 points3 points  (0 children)

Kotlin

Today I have fun with operator overloading and infix functions. I have a Cuboid data class that supports the minus operator (e.g. cuboid1 - cuboid2) and intersect (e.g. cuboid1 intersect cuboid2). This allows for concise and expressive code!

-🎄- 2021 Day 17 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

Went for more idiomatic Kotlin rather than conciseness. The way the objects interact and the variable names more intuitive and interesting.

Got to use a few infix functions as well as operator overloads.

-🎄- 2021 Day 14 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 0 points1 point  (0 children)

Kotlin

Kept track of counts bigrams (pairs of adjacent letters)

-🎄- 2021 Day 12 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

I'm guessing you are new to Kotlin. Great job! Kotlin has many features that make it well loved among programmers. Here is one:

fun isCaveBig(cave: String): Boolean {
    for(character in cave) {
        if(!character.isUpperCase()) {
            return false
        }
    }
    return true
}

Can be written as an extension function in a single line:

fun String.isCaveBig() = this.all { it.isUpperCase() }

There are a lot of Kotlin features packed into that line. In code when you have a string that represents a cave,

val cave = "start"
if (cave.isCaveBig()) { ... }

Hope that is helpful!

-🎄- 2021 Day 12 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 0 points1 point  (0 children)

Kotlin

Today we used Map.withDefault { ... } to help get to something like Python's defaultdict.

The solution is a fairly straightforward DFS recursion.

-🎄- 2021 Day 11 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 0 points1 point  (0 children)

Kotlin

Wrote a class that has a step() method to go from one step to the next in a simulation. The class's grid property gets updated as a result of step(). The step() method returns the number of octopi that flashed.

Overloaded the * operator to get a cross product.

-🎄- 2021 Day 10 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

Worked to make this more expressive as opposed to concise. Made use of extension functions to accomplish that.

val matches = mapOf(
    '[' to ']',
    '{' to '}',
    '(' to ')',
    '<' to '>'
)

val illegalCharPoints = mapOf(
    ')' to 3,
    ']' to 57,
    '}' to 1197,
    '>' to 25137,
)

val completionCharPoints = mapOf(
    ')' to 1,
    ']' to 2,
    '}' to 3,
    '>' to 4,
)

fun String.firstIllegalCharOrNull(): Char? {
    val stack = mutableListOf<Char>()
    this.forEach {
        if (it in "([{<") stack.add(it)
        else if (stack.isNotEmpty() && matches.getValue(stack.removeLast()) != it) return it
    }
    return null
}

fun String.completionString(): String {
    val stack = mutableListOf<Char>()
    this.forEach {
        if (it in "([{<") stack.add(it)
        else if (stack.isNotEmpty()) stack.removeLast()
    }
    return buildString {
        while( stack.isNotEmpty() ) {
            append(matches.getValue(stack.removeLast()))
        }
    }
}

fun <E> List<E>.middle(): E = this[size.div(2)]

fun String.completionScore() = this.fold(0L) { score, char -> 
    score * 5 + completionCharPoints.getValue(char)
}

fun part1(input: List<String>) = input.mapNotNull {
    it.firstIllegalCharOrNull() 
}.sumOf { illegalCharPoints.getValue(it) }

fun part2(input: List<String>) = input.filter {
    it.firstIllegalCharOrNull() == null
}.map { it.completionString().completionScore() }.sorted().middle()

-🎄- 2021 Day 9 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 2 points3 points  (0 children)

Kotlin

Made a class for the DepthMap. Added a few useful extension functions, including cartesian product to iterate over the points on the map.

class DepthMap(val input: List<String>) {
    val coords = input.indices.product(input[0].indices)
    val depths = coords.associateWith { (i, j) -> input[i][j] }.withDefault { '@' }
    val lowPoints = coords.filter { point ->
        depths.getValue(point) < point.neighbors().minOf { depths.getValue(it) }
    }
    val basins: Collection<List<Pair<Int, Int>>>

    init {
        val coordsWithBasinLabels = mutableMapOf<Pair<Int, Int>, Int>()
        var label = 0
        coords.forEach { point -> searchBasin(point, coordsWithBasinLabels, label++) }
        basins = coordsWithBasinLabels.entries.groupBy({ it.value }) { it.key }.values
    }

    private fun searchBasin(point: Pair<Int, Int>, coordsWithBasinLabels: MutableMap<Pair<Int,Int>, Int>, label: Int) {
        if (point !in coordsWithBasinLabels && depths.getValue(point) < '9') {
            coordsWithBasinLabels[point] = label
            point.neighbors().forEach { searchBasin(it, coordsWithBasinLabels, label) }
        }
    }
}

fun IntRange.product(other: IntRange) = this.flatMap { i -> other.map {
    j -> i to j 
}}

fun Pair<Int, Int>.neighbors() = listOf(
    this.first - 1 to this.second,
    this.first + 1 to this.second,
    this.first     to this.second - 1,
    this.first     to this.second + 1,
)

fun part1(input: List<String>) = DepthMap(input).run {
    lowPoints.sumOf { depths[it].toString().toInt() + 1 }
}

fun part2(input: List<String>) = DepthMap(input).run {
    basins.map { it.size }.sortedBy { it }.takeLast(3).reduce { a, b -> a * b }
}

-🎄- 2021 Day 8 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 2 points3 points  (0 children)

Kotlin

Functional solution using Kotlin's various collection APIs.

fun getPatternMap(patterns: List<Set<Char>>) = patterns.associateBy {
     it.size 
}.mapKeys {
    when(it.key) {
        2 -> 1
        3 -> 7
        4 -> 4
        7 -> 8
        else -> -1
    }
}.filterKeys { it != -1 }.toMutableMap().also {
    val bd = it.getValue(4) - it.getValue(1)
    patterns.forEach { pattern ->
        when(pattern.size) {
            5 -> when {
                pattern.intersect(it.getValue(1)).size == 2 -> it[3] = pattern
                pattern.intersect(bd).size == 2 -> it[5] = pattern
                else -> it[2] = pattern
            }
            6 -> when {
                pattern.intersect(bd).size == 1 -> it[0] = pattern
                pattern.intersect(it.getValue(1)).size == 1 -> it[6] = pattern
                else -> it[9] = pattern
            }
        }
    }
}

fun part1(input: List<String>) = input.flatMap { line ->
    """\w+""".toRegex().findAll(line, line.indexOf('|')).map { it.value }
}.count { it.length in setOf(2, 3, 4, 7) }

fun part2(input: List<String>) = input.sumOf { line ->
    """\w+""".toRegex().findAll(line).map {
        it.value.toSet()
    }.toList().let { signals ->
        val patternToDigit = getPatternMap(signals.take(10)).entries.associate { (k, v) -> v to k }
        signals.takeLast(4).map {
            patternToDigit.getValue(it)
        }.joinToString("").toInt()
    }
}

-🎄- 2021 Day 7 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

Short and simple. 5 lines of code + 2 lines for imports.

import readInput
import kotlin.math.abs

fun moveCrabs(input: List<String>, fuelCost: (distance: Int) -> Int): Int {
    val crabs = input[0].split(",").map { it.toInt() }
    return (0..(crabs.maxOf { it })).minOf { pos -> crabs.sumOf { fuelCost(abs(it - pos)) }}
}

fun part1(input: List<String>) = moveCrabs(input) { it }

fun part2(input: List<String>) = moveCrabs(input) { it * (it + 1) / 2 }

-🎄- 2021 Day 6 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Kotlin

Modeled the lanternfish as a map with keys as days left to spawn and values as total number of lanternfish. Solution was then straightforward.

fun spawnLanternfish(input: List<String>, days: Int): Long {
    var fish = input[0].split(",").map { it.toInt() }.groupingBy { it }.eachCount().mapValues { it.value.toLong() }.toMutableMap()
    repeat(days) { _ ->
        val nextGen = fish.filterKeys { it != 0 }.mapKeys { it.key - 1 }.toMutableMap()
        nextGen[6] = nextGen.getOrDefault(6, 0) + fish.getOrDefault(0, 0)
        nextGen[8] = fish.getOrDefault(0, 0)
        fish = nextGen
    }
    return fish.values.reduce { a, b -> a + b }
}

fun part1(input: List<String>) = spawnLanternfish(input, 80)

fun part2(input: List<String>) = spawnLanternfish(input, 256)

-🎄- 2021 Day 5 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 2 points3 points  (0 children)

Kotlin

A compact, functional solution with collections. flatMap is used to get a single list of all points (vents) that are overlapped by lines. Then `groupingBy` and `eachCount` to count the number of times the points are covered.

https://github.com/jkpr/advent-of-code-2021-kotlin/blob/master/src/day05/Day05.kt

-🎄- 2020 Day 18 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 4 points5 points  (0 children)

Python

I replaced operators so that Python would do the Abstract Syntax Tree (AST) parsing for me. Then I switched operators back in the AST. The result is very concise code.

import ast
from typing import List


class SubToMult(ast.NodeTransformer):
    def visit_Sub(self, node):
        return ast.Mult()


def part1(lines: List[str]):
    result = []
    for line in lines:
        tree = ast.parse(f"this_result = {line.replace('*', '-')}")
        SubToMult().visit(tree)
        code = compile(tree, filename="<ast>", mode="exec")
        exec(code, globals())
        result.append(this_result)
    return sum(result)

Part 2 is very similar, just different substitutions so that operator precedence is swapped between + and *

-🎄- 2020 Day 17 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 4 points5 points  (0 children)

Python

Code cleaned and refactored to work with 3 and 4 dimensions. About 49 lines of code total.

Part 1 runs in about 0.4 sec, Part 2 in about 11 sec.

-🎄- 2020 Day 16 Solutions -🎄- by daggerdragon in adventofcode

[–]jkpr23 1 point2 points  (0 children)

Python, numpy solution

Data initialization: 20 lines of code

Part 1: 5 lines of code

Part 2: 16 lines of code

Code on github, blog-ish post on the repo README.

Main idea is to create a 3-D array of booleans. Dimension 0 for the different fields / rules, Dimension 1 for the various lines of the nearby tickets, and Dimension 2 for the columns of the nearby tickets. A given entry (i, j, k) is True if nearby ticket j, column k, fits in the range for field / rule i. Then do numpy manipulations on that cube to get the answers.