diff options
-rw-r--r-- | src/Day01.kt | 10 | ||||
-rw-r--r-- | src/Day02.kt | 30 | ||||
-rw-r--r-- | src/Day03.kt | 55 | ||||
-rw-r--r-- | src/Utils.kt | 8 |
4 files changed, 56 insertions, 47 deletions
diff --git a/src/Day01.kt b/src/Day01.kt index 7503c69..6d45527 100644 --- a/src/Day01.kt +++ b/src/Day01.kt @@ -1,24 +1,22 @@ fun main() { - fun part1(input: List<String>): Int = + fun part1(input: List<Int>): Int = input - .map { it.toInt() } .zipWithNext() .count { it.second > it.first } - fun part2(input: List<String>): Int = + fun part2(input: List<Int>): Int = input .asSequence() - .map { it.toInt() } .windowed(3) .map { it.sum() } .zipWithNext() .count { it.second > it.first } - val testInput = readInput("Day01_test") + val testInput = readInputAsNumbers("Day01_test") check(part1(testInput) == 7) check(part2(testInput) == 5) - val input = readInput("Day01") + val input = readInputAsNumbers("Day01") println(part1(input)) println(part2(input)) } diff --git a/src/Day02.kt b/src/Day02.kt index dd3992b..1b4bfad 100644 --- a/src/Day02.kt +++ b/src/Day02.kt @@ -1,14 +1,20 @@ fun main() { + fun dispatchCommands(commands: List<String>, action: (command: String, argument: Int) -> Unit) { + for (line in commands) { + val parts = line.split(" ") + val command = parts[0] + val argument = parts[1].toInt() + + action(command, argument) + } + } + fun part1(input: List<String>): Int { var horizontal = 0 var depth = 0 - for (line in input) { - val parts = line.split(" ") - val commandName = parts[0] - val argument = parts[1].toInt() - - when (commandName) { + dispatchCommands(input) { command, argument -> + when (command) { "forward" -> horizontal += argument "down" -> depth += argument "up" -> depth -= argument @@ -23,12 +29,8 @@ fun main() { var depth = 0 var aim = 0 - for (line in input) { - val parts = line.split(" ") - val commandName = parts[0] - val argument = parts[1].toInt() - - when (commandName) { + dispatchCommands(input) { command, argument -> + when (command) { "forward" -> { horizontal += argument depth += aim * argument @@ -41,11 +43,11 @@ fun main() { return horizontal * depth } - val testInput = readInput("Day02_test") + val testInput = readInputAsLines("Day02_test") check(part1(testInput) == 150) check(part2(testInput) == 900) - val input = readInput("Day02") + val input = readInputAsLines("Day02") println(part1(input)) println(part2(input)) } diff --git a/src/Day03.kt b/src/Day03.kt index c6acda4..c64da47 100644 --- a/src/Day03.kt +++ b/src/Day03.kt @@ -1,46 +1,49 @@ fun main() { fun addLists(l1: List<Int>, l2: List<Int>): List<Int> = l1.zip(l2).map { it.first + it.second } - fun bitListToNumber(bitList: List<Int>): Int = bitList.reduce { acc, bit -> acc * 2 + bit } + fun valueOfBits(bitList: List<Int>): Int = bitList.reduce { acc, bit -> acc * 2 + bit } - fun binaryStringToBitList(binaryString: String): List<Int> = binaryString.toList().map { bit -> bit.toString().toInt() } + fun invertBits(bitList: List<Int>): List<Int> = bitList.map { bit -> 1 - bit } fun mostCommonBits(input: List<List<Int>>): List<Int> = input .reduce(::addLists) - .map { bit -> if (bit.toDouble() / input.size >= 0.5) { 1 } else { 0 } } - - fun part1(input: List<String>): Int = - mostCommonBits(input.map(::binaryStringToBitList)) - .let { gammaBits -> - val epsilonBits = gammaBits.map { bit -> 1 - bit } + .map { bit -> if (bit.toDouble() / input.size >= 0.5) 1 else 0 } + + fun selectByBitCriteria( + input: List<List<Int>>, + comparisonCriteria: (currentList: List<List<Int>>) -> List<Int> + ): List<Int>? { + var list = input + var index = 0 + + while (list.size > 1 && index < list[0].size) { + list = list.filter { e -> e[index] == comparisonCriteria(list)[index] } + index += 1 + } - return bitListToNumber(gammaBits) * bitListToNumber(epsilonBits) - } + return list.getOrNull(0) + } - fun part2(input: List<String>): Int { - var oxygenList = input.map(::binaryStringToBitList) - var oxygenIdx = 0 - while (oxygenList.size > 1) { - oxygenList = oxygenList.filter { e -> e[oxygenIdx] == mostCommonBits(oxygenList)[oxygenIdx]} - oxygenIdx += 1 + fun part1(input: List<List<Int>>): Int = + mostCommonBits(input) + .let { gammaBits -> + val epsilonBits = invertBits(gammaBits) + return valueOfBits(gammaBits) * valueOfBits(epsilonBits) } - var scrubberList = input.map(::binaryStringToBitList) - var scrubberIdx = 0 - while (scrubberList.size > 1) { - scrubberList = scrubberList.filter { e -> e[scrubberIdx] != mostCommonBits(scrubberList)[scrubberIdx]} - scrubberIdx += 1 - } + fun part2(input: List<List<Int>>): Int { + val oxygenRating = selectByBitCriteria(input) { mostCommonBits(it) }!! + val scrubberRating = selectByBitCriteria(input) { invertBits(mostCommonBits(it)) }!! - return bitListToNumber(oxygenList[0]) * bitListToNumber(scrubberList[0]) - } + return valueOfBits(oxygenRating) * valueOfBits(scrubberRating) + } - val testInput = readInput("Day03_test") + val testInput = readInputAsBitLists("Day03_test") check(part1(testInput) == 198) check(part2(testInput) == 230) - val input = readInput("Day03") + val input = readInputAsBitLists("Day03") println(part1(input)) println(part2(input)) } diff --git a/src/Utils.kt b/src/Utils.kt index acfb72a..23eacb9 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -5,7 +5,13 @@ import java.security.MessageDigest /** * Reads lines from the given input txt file. */ -fun readInput(name: String) = File("src", "$name.txt").readLines() +fun readInputAsLines(name: String): List<String> = File("src", "$name.txt").readLines() + +fun readInputAsNumbers(name: String): List<Int> = readInputAsLines(name).map { it.toInt() } + +fun readInputAsBitLists(name: String): List<List<Int>> = + readInputAsLines(name) + .map { binaryString -> binaryString.toList().map { bit -> bit.toString().toInt() } } /** * Converts string to md5 hash. |