-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Copied 2019 solutions from old repo, without editing https://github.com/hibob224/aoc2019
- Loading branch information
Showing
43 changed files
with
1,148 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import java.util.concurrent.BlockingQueue | ||
import java.util.concurrent.Callable | ||
import java.util.concurrent.LinkedBlockingQueue | ||
|
||
typealias Input = () -> Long | ||
typealias Output = (Long) -> Unit | ||
|
||
class IntCodeComputer( | ||
inpMemory: LongArray, | ||
var latestOutput: Long = -1 | ||
) : Callable<Long> { | ||
|
||
private val memory = LongArray(10000) { 0 } | ||
private val inputs = LinkedBlockingQueue<Long>() | ||
var outputComputer: IntCodeComputer? = null | ||
var outputArray: BlockingQueue<Long>? = null | ||
var input: Input? = null | ||
var output: Output? = null | ||
|
||
init { | ||
inpMemory.copyInto(memory) | ||
} | ||
|
||
fun addInput(vararg input: Long) { | ||
inputs.addAll(input.toList()) | ||
} | ||
|
||
override fun call(): Long { | ||
var position = 0 | ||
var relativeBase = 0 | ||
|
||
do { | ||
val opcode = memory[position].toString().padStart(5, '0') | ||
val parsedOpcode = opcode.substring(opcode.lastIndex.dec()).toInt() | ||
val modes = mutableListOf( | ||
opcode[0].toString().toInt(), | ||
opcode[1].toString().toInt(), | ||
opcode[2].toString().toInt() | ||
) | ||
|
||
val inp1 = when (modes[2]) { | ||
0 -> memory.getOrElse(memory.getOrElse(position.inc()) { 0L }.toInt()) { 0L } | ||
1 -> memory.getOrElse(position.inc()) { 0L } | ||
2 -> memory.getOrElse(memory.getOrElse(position.inc()) { 0L }.toInt() + relativeBase) { 0L } | ||
else -> throw IllegalArgumentException("Fucked") | ||
} | ||
val inp2 = when (modes[1]) { | ||
0 -> memory.getOrElse(memory.getOrElse(position.inc().inc()) { 0L }.toInt()) { 0L } | ||
1 -> memory.getOrElse(position.inc().inc()) { 0L } | ||
2 -> memory.getOrElse(memory.getOrElse(position.inc().inc()) { 0L }.toInt() + relativeBase) { 0L } | ||
else -> throw IllegalArgumentException("Fucked") | ||
} | ||
val inp3 = when (modes[0]) { | ||
0, 1 -> memory.getOrElse(position.inc().inc().inc()) { 0L } | ||
2 -> memory.getOrElse(position.inc().inc().inc()) { 0L } + relativeBase | ||
else -> throw IllegalArgumentException("Fucked") | ||
}.toInt() | ||
|
||
when (parsedOpcode) { | ||
1 -> { | ||
memory[inp3] = inp1 + inp2 | ||
position += 4 | ||
} | ||
2 -> { | ||
memory[inp3] = inp1 * inp2 | ||
position += 4 | ||
} | ||
3 -> { | ||
val out = when (modes[2]) { | ||
0, 1 -> memory.getOrElse(position.inc()) { 0L } | ||
2 -> memory.getOrElse(position.inc()) { 0L } + relativeBase | ||
else -> throw IllegalArgumentException("Fucked") | ||
}.toInt() | ||
input?.let { | ||
memory[out] = it.invoke() | ||
} ?: kotlin.run { memory[out] = inputs.take() } | ||
position += 2 | ||
} | ||
4 -> { | ||
latestOutput = inp1 | ||
output?.invoke(inp1) | ||
outputComputer?.inputs?.add(inp1) | ||
outputArray?.add(inp1) | ||
position += 2 | ||
} | ||
5 -> { | ||
if (inp1 != 0L) { | ||
position = inp2.toInt() | ||
} else { | ||
position += 3 | ||
} | ||
} | ||
6 -> { | ||
if (inp1 == 0L) { | ||
position = inp2.toInt() | ||
} else { | ||
position += 3 | ||
} | ||
} | ||
7 -> { | ||
memory[inp3] = if (inp1 < inp2) 1L else 0L | ||
position += 4 | ||
} | ||
8 -> { | ||
memory[inp3] = if (inp1 == inp2) 1L else 0L | ||
position += 4 | ||
} | ||
9 -> { | ||
relativeBase += inp1.toInt() | ||
position += 2 | ||
} | ||
99 -> return latestOutput | ||
else -> throw IllegalStateException("Unknown opcode $opcode") | ||
} | ||
} while (true) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package y2019.day01 | ||
|
||
import utils.getInputFile | ||
import utils.orZero | ||
|
||
fun main() { | ||
println("Part one: ${Day1.solvePartOne()}") | ||
println("Part two: ${Day1.solvePartTwo()}") | ||
} | ||
|
||
object Day1 { | ||
|
||
private val moduleMasses = getInputFile().readLines().map(String::toInt) | ||
|
||
fun solvePartOne(): String = moduleMasses.sumBy { calculateRequiredFuel(it) }.toString() | ||
|
||
fun solvePartTwo(): String { | ||
return moduleMasses.fold(0) { acc, mass -> | ||
var requiredFuel = 0 | ||
var temp = mass | ||
while (temp > 0) { | ||
temp = calculateRequiredFuel(temp) | ||
requiredFuel += temp | ||
} | ||
acc + requiredFuel | ||
}.toString() | ||
} | ||
|
||
private fun calculateRequiredFuel(mass: Int) = (mass / 3 - 2).takeIf { it > 0 }.orZero() | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package y2019.day02 | ||
|
||
import utils.getInputFile | ||
|
||
fun main() { | ||
println("Part one: ${Day2.solvePartOne()}") | ||
println("Part two: ${Day2.solvePartTwo()}") | ||
} | ||
|
||
object Day2 { | ||
|
||
private val input = getInputFile().readText().split(",").map(String::toInt) | ||
|
||
fun solvePartOne(): String { | ||
val partOneInput = ArrayList(input) | ||
partOneInput[1] = 12 | ||
partOneInput[2] = 2 | ||
return runProgram(partOneInput).toString() | ||
} | ||
|
||
fun solvePartTwo(): String { | ||
for (n in 0..99) { | ||
for (v in 0..99) { | ||
val input = ArrayList(input) | ||
input[1] = n | ||
input[2] = v | ||
val output = runProgram(input) | ||
if (output == 19690720) { | ||
return (100 * n + v).toString() | ||
} | ||
} | ||
} | ||
throw IllegalStateException("Didn't find answer") | ||
} | ||
|
||
private fun runProgram(input: ArrayList<Int>): Int { | ||
var position = 0 | ||
do { | ||
val opcode = input[position] | ||
val inp1 = input[position.inc()] | ||
val inp2 = input[position.inc().inc()] | ||
val out = input[position.inc().inc().inc()] | ||
|
||
when (opcode) { | ||
1 -> input[out] = input[inp1] + input[inp2] | ||
2 -> input[out] = input[inp1] * input[inp2] | ||
99 -> return input[0] | ||
else -> return -1 // Exception | ||
} | ||
|
||
position += 4 | ||
} while (true) | ||
} | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package y2019.day03 | ||
|
||
import utils.Point | ||
import utils.getInputFile | ||
import kotlin.math.abs | ||
|
||
fun main() { | ||
println("Part one: ${Day3.solvePartOne()}") | ||
println("Part two: ${Day3.solvePartTwo()}") | ||
} | ||
|
||
object Day3 { | ||
|
||
private val lineOne = mutableListOf(Wire(0, 0)) | ||
private val lineTwo = mutableListOf(Wire(0, 0)) | ||
|
||
init { | ||
val lineOneInput = parseInput()[0] | ||
val lineTwoInput = parseInput()[1] | ||
lineOneInput.forEach { lineOne.addAll(lineOne.last().move(it)) } | ||
lineTwoInput.forEach { lineTwo.addAll(lineTwo.last().move(it)) } | ||
lineOne.removeAt(0) | ||
lineTwo.removeAt(0) | ||
} | ||
|
||
private fun parseInput(): List<List<String>> = | ||
getInputFile().readLines().map { it.split(",") } | ||
|
||
fun solvePartOne(): String = lineOne.intersect(lineTwo.toSet()).minOfOrNull { it.distanceFromOrigin() }.toString() | ||
|
||
fun solvePartTwo(): String = lineOne.intersect(lineTwo.toSet()).minOfOrNull { intersect -> | ||
lineOne.first { intersect == it }.steps + lineTwo.first { intersect == it }.steps | ||
}.toString() | ||
|
||
// Basically just Point, but have copied in this solution years later so, not fixing it now | ||
private data class Wire(val x: Int, val y: Int) { | ||
|
||
var steps = 0 | ||
|
||
fun move(movement: String): List<Wire> { | ||
val direction = movement.first() | ||
val steps = movement.substring(1).toInt() | ||
|
||
return (1..steps).map { step -> | ||
when (direction) { | ||
'R' -> copy(x = x + step) | ||
'L' -> copy(x = x - step) | ||
'U' -> copy(y = y - step) | ||
'D' -> copy(y = y + step) | ||
else -> throw IllegalArgumentException("Unknown movement type") | ||
}.also { it.steps += this.steps + step } | ||
} | ||
} | ||
|
||
fun distanceFromOrigin(): Int = manhattan(Point(0, 0)) | ||
|
||
fun manhattan(other: Point): Int = abs(x - other.x) + abs(y - other.y) | ||
} | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package y2019.day04 | ||
|
||
import utils.orFalse | ||
|
||
fun main() { | ||
println("Part one: ${Day4.solvePartOne()}") | ||
println("Part two: ${Day4.solvePartTwo()}") | ||
} | ||
|
||
object Day4 { | ||
|
||
private val range = 240920..789857 | ||
|
||
fun solvePartOne(): String { | ||
return range.count { pw -> | ||
val zipped = pw.toString().zipWithNext() | ||
zipped.all { it.first <= it.second } && | ||
zipped.any { it.first == it.second } | ||
}.toString() | ||
} | ||
|
||
fun solvePartTwo(): String { | ||
return range.count { pw -> | ||
val zipped = pw.toString().zipWithNext() | ||
zipped.all { it.first <= it.second } && | ||
zipped.filter { it.first == it.second } | ||
.groupBy { it.first } | ||
.entries | ||
.takeIf { it.isNotEmpty() } | ||
?.any { it.value.size == 1 } | ||
.orFalse() | ||
}.toString() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package y2019.day05 | ||
|
||
import IntCodeComputer | ||
import utils.getInputFile | ||
|
||
fun main() { | ||
println("Part one: ${Day5.solvePartOne()}") | ||
println("Parse two: ${Day5.solvePartTwo()}") | ||
} | ||
|
||
object Day5 { | ||
|
||
private fun parseInput(): List<Long> = getInputFile() | ||
.readLines()[0] | ||
.split(",") | ||
.map { it.toLong() } | ||
|
||
fun solvePartOne(): String = IntCodeComputer(parseInput().toLongArray()).also { it.addInput(1) }.call().toString() | ||
|
||
fun solvePartTwo(): String = IntCodeComputer(parseInput().toLongArray()).also { it.addInput(5) }.call().toString() | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package y2019.day06 | ||
|
||
import utils.getInputFile | ||
|
||
fun main() { | ||
println("Part one: ${Day6.solvePartOne()}") | ||
println("Part two: ${Day6.solvePartTwo()}") | ||
} | ||
|
||
object Day6 { | ||
|
||
private fun parseInput(): Map<String, List<String>> = | ||
getInputFile() | ||
.readLines() | ||
.map { it.split(")")[0] to it.split(")")[1] } | ||
.groupBy({ it.first }) { it.second } | ||
|
||
fun solvePartOne(): String { | ||
val input = parseInput() | ||
var count = 0 | ||
|
||
input.forEach { | ||
count += it.value.size | ||
val multiplier = it.value.size | ||
var target = it.key | ||
while (true) { | ||
input.entries.find { it.value.contains(target) }?.let { | ||
count += 1 * multiplier | ||
target = it.key | ||
} ?: break | ||
} | ||
} | ||
|
||
return count.toString() | ||
} | ||
|
||
fun solvePartTwo(): String { | ||
val input = parseInput() | ||
val youLoc = input.entries.find { it.value.contains("YOU") }!!.key | ||
val santaLoc = input.entries.find { it.value.contains("SAN") }!!.key | ||
|
||
val steps = mutableListOf(listOf(youLoc)) | ||
|
||
while (true) { | ||
var newFrontline = mutableListOf<String>() | ||
|
||
newFrontline.addAll(steps.last().flatMap { input[it].orEmpty() }) // Add all objects that orbit our current objects | ||
newFrontline.addAll(steps.last().mapNotNull { loc -> // Add all our direct orbits | ||
input.entries.find { it.value.contains(loc) }?.key | ||
}) | ||
newFrontline = newFrontline.filterNot { steps.flatten().contains(it) }.toMutableList() // Make sure we're not checking locations we've checked before | ||
newFrontline = newFrontline.distinct().toMutableList() // Remove duplicates | ||
steps.add(newFrontline) | ||
if (newFrontline.contains(santaLoc)) { | ||
// We've found Santa! | ||
break | ||
} | ||
} | ||
|
||
// Decrease steps by 1 because we don't count the starting location | ||
return steps.size.dec().toString() | ||
} | ||
} |
Binary file not shown.
Oops, something went wrong.