DEV Community

Discussion on: Advent of Code 2019 Solution Megathread - Day 8: Space Image Format

Collapse
 
jbristow profile image
Jon Bristow

This was a nice and simple solution as long as you remembered how to pivot a list of lists. Kotlin's builtin minBy and count functions also simplify things a lot.

import arrow.core.firstOrNone
import arrow.core.getOrElse
import java.nio.file.Files
import java.nio.file.Paths

object Day08 {

    private const val FILENAME = "src/main/resources/day08.txt"
    val fileData: String = Files.readAllLines(Paths.get(FILENAME)).first()

    private fun List<String>.countAllEqualTo(match: Char): Int {
        return sumBy { row -> row.count { pixel -> pixel == match } }
    }

    fun part1(input: String): Int {
        val layerWithLeast0s = input.chunked(25).chunked(6).minBy { layer ->
            layer.countAllEqualTo('0')
        }.orEmpty()

        val num1s = layerWithLeast0s.countAllEqualTo('1')
        val num2s = layerWithLeast0s.countAllEqualTo('2')
        return num1s * num2s
    }

    private fun List<String>.findPixelColors() =
        (this[0].indices).map { i -> map { it[i] } }
            .map(this@Day08::findPixelColor)

    private fun findPixelColor(it: List<Char>) =
        it.dropWhile { c -> c == '2' }
            .firstOrNone()
            .getOrElse { '2' }

    private fun List<List<Char>>.renderImage() =
        joinToString("\n") { row ->
            row.joinToString("") { pixel ->
                when (pixel) {
                    '0' -> '.'
                    '1' -> '#'
                    '2' -> ' '
                    else -> '?'
                }.toString()
            }
        }

    fun part2(input: String) =
        input.chunked(25 * 6)
            .findPixelColors()
            .chunked(25)
            .renderImage()

}

fun main() {
    println(Day08.part1(Day08.fileData))
    println(Day08.part2(Day08.fileData))
}
Collapse
 
jbristow profile image
Jon Bristow • Edited

Here's a version of part1 that does everything in two passes of the list instead of four.

    fun part1(input: String) =
        input.chunked(25 * 6)
            .asSequence()
            .map { layer ->
                layer.groupBy { it }
                    .mapValues { (_, v) -> v.size }
            }.minBy { it.getOrDefault('0', 0) }?.let {
                it.getOrDefault('1', 0) * it.getOrDefault('2', 0)
            } ?: 0