Last active
December 10, 2019 08:02
-
-
Save ryanmoelter/84d3a6050a34cad2b6c3af48d315f09e to your computer and use it in GitHub Desktop.
Advent of code 2019
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
/* Run in IntelliJ scratch file */ | |
// AoC 2019, day 2 | |
enum class Operation(val action: (Int, Int) -> Int) { | |
PLUS({ first, second -> first + second }), | |
MULTIPLY({ first, second -> first * second }), | |
UNKNOWN({ _, _ -> throw IllegalArgumentException("No operation specified") }) | |
} | |
fun performOperation(address: Int, opcodes: MutableList<Int>): Boolean { | |
val operation = when (opcodes[address]) { | |
1 -> Operation.PLUS | |
2 -> Operation.MULTIPLY | |
99 -> return true | |
else -> Operation.UNKNOWN | |
} | |
val parameterAddress1 = opcodes[address + 1] | |
val parameterAddress2 = opcodes[address + 2] | |
val destinationAddress = opcodes[address + 3] | |
opcodes[destinationAddress] = operation.action(opcodes[parameterAddress1], opcodes[parameterAddress2]) | |
return false | |
} | |
fun run(originalOpcodes: List<Int>): List<Int> { | |
val opcodes = originalOpcodes.toMutableList() | |
var currentAddress = 0 | |
var done = false | |
while (currentAddress <= opcodes.size && !done) { | |
done = performOperation(currentAddress, opcodes) | |
currentAddress += 4 | |
} | |
return opcodes | |
} | |
fun findProperInput(opcodes: List<Int>): Pair<Int, Int> { | |
for (noun in 0..99) { | |
for (verb in 0..99) { | |
val tempOpcodes = opcodes.toMutableList() | |
tempOpcodes[1] = noun | |
tempOpcodes[2] = verb | |
if (run(tempOpcodes)[0] == 19690720) { | |
return noun to verb | |
} | |
} | |
} | |
throw IllegalStateException("No value found") | |
} | |
val opcodes = listOf( | |
1,12,2,3,1,1,2,3,1,3,4,3,1,5,0,3,2,9,1,19,1,9,19,23,1,23,5,27,2,27,10,31,1,6,31,35,1,6,35,39,2,9,39,43,1,6,43,47,1,47,5,51,1,51,13,55,1,55,13,59,1,59,5,63,2,63,6,67,1,5,67,71,1,71,13,75,1,10,75,79,2,79,6,83,2,9,83,87,1,5,87,91,1,91,5,95,2,9,95,99,1,6,99,103,1,9,103,107,2,9,107,111,1,111,6,115,2,9,115,119,1,119,6,123,1,123,9,127,2,127,13,131,1,131,9,135,1,10,135,139,2,139,10,143,1,143,5,147,2,147,6,151,1,151,5,155,1,2,155,159,1,6,159,0,99,2,0,14,0 | |
) | |
println(run(opcodes)) | |
println(findProperInput(opcodes)) | |
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
import kotlin.math.absoluteValue | |
// AoC 2019, day 3 | |
data class Input(val first: List<String>, val second: List<String>) | |
val testCases = listOf( | |
Input( | |
"R8,U5,L5,D3".split(','), | |
"U7,R6,D4,L4".split(',') | |
) to 6, | |
Input( | |
"R75,D30,R83,U83,L12,D49,R71,U7,L72".split(','), | |
"U62,R66,U55,R34,D71,R55,D58,R83".split(',') | |
) to 159, | |
Input( | |
"R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51".split(','), | |
"U98,R91,D20,R16,D67,R40,U7,R15,U6,R7".split(',') | |
) to 135, | |
Input( | |
"R1007,D949,R640,D225,R390,D41,R257,D180,L372,U62,L454,U594,L427,U561,R844,D435,L730,U964,L164,U342,R293,D490,L246,U323,L14,D366,L549,U312,L851,U959,L255,U947,L179,U109,R850,D703,L310,U175,L665,U515,R23,D633,L212,U650,R477,U131,L838,D445,R999,D229,L772,U716,L137,U355,R51,D565,L410,D493,L312,U623,L846,D283,R980,U804,L791,U918,L641,U258,R301,U727,L307,U970,L748,U229,L225,U997,L134,D707,L655,D168,L931,D6,R36,D617,L211,D453,L969,U577,R299,D804,R910,D898,R553,U298,L309,D912,R757,U581,R228,U586,L331,D865,R606,D163,R425,U670,R156,U814,L168,D777,R674,D970,L64,U840,L688,U144,L101,U281,L615,D393,R277,U990,L9,U619,L904,D967,L166,U839,L132,U216,R988,U834,R342,U197,L717,U167,L524,U747,L222,U736,L149,D156,L265,U657,L72,D728,L966,U896,R45,D985,R297,U38,R6,D390,L65,D367,R806,U999,L840,D583,R646,U43,L731,D929,L941,D165,R663,U645,L753,U619,R60,D14,L811,D622,L835,U127,L475,D494,R466,U695,R809,U446,R523,D403,R843,U715,L486,D661,L584,U818,L377,D857,L220,U309,R192,U601,R253,D13,L95,U32,L646,D983,R13,U821,L1,U309,L425,U993,L785,U804,L663,U699,L286,U280,R237,U388,L170,D222,L900,U204,R68,D453,R721,U326,L629,D44,R925,D347,R264,D767,L785,U249,R989,D469,L446,D384,L914,U444,R741,U90,R424,U107,R98,U20,R302,U464,L808,D615,R837,U405,L191,D26,R661,D758,L866,D640,L675,U135,R288,D357,R316,D127,R599,U411,R664,D584,L979,D432,R887,D104,R275,D825,L338,D739,R568,D625,L829,D393,L997,D291,L448,D947,L728,U181,L137,D572,L16,U358,R331,D966,R887,D122,L334,D560,R938,D159,R178,D29,L832,D58,R374".split(','), | |
"L993,U121,L882,U500,L740,D222,R574,U947,L541,U949,L219,D492,R108,D621,L875,D715,R274,D858,R510,U668,R677,U327,L284,U537,L371,U810,L360,U333,L926,D144,R162,U750,L741,D360,R792,D256,L44,D893,R969,D996,L905,D524,R538,U141,R70,U347,L383,U74,R893,D560,L39,U447,L205,D783,L244,D40,R374,U507,L946,D934,R962,D138,L584,U562,L624,U69,L77,D137,L441,U671,L849,D283,L742,D459,R105,D265,R312,D734,R47,D369,R676,D429,R160,D814,L881,D830,R395,U598,L413,U817,R855,D377,L338,D413,L294,U321,L714,D217,L15,U341,R342,D480,R660,D11,L192,U518,L654,U13,L984,D866,R877,U801,R413,U66,R269,D750,R294,D143,R929,D786,R606,U816,L562,U938,R484,U32,R136,U30,L393,U209,L838,U451,L387,U413,R518,D9,L847,D605,L8,D805,R348,D174,R865,U962,R926,U401,R445,U720,L843,U785,R287,D656,L489,D465,L192,U68,L738,U962,R384,U288,L517,U396,L955,U556,R707,U329,L589,U604,L583,U457,R545,D504,L521,U711,L232,D329,L110,U167,R311,D234,R284,D984,L778,D295,R603,U349,R942,U81,R972,D505,L301,U422,R840,U689,R225,D780,R379,D200,R57,D781,R166,U245,L865,U790,R654,D127,R125,D363,L989,D976,R993,U702,L461,U165,L747,U656,R617,D115,L783,U187,L462,U838,R854,D516,L978,U846,R203,D46,R833,U393,L322,D17,L160,D278,R919,U611,L59,U709,L472,U871,L377,U111,L612,D177,R712,U628,R858,D54,L612,D303,R205,U430,R494,D306,L474,U848,R816,D104,L967,U886,L866,D366,L120,D735,R694,D335,R399,D198,R132,D787,L749,D612,R525,U163,R660,U316,R482,D412,L376,U170,R891,D202,R408,D333,R842,U965,R955,U440,L26,U747,R447,D8,R319,D188,L532,D39,L863,D599,R307,U253,R22".split(',') | |
) to null | |
) | |
enum class Orientation { HORIZONTAL, VERTICAL; | |
val opposite get() = when (this) { | |
HORIZONTAL -> VERTICAL | |
VERTICAL -> HORIZONTAL | |
} | |
} | |
data class Segment(val start: Int, val end: Int, val crossAxis: Int, val orientation: Orientation) { | |
val distanceVector = end - start | |
val range = minOf(start, end)..maxOf(start, end) | |
override fun toString(): String { | |
return when (orientation) { | |
Orientation.HORIZONTAL -> "($start, $crossAxis) -> ($end, $crossAxis)" | |
Orientation.VERTICAL -> "($crossAxis, $start) -> ($crossAxis, $end)" | |
} | |
} | |
} | |
fun parseSegment(string: String, startX: Int, startY: Int): Segment { | |
val distance = string | |
.substring(1 until string.length) | |
.toInt() | |
return when(string.first()) { | |
'R' -> Segment(startX, startX + distance, startY, Orientation.HORIZONTAL) | |
'L' -> Segment(startX, startX - distance, startY, Orientation.HORIZONTAL) | |
'U' -> Segment(startY, startY + distance, startX, Orientation.VERTICAL) | |
'D' -> Segment(startY, startY - distance, startX, Orientation.VERTICAL) | |
else -> throw IllegalArgumentException("Unknown direction: ${string.first()}") | |
} | |
} | |
fun parseSegmentList(firstPath: List<String>): List<Segment> { | |
var currentX = 0 | |
var currentY = 0 | |
return firstPath | |
.map { | |
parseSegment(it, currentX, currentY).also { segment -> | |
when (segment.orientation) { | |
Orientation.HORIZONTAL -> currentX += segment.distanceVector | |
Orientation.VERTICAL -> currentY += segment.distanceVector | |
} | |
} | |
} | |
// .map { | |
// println("Segment: $it") | |
// it | |
// } | |
} | |
fun findIntersectionDistances(firstSegments: List<Segment>, secondSegments: List<Segment>): List<Int> { | |
return firstSegments | |
.map { firstSegment -> | |
secondSegments | |
.filter { it.orientation == firstSegment.orientation.opposite } | |
.filter { it.crossAxis != 0 || firstSegment.crossAxis != 0 } | |
.filter { | |
// println("(comparing: $firstSegment and $it)") | |
(it.crossAxis in firstSegment.range) && (firstSegment.crossAxis in it.range) | |
} | |
.map { | |
// println("Intersection: $firstSegment and $it") | |
firstSegment.crossAxis.absoluteValue + it.crossAxis.absoluteValue | |
} | |
} | |
.fold(emptyList()) { acc: List<Int>, distanceList: List<Int> -> acc + distanceList } | |
} | |
fun run(firstPath: List<String>, secondPath: List<String>): Int? { | |
val firstSegments = parseSegmentList(firstPath) | |
val secondSegments = parseSegmentList(secondPath) | |
return findIntersectionDistances(firstSegments, secondSegments).min() | |
} | |
testCases.forEachIndexed { index, (input, expectedResult) -> | |
println("${input.first} | ${input.second}") | |
println("${index + 1}: ${run(input.first, input.second)} (expected $expectedResult)") | |
} |
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
import kotlin.math.absoluteValue | |
// AoC 2019, day 3 | |
data class Input(val first: List<String>, val second: List<String>) | |
val testCases = listOf( | |
Input( | |
"R8,U5,L5,D3".split(','), | |
"U7,R6,D4,L4".split(',') | |
) to 30, | |
Input( | |
"R75,D30,R83,U83,L12,D49,R71,U7,L72".split(','), | |
"U62,R66,U55,R34,D71,R55,D58,R83".split(',') | |
) to 610, | |
Input( | |
"R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51".split(','), | |
"U98,R91,D20,R16,D67,R40,U7,R15,U6,R7".split(',') | |
) to 410, | |
Input( | |
"R1007,D949,R640,D225,R390,D41,R257,D180,L372,U62,L454,U594,L427,U561,R844,D435,L730,U964,L164,U342,R293,D490,L246,U323,L14,D366,L549,U312,L851,U959,L255,U947,L179,U109,R850,D703,L310,U175,L665,U515,R23,D633,L212,U650,R477,U131,L838,D445,R999,D229,L772,U716,L137,U355,R51,D565,L410,D493,L312,U623,L846,D283,R980,U804,L791,U918,L641,U258,R301,U727,L307,U970,L748,U229,L225,U997,L134,D707,L655,D168,L931,D6,R36,D617,L211,D453,L969,U577,R299,D804,R910,D898,R553,U298,L309,D912,R757,U581,R228,U586,L331,D865,R606,D163,R425,U670,R156,U814,L168,D777,R674,D970,L64,U840,L688,U144,L101,U281,L615,D393,R277,U990,L9,U619,L904,D967,L166,U839,L132,U216,R988,U834,R342,U197,L717,U167,L524,U747,L222,U736,L149,D156,L265,U657,L72,D728,L966,U896,R45,D985,R297,U38,R6,D390,L65,D367,R806,U999,L840,D583,R646,U43,L731,D929,L941,D165,R663,U645,L753,U619,R60,D14,L811,D622,L835,U127,L475,D494,R466,U695,R809,U446,R523,D403,R843,U715,L486,D661,L584,U818,L377,D857,L220,U309,R192,U601,R253,D13,L95,U32,L646,D983,R13,U821,L1,U309,L425,U993,L785,U804,L663,U699,L286,U280,R237,U388,L170,D222,L900,U204,R68,D453,R721,U326,L629,D44,R925,D347,R264,D767,L785,U249,R989,D469,L446,D384,L914,U444,R741,U90,R424,U107,R98,U20,R302,U464,L808,D615,R837,U405,L191,D26,R661,D758,L866,D640,L675,U135,R288,D357,R316,D127,R599,U411,R664,D584,L979,D432,R887,D104,R275,D825,L338,D739,R568,D625,L829,D393,L997,D291,L448,D947,L728,U181,L137,D572,L16,U358,R331,D966,R887,D122,L334,D560,R938,D159,R178,D29,L832,D58,R374".split(','), | |
"L993,U121,L882,U500,L740,D222,R574,U947,L541,U949,L219,D492,R108,D621,L875,D715,R274,D858,R510,U668,R677,U327,L284,U537,L371,U810,L360,U333,L926,D144,R162,U750,L741,D360,R792,D256,L44,D893,R969,D996,L905,D524,R538,U141,R70,U347,L383,U74,R893,D560,L39,U447,L205,D783,L244,D40,R374,U507,L946,D934,R962,D138,L584,U562,L624,U69,L77,D137,L441,U671,L849,D283,L742,D459,R105,D265,R312,D734,R47,D369,R676,D429,R160,D814,L881,D830,R395,U598,L413,U817,R855,D377,L338,D413,L294,U321,L714,D217,L15,U341,R342,D480,R660,D11,L192,U518,L654,U13,L984,D866,R877,U801,R413,U66,R269,D750,R294,D143,R929,D786,R606,U816,L562,U938,R484,U32,R136,U30,L393,U209,L838,U451,L387,U413,R518,D9,L847,D605,L8,D805,R348,D174,R865,U962,R926,U401,R445,U720,L843,U785,R287,D656,L489,D465,L192,U68,L738,U962,R384,U288,L517,U396,L955,U556,R707,U329,L589,U604,L583,U457,R545,D504,L521,U711,L232,D329,L110,U167,R311,D234,R284,D984,L778,D295,R603,U349,R942,U81,R972,D505,L301,U422,R840,U689,R225,D780,R379,D200,R57,D781,R166,U245,L865,U790,R654,D127,R125,D363,L989,D976,R993,U702,L461,U165,L747,U656,R617,D115,L783,U187,L462,U838,R854,D516,L978,U846,R203,D46,R833,U393,L322,D17,L160,D278,R919,U611,L59,U709,L472,U871,L377,U111,L612,D177,R712,U628,R858,D54,L612,D303,R205,U430,R494,D306,L474,U848,R816,D104,L967,U886,L866,D366,L120,D735,R694,D335,R399,D198,R132,D787,L749,D612,R525,U163,R660,U316,R482,D412,L376,U170,R891,D202,R408,D333,R842,U965,R955,U440,L26,U747,R447,D8,R319,D188,L532,D39,L863,D599,R307,U253,R22".split(',') | |
) to null | |
) | |
enum class Orientation { HORIZONTAL, VERTICAL; | |
val opposite get() = when (this) { | |
HORIZONTAL -> VERTICAL | |
VERTICAL -> HORIZONTAL | |
} | |
} | |
data class Segment( | |
val start: Int, | |
val end: Int, | |
val crossAxis: Int, | |
val orientation: Orientation, | |
val startDistance: Int | |
) { | |
val distanceVector = end - start | |
val range = minOf(start, end)..maxOf(start, end) | |
fun cumulativeDistanceTo(crossAxisValue: Int) = | |
startDistance + (start - crossAxisValue).absoluteValue | |
override fun toString(): String { | |
return when (orientation) { | |
Orientation.HORIZONTAL -> "($start, $crossAxis) -> ($end, $crossAxis)" | |
Orientation.VERTICAL -> "($crossAxis, $start) -> ($crossAxis, $end)" | |
} | |
} | |
} | |
fun parseSegment(string: String, startX: Int, startY: Int, startDistance: Int): Segment { | |
val distance = string | |
.substring(1 until string.length) | |
.toInt() | |
return when(string.first()) { | |
'R' -> Segment(startX, startX + distance, startY, Orientation.HORIZONTAL, startDistance) | |
'L' -> Segment(startX, startX - distance, startY, Orientation.HORIZONTAL, startDistance) | |
'U' -> Segment(startY, startY + distance, startX, Orientation.VERTICAL, startDistance) | |
'D' -> Segment(startY, startY - distance, startX, Orientation.VERTICAL, startDistance) | |
else -> throw IllegalArgumentException("Unknown direction: ${string.first()}") | |
} | |
} | |
fun parseSegmentList(firstPath: List<String>): List<Segment> { | |
var currentX = 0 | |
var currentY = 0 | |
var currentDistance = 0 | |
return firstPath | |
.map { | |
parseSegment(it, currentX, currentY, currentDistance).also { segment -> | |
when (segment.orientation) { | |
Orientation.HORIZONTAL -> currentX += segment.distanceVector | |
Orientation.VERTICAL -> currentY += segment.distanceVector | |
} | |
currentDistance += segment.distanceVector.absoluteValue | |
} | |
} | |
// .map { | |
// println("Segment: $it") | |
// it | |
// } | |
} | |
fun findIntersectionDistances(firstSegments: List<Segment>, secondSegments: List<Segment>): List<Int> { | |
return firstSegments | |
.map { firstSegment -> | |
secondSegments | |
.filter { it.orientation == firstSegment.orientation.opposite } | |
.filter { it.crossAxis != 0 || firstSegment.crossAxis != 0 } | |
.filter { | |
// println("(comparing: $firstSegment and $it)") | |
(it.crossAxis in firstSegment.range) && (firstSegment.crossAxis in it.range) | |
} | |
.map { | |
// println("Intersection: $firstSegment and $it") | |
// Manhattan distance | |
// firstSegment.crossAxis.absoluteValue + it.crossAxis.absoluteValue | |
// Wire length distance | |
firstSegment.cumulativeDistanceTo(it.crossAxis) + it.cumulativeDistanceTo(firstSegment.crossAxis) | |
} | |
} | |
.fold(emptyList()) { acc: List<Int>, distanceList: List<Int> -> acc + distanceList } | |
} | |
fun run(firstPath: List<String>, secondPath: List<String>): Int? { | |
val firstSegments = parseSegmentList(firstPath) | |
val secondSegments = parseSegmentList(secondPath) | |
return findIntersectionDistances(firstSegments, secondSegments).min() | |
} | |
testCases.forEachIndexed { index, (input, expectedResult) -> | |
println("${input.first} | ${input.second}") | |
println("${index + 1}: ${run(input.first, input.second)} (expected $expectedResult)") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment