aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Day01.kt10
-rw-r--r--src/Day02.kt30
-rw-r--r--src/Day03.kt55
-rw-r--r--src/Utils.kt8
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.