fallshare
: fallshare
fallshare |
Here is another solution written in Groovy.
For the the time being I keep it simple and just call println.
This solution is written in Groovy. It is the solution for the first day of AoC: The Tyranny of the Rocket Equation
The calculation to get the required fuel per module is straight forward and done in calculateFuelForMass
.
I decided to iterate through the input list and calculate the total fuel on the fly with calculateTotalRequiredFuel
.
I have already wondered that it in part one negative fuel values are possible. But since the input file did not contain any numbers smaller then (1 + 2) * 3 = 9 I decided that this not a problem to get the task done…
I decided to recuryivley calculate the total mass of fuel that is required per module.
So calculateTotalRequiredFuelConsideringFuelMass
iterativley calls calculateFuelForMass
until the final result is available.
With calculateTotalRequiredFuelConsideringFuelMass
the required fuel for all modules is calculated with the update method.
There is quite some duplicated code between calculateTotalRequiredFuel
and calculateTotalRequiredFuelConsideringFuelMass
but I’m to lazy to clean this up now.
include::solution.groovy
This is the solution for the second day of AoC: 1202 Program Alarm
Once again a text file is being read. This time it is a comma separated list of integers. So the readFile methods returns an array of integers which represents our computer memory.
Integer[] readFile(String filePath) {
File file = new File(filePath)
String fileContent = file.text
contentArray = fileContent.tokenize(',')*.toInteger()
return contentArray
}
The whole computer operations part is implemented inside the processCode() function. It takes the computer’s memory (array of integers) as input and performs the operation according to the specification. This could also have been implemented as a class, but I was to lazy for that.
Integer processCode(code)
{
int finalOutput = 0;
for (i = 0; i < code.length; i += 4) {
int opcode = code[i]
int operand1 = code[code[i + 1]]
int operand2 = code[code[i + 2]]
int resultAdr = code[i + 3]
if ( opcode == 1 ) {
code[resultAdr] = operand1 + operand2
} else if (opcode == 2) {
code[resultAdr] = operand1 * operand2
} else if (opcode == 99) {
finalOutput = code[0]
break
} else {
throw new Exception("Invalid opcode found!")
}
}
return code[0]
}
Now the "code" which was read in must only be manipulated according to the requirements (substiuting the second and third integer) and then processCode() returns with the desired value.
Unresolved directive in ../../../../../../day02/groovy/fallshare/README.adoc - include::processor.groovy[tags=star1]
What a "lucky" coincidence ;) that processCode() takes the computer memory as input. So we can easily brutforce through all combinations of nouns and verbs (99 * 99) until the calculation returns with the right return value.
int finalCode, noun, verb
final int requiredResult = 19690720
for(noun = 0; noun <= 99; noun++){
for(verb = 0; verb <= 99; verb++){
code = readFile("input.txt")
code[1] = noun
code[2] = verb
finalCode = processCode(code)
if(finalCode == requiredResult)
break
}
if(finalCode == requiredResult)
break
}
println "Star 2:"
println "\tvalue ${finalCode} found with noun: ${noun} and verb: ${verb}"
println "\tresulting key is: " + noun + verb
This is the solution for the third day of AoC: Crossed Wires
So it is slowly gets interesting. I am having two ideas how to solve this riddle. I guess I’ll come back later to try out both variants. I first will write down some assumptions and ideas before I start coding. My first idea is it to create two matrices that mark all points that are part of the wires paths (0; no wire; 1:wire present) If I add both matrices the resulting matrix shall have the value two where the two wires overlap. I only have to find those points and calculate the Manhattan distance. BUT there are two details missing: - What is the location of the central port in my matrices? - What is the size of the matrices? Those questions must be answered first before I get started with the path calculation. So let’s get started.
As usual we a first reading in the input file. This time a list of string list will be returned. The first dimension defines which wire is selected, the second contains the instructions to draw the wires.
String[][] readFile(String filePath) {
File file = new File(filePath)
def lines = file.readLines()
def wire_instructions = [][]
wire_instructions[0] = lines[0].split(",")
wire_instructions[1] = lines[1].split(",")
return wire_instructions
}
// end::readFile
Integer[][] getMatrixDimensions(String[] intstructions)
{
int x = 0
int y = 0
x_list = []
y_list = []
intstructions.each{ instruction ->
operator = instruction[0]
value = instruction.substring(1).toInteger()
switch (operator) {
case "L":
x -= value
break
case "R":
x += value
break
case "U":
y += value
break
case "D":
y -= value
break
}
x_list << x
y_list << y
}
x_min = x_list.min()
x_max = x_list.max()
y_min = y_list.min()
y_max = y_list.max()
def dimensions = [][]
dimensions << [x_min, x_max]
dimensions << [y_min, y_max]
//i don't like to return an list of lists but it gets the job done for the time being
return dimensions
}
Integer[][] getMatrixMinMax(first, second){
minMaxMatrix = [[0,0],[0,0]]
for(i = 0; i < first[0].size(); i++){
minMaxMatrix[i][0] = (first[i][0] < second[i][0]) ? first[i][0] : second[i][0]
minMaxMatrix[i][1] = (first[i][1] > second[i][1]) ? first[i][1] : second[i][1]
}
return minMaxMatrix
}
Integer[][] createWirePath(intstructions, centralPort, matrixDimensions)
{
matrix = new Integer[matrixDimensions[0] + 1][matrixDimensions[1] + 1]
int x = centralPort[0]
int y = centralPort[1]
intstructions.each{ instruction ->
operator = instruction[0]
value = instruction.substring(1).toInteger()
switch (operator) {
case "L":
matrix = moveLeft(matrix, value, x, y)
x -= value
break
case "R":
matrix = moveRight(matrix, value, x, y)
x += value
break
case "U":
matrix = moveUp(matrix, value, x, y)
y += value
break
case "D":
matrix = moveDown(matrix, value, x, y)
y -= value
break
}
}
return matrix
}
Integer[][] moveRight(matrix, steps, x, y){
for(int i = 1; i <= steps; i++) {
matrix[x + i][y] = 1
}
return matrix
}
Integer[][] moveLeft(matrix, steps, x, y){
for(int i = 1; i <= steps; i++) {
matrix[x - i][y] = 1
}
return matrix
}
Integer[][] moveUp(matrix, steps, x, y){
for(int i = 1; i <= steps; i++) {
matrix[x][y + i] = 1
}
return matrix
}
Integer[][] moveDown(matrix, steps, x, y){
for(int i = 1; i <= steps; i++) {
matrix[x][y - i] = 1
}
return matrix
}
def getCrossings(matrix1, matrix2, matrixDimensions)
{
def intersections = []
for(int i = 0; i < matrixDimensions[0]; i++){
for(int j = 0; j < matrixDimensions[1]; j++){
if((matrix1[i][j] == 1 ) && (matrix1[i][j] == matrix2[i][j] ))
intersections << [i,j]
}
}
return intersections
}
Integer getSmallestDistance(crossings, centralPort){
min = 100000
minI = 0
for(int i = 0; i < crossings.size(); i++){
dist = calcManhattanDistance(crossings[i], centralPort)
if(dist < min){
min = dist
minI = i
}
}
println "Closest intersection is: ${crossings[i][0]} | ${crossings[i][1]}"
return min
}
Integer calcManhattanDistance(intersection, centralPort){
xDistance = Math.abs(intersection[0] - centralPort[0])
yDistance = Math.abs(intersection[1] - centralPort[1])
return xDistance + yDistance
}
wire_instructions = readFile("input.txt")
firstWireDimensions = getMatrixDimensions(wire_instructions[0])
secondWireDimensions = getMatrixDimensions(wire_instructions[1])
minMaxMatrix = getMatrixMinMax(firstWireDimensions, secondWireDimensions)
//By executin until here I know now that both on x and y axis the min values are negative
centralPort = [(-1 * minMaxMatrix[0][0]), (-1 * minMaxMatrix [1][0])]
matrixDimensions = [(-1 * minMaxMatrix[0][0]) + minMaxMatrix[0][1], (-1 * minMaxMatrix [1][0]) + minMaxMatrix[1][1]]
println "Matrix dimensions: ${matrixDimensions}"
println "location of central port: ${centralPort}"
firstWirePath = createWirePath(wire_instructions[0],centralPort, matrixDimensions)
secondWirePath = createWirePath(wire_instructions[1],centralPort, matrixDimensions)
crossings = getCrossings(firstWirePath, secondWirePath, matrixDimensions)
println "Smalles distance is: " + getSmallestDistance(crossings, centralPort)
println "End Star 1"
println "Star 2:"
println "Short total distance to intersection: " + getPointWithShortestTotalDistance(wire_instructions, crossings, centralPort)
def getPointWithShortestTotalDistance(wire_instructions, crossings, centralPort){
min = 10000000
minI = 0
for(int i = 0; i < crossings.size(); i++){
distWire1 = getDistanceToPoint(wire_instructions[0], crossings[i][0], crossings[i][1], centralPort)
distWire2 = getDistanceToPoint(wire_instructions[1], crossings[i][0], crossings[i][1], centralPort)
dist = distWire1 + distWire2
if(dist < min){
min = dist
minI = i
}
}
println "Closest intersection with the smalles distance: ${crossings[i][0]} | ${crossings[i][1]}"
return min
}
Integer getDistanceToPoint(instructions, xInter, yInter, centralPort)
{
int x = centralPort[0]
int y = centralPort[1]
int totalDist = 0
for(int i = 0; i < instructions.size(); i++){
instruction = instructions[i]
operator = instruction[0]
value = instruction.substring(1).toInteger()
switch (operator) {
case "L":
for(int j = 1; j <= value; j++){
x--
if((xInter == x)&&(yInter == y)){
return totalDist + j
}
}
break
case "R":
for(int j = 1; j <= value; j++){
x++
if((xInter == x)&&(yInter == y)){
return totalDist + j
}
}
break
case "U":
for(int j = 1; j <= value; j++){
y++
if((xInter == x)&&(yInter == y)){
return totalDist + j
}
}
break
case "D":
for(int j = 1; j <= value; j++){
y--
if((xInter == x)&&(yInter == y)){
return totalDist + j
}
}
break
}
totalDist += value
}
return totalDist
}
Both lines start at the central port. We assume that this is the origin of our coordinate sytem for the time being. We need to calculate the absolute locations of the wire by adding the wire instructions. The resulting coordinates are stored as tuples in a list:
Integer[][] getMatrixDimensions(String[] intstructions)
{
int x = 0
int y = 0
x_list = []
y_list = []
intstructions.each{ instruction ->
operator = instruction[0]
value = instruction.substring(1).toInteger()
switch (operator) {
case "L":
x -= value
break
case "R":
x += value
break
case "U":
y += value
break
case "D":
y -= value
break
}
x_list << x
y_list << y
}
x_min = x_list.min()
x_max = x_list.max()
y_min = y_list.min()
y_max = y_list.max()
def dimensions = [][]
dimensions << [x_min, x_max]
dimensions << [y_min, y_max]
//i don't like to return an list of lists but it gets the job done for the time being
return dimensions
}
Once we are done with calculating the whole wire path we can find the smalles and biggest value of the x and y axis with the getMatrixMinMax() method. This gives us the total dimension of the coordiante system.
With this informtaion we can create two matrices (two dimensional arrays) and store the wire paths in themby using the createWirePath() method.
Once this is done the two matrices can be compared so that we get all points that overlap (= crossings)
def getCrossings(matrix1, matrix2, matrixDimensions)
{
def intersections = []
for(int i = 0; i < matrixDimensions[0]; i++){
for(int j = 0; j < matrixDimensions[1]; j++){
if((matrix1[i][j] == 1 ) && (matrix1[i][j] == matrix2[i][j] ))
intersections << [i,j]
}
}
return intersections
}
Now we can caculate the Manhattan distance for all retrieved points and then can get the point with the smalles distance. And we are done :)
If I knew what the star 2 challenge would be then my star 1 solution would look differnt. I lost my patience a litle bit and just hacked down the rest of the challenge. I take the list of found crossings and then I iterate through the wire instructions until this point is reached. By adding the distance and finding the smalles total distance the star 2 challenge is done.
This is the solution for the third day of AoC: Secure Container
I guess this challenge can be solved by applying some stochastic theory but I didn’t pay that much attention to it in school. So I guess I have to use brutforce to get the solution.
I’m iterating throw all the possible combinations in a for loop. In each iteration I split the current number into an array of digits. Then I interativle check if the digits fullfill the specified criteria. If this is the case the total number of valid combinations is incremented and we continue with the next combination.
The solution for start 2 is using the same approach then star 1. But this time the criteria for a valid combination is sligthly different. I’m using a list to collect twin digit pairs. If a digit appears more then twice in a row then the digit is removed from that list and added to a list that collects digits ocurring more then twince in a row. A number is only valid when the digit twin list is not empty and all other critiera are fulfilled.
This is the solution for the second day of AoC: Sunny with a Chance of Asteroids
I use this readme to collect all the thoughts and ideas I’m having for the challenge. This is a loose connection of all the thoughts I’m having. I need: * a program or instruction counter, that is incremented after the instruction is finished * a functionn that reads the next opcode and the parameters that belong to it * a way how to resolve the parameter mode
I’m currently lacking the time to write a proper documentation. What I can say is that I implemented all the thoughts mentioned above.
This is the solution for the second day of AoC: Universal Orbit Map
Yeah finally a graph. Here is my plan for today: In phase 1 I focus on creating a object structure that reprents my graph. Every object is unique and itentified by its name. I introduce a UniverseCreator class that keeps track of all space objects. If a required space object is not existing yet it will be created. Afterwards the objects will be linked.
In phase 2 I will try to extract the required information from the graph.
Got that one done. Using some recursion got the tricky part done.
Got that one done too. Here the trick was to find the common orbit and calculate the distance from santa and me to the orbit and sum up the distances.
This is the solution for the second day of AoC: Amplification Circuit
Solving all the challenges is more time consuming than I expected. Hence I have to keep the docu part short.
I started to take my code from day 5 and turn it into a Computer class.
Then I added further functionality like waiting for input and providing output.
Once the class was having all required features I started to create 5 instances of it.
One for each amplifier. My connecting the in- and outouts I was able to create the amplifier chain as requried.
Luckily groovy has the eachPermutation
method that allows to perumtate an array and to execute code for every permutation.
With every iteration a simple compare checks if the output is a new max output.
[0,1,2,3,4].eachPermutation{ phaseSetting ->
// do stuff
}
For star 2 some change in my Computer class code was required.
The Computer has now a isActive
method that indicates if the program already reached the program stop opcode.
In addition I ran into an bug. I always read in 3 parameters for an operation indepent of the actually required amount for the opcode.
This resulted into an array out of bound errors.
I fixed it by only reading as many paramters as required.
For the calculations the eachPermutation
method is used again.
In addition the amplifiers are running inside a while loop that only steps when the last amplifiert program stops.
This is the solution for the second day of AoC: Space Image Format
Finally a more simpe challenge. Not much to say. Read the input. Split into layers. Count the zeros. And so on..
This is the solution for the second day of AoC: Sensor Boost
Enhanced the computer according to spec.
This is the solution for the second day of AoC: Monitoring Station
Wow this was a though one. I had some idea in mind how to solve the riddle. I came up with my own algorithm to scan the space.. Which didn’t work. Then I rewrote my implementation to just remember parts that have already been scanned. I was able to figure out Star 1 with that. See solution_attempt1.groovy
Then Star 2 came and I had to learn that my scan approach does not scan the astroids in the order as required for star 2. I doubled checked and Star 1 did not mention that the beam/scan was happening in a circular motion. I wanted to avoid any angle calculation and stuff hence I came up with the first solution. Thanks to an tip I realized that I somehow had to use the angle or gradient in order to scan in the right order for part 2. It turned out that the second solution (solution.groovy) is a lot simpler compared to my first overcomplicated attempt.
This is the solution for the second day of AoC: Space Police
Not much to say. Create a new class for the robot and do what you are told to do.
this documentation is autogenerated. Add a README.adoc
to your solution to take over the control of this :-)
2,380,379,385,1008,2709,828459,381,1005,381,12,99,109,2710,1102,1,0,383,1102,1,0,382,20101,0,382,1,21002,383,1,2,21102,1,37,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,45,381,1005,381,22,1001,383,1,383,1007,383,23,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1106,0,161,107,1,392,381,1006,381,161,1102,1,-1,384,1106,0,119,1007,392,43,381,1006,381,161,1101,0,1,384,20102,1,392,1,21102,1,21,2,21101,0,0,3,21102,138,1,0,1106,0,549,1,392,384,392,20101,0,392,1,21102,1,21,2,21102,3,1,3,21102,1,161,0,1105,1,549,1102,1,0,384,20001,388,390,1,21002,389,1,2,21102,180,1,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,21001,389,0,2,21101,205,0,0,1105,1,393,1002,390,-1,390,1101,0,1,384,20101,0,388,1,20001,389,391,2,21101,228,0,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,21001,388,0,1,20001,389,391,2,21101,253,0,0,1105,1,393,1002,391,-1,391,1102,1,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,0,279,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1105,1,393,1002,390,-1,390,1002,391,-1,391,1102,1,1,384,1005,384,161,21002,388,1,1,21001,389,0,2,21101,0,0,3,21101,0,338,0,1105,1,549,1,388,390,388,1,389,391,389,20102,1,388,1,20102,1,389,2,21101,4,0,3,21101,365,0,0,1105,1,549,1007,389,22,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,329,20,18,1,1,22,109,3,21202,-2,1,1,21202,-1,1,2,21101,0,0,3,21102,414,1,0,1105,1,549,21202,-2,1,1,22101,0,-1,2,21101,429,0,0,1105,1,601,1202,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2105,1,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22102,1,-3,-7,109,-8,2105,1,0,109,4,1202,-2,45,566,201,-3,566,566,101,639,566,566,2102,1,-1,0,204,-3,204,-2,204,-1,109,-4,2106,0,0,109,3,1202,-1,45,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2105,1,0,109,3,22102,23,-2,1,22201,1,-1,1,21102,1,521,2,21102,1,730,3,21102,1,1035,4,21101,0,630,0,1105,1,456,21201,1,1674,-2,109,-3,2106,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,2,0,0,0,0,2,2,2,2,0,2,2,2,2,2,0,2,0,0,2,2,0,2,0,0,0,2,2,2,2,0,2,2,2,0,0,2,2,2,0,0,1,1,0,0,0,2,0,2,2,0,0,0,2,2,0,2,2,0,0,2,0,0,0,2,0,2,2,0,0,2,0,0,0,2,0,0,0,2,0,2,0,0,0,2,0,1,1,0,2,2,2,0,2,2,2,2,0,0,2,0,2,2,0,0,2,0,0,2,0,2,2,2,2,0,2,0,2,0,0,2,2,2,0,0,2,0,0,0,2,0,1,1,0,2,0,2,0,2,2,0,0,0,0,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,0,0,2,0,0,2,0,1,1,0,0,2,0,2,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,0,0,2,2,0,2,0,0,0,2,2,2,2,0,2,0,2,0,0,2,0,0,1,1,0,2,2,0,2,2,0,2,2,0,0,0,2,2,2,0,2,0,0,2,2,0,2,0,2,2,0,2,2,0,2,0,2,2,2,2,0,0,0,2,2,0,0,1,1,0,2,2,0,2,0,0,2,2,0,0,2,0,0,2,2,0,0,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,0,0,0,2,0,0,2,2,2,0,1,1,0,2,2,2,0,0,0,0,2,0,0,0,2,2,2,0,0,2,2,0,0,0,0,0,2,2,0,2,2,0,2,0,2,2,0,2,0,2,2,0,0,0,0,1,1,0,0,2,0,2,0,2,0,0,0,0,2,0,0,2,0,2,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,0,2,2,0,2,0,2,2,2,0,0,1,1,0,2,2,0,0,0,2,2,0,2,2,0,0,0,2,2,2,2,0,0,0,2,2,2,0,0,0,0,2,2,2,2,2,0,0,2,2,0,2,2,2,2,0,1,1,0,2,0,0,2,2,2,0,0,2,0,2,0,2,0,2,2,0,2,0,2,0,2,2,2,2,2,2,2,0,2,0,0,2,0,2,0,2,2,2,2,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2,0,0,2,2,0,2,2,2,0,2,2,0,0,2,0,2,0,2,0,0,1,1,0,2,0,2,2,0,2,2,0,0,2,0,0,0,2,0,0,2,2,0,2,0,2,0,0,2,2,0,2,0,2,0,2,2,2,0,0,2,0,2,2,2,0,1,1,0,2,0,2,2,0,2,2,2,0,0,2,0,0,2,2,2,2,2,0,0,2,2,0,2,2,2,0,0,0,2,2,2,2,2,0,2,0,2,2,2,0,0,1,1,0,0,0,0,0,2,2,0,2,2,0,2,0,2,2,2,0,0,2,0,2,0,0,2,0,2,2,0,2,2,2,2,0,0,0,2,2,2,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,19,57,3,10,63,4,73,55,28,50,19,46,18,78,18,9,25,36,40,29,86,84,2,46,1,16,66,12,94,19,6,76,86,17,18,59,9,53,19,74,29,61,89,19,50,4,10,57,89,29,42,27,11,29,9,76,86,3,53,87,20,16,58,5,11,53,93,72,15,84,7,49,91,43,44,75,37,91,73,10,86,46,97,7,79,5,55,40,10,93,57,50,32,6,82,4,35,25,86,81,18,63,26,70,47,87,44,55,74,1,92,18,87,15,93,75,31,51,70,48,9,54,86,41,39,76,76,69,27,25,24,82,26,77,3,46,90,81,53,92,10,87,82,22,72,60,57,58,20,20,68,50,36,49,62,45,98,65,25,51,71,43,63,50,48,85,70,37,27,60,75,8,48,73,68,52,1,66,58,49,40,50,10,34,40,29,75,57,21,55,43,19,21,49,32,77,87,50,23,58,25,66,46,37,60,59,15,40,80,23,32,89,96,80,31,48,73,48,69,42,71,47,60,52,93,67,84,2,70,9,75,53,78,59,43,21,17,32,24,10,38,39,76,2,54,78,18,42,64,63,3,75,3,55,34,92,48,89,65,61,20,94,64,48,85,93,50,62,10,31,48,29,43,89,52,82,42,36,1,92,12,78,53,88,22,93,86,62,53,46,69,2,7,71,13,18,29,9,9,8,19,49,79,32,9,59,32,84,6,84,7,27,89,7,84,56,62,5,75,33,64,19,97,23,77,13,14,19,36,93,10,36,20,25,2,98,20,49,25,97,70,32,7,24,41,49,26,61,42,47,3,50,13,69,87,73,85,39,85,82,91,95,37,53,63,47,25,4,66,43,41,7,43,48,7,9,89,64,67,6,38,76,84,48,22,31,23,32,28,76,1,21,49,88,47,75,79,45,75,21,93,38,25,53,86,13,22,64,35,77,98,48,44,88,65,37,93,30,86,93,65,67,86,69,87,2,16,83,21,44,12,2,42,90,95,81,58,76,8,61,42,77,58,57,12,18,3,14,43,97,81,57,16,80,65,42,43,16,71,46,31,40,31,91,12,5,10,97,79,54,35,51,80,1,4,39,47,30,67,96,10,34,51,90,81,17,2,45,8,64,58,12,82,45,18,69,22,14,38,94,28,97,5,47,53,51,67,38,59,20,61,49,65,83,31,62,23,83,48,41,61,75,18,67,37,82,15,74,43,88,25,98,73,28,88,53,8,6,41,94,8,65,34,12,40,1,23,46,36,83,96,44,70,71,39,59,82,83,51,53,9,25,84,68,3,78,2,16,98,6,46,54,68,97,83,88,92,7,82,73,59,68,24,93,19,19,37,87,1,42,50,41,12,88,43,16,1,88,50,84,13,80,28,4,47,62,72,98,97,73,45,67,53,6,65,90,31,71,94,15,21,20,81,23,57,62,75,16,19,4,43,63,41,98,9,50,23,11,78,11,70,22,82,97,70,58,94,77,77,71,21,86,57,67,76,33,3,43,39,37,88,68,14,91,95,7,46,42,35,44,52,61,52,91,47,38,50,94,92,32,33,59,18,15,30,10,85,90,39,6,2,40,66,51,16,47,56,95,98,49,60,69,53,61,55,59,11,98,75,78,45,18,96,82,85,58,57,49,2,48,34,30,50,63,14,52,65,85,50,53,31,74,17,98,57,74,77,85,68,92,53,54,48,42,35,52,17,93,43,9,5,90,33,16,60,72,62,66,81,40,91,14,83,4,96,50,4,56,12,14,93,95,38,38,49,94,18,22,69,44,71,18,88,38,20,55,78,53,83,3,73,25,2,64,24,63,25,18,47,2,97,88,64,29,58,93,35,36,61,64,6,5,52,75,18,2,89,68,38,22,42,19,34,32,58,81,60,98,8,67,5,51,59,98,88,70,46,33,82,88,27,41,85,44,40,90,4,41,36,32,5,91,20,4,41,62,16,16,36,50,92,93,94,88,16,30,94,70,8,13,26,35,80,98,34,6,98,92,85,1,9,31,40,10,38,87,61,11,89,69,26,1,11,29,71,6,34,11,95,45,14,42,44,9,40,22,95,75,17,18,13,95,60,93,74,53,93,71,54,68,8,51,16,18,53,62,87,32,18,42,74,38,54,82,89,61,28,47,29,68,83,63,65,11,1,4,42,85,61,70,90,12,80,84,5,58,7,88,70,93,64,92,4,21,80,80,92,63,53,47,11,38,91,80,38,13,81,23,25,16,66,96,50,37,73,80,87,50,84,48,27,69,86,52,86,36,98,21,92,94,91,30,68,56,8,45,31,6,57,6,51,88,77,77,50,21,81,22,79,95,60,42,54,65,65,97,15,15,91,32,59,25,46,93,25,828459
class Computer {
Boolean isActive
BigInteger[] code
def input
BigInteger[] output
int ip;
int rb;
//this map stores how many paramter a certrain operator has
def numberOfParameters = [
1 : 3,
2 : 3,
3 : 1,
4 : 1,
5 : 2,
6 : 2,
7 : 3,
8 : 3,
9 : 1
]
Computer(String filePath){
isActive = true
input = []
output = []
code = readFile(filePath)
def iniSize = code.size()
code += new BigInteger[100000]
//initalize rest of code with 0, didn't find a better way yet
for(int i = iniSize; i < iniSize + 100000; i++){
code[i] = 0
}
ip = 0;
rb = 0;
}
Boolean isActive(){
this.isActive
}
Integer processInput(Integer input){
this.input += input
return this.processCode()
}
void addInput(Integer input){
this.input += input
}
// tag::readFile[]
BigInteger[] readFile(String filePath) {
File file = new File(filePath)
String fileContent = file.text
def contentArray = fileContent.tokenize(',')*.toBigInteger()
return contentArray
}
// end::readFile[]
Integer[] splitNumberInDigits(int number){
def numberOfDigits = String.valueOf(number).length()
def digits = new Integer[numberOfDigits]
def intermediate = number
for(int j = (numberOfDigits - 1); j >= 0; j--){
def curDigit = intermediate % 10
intermediate = (intermediate / 10).trunc().intValue()
digits[j] = curDigit
}
return digits
}
//takes an instruciton and returns the opcde that it contains
Integer getOpcode(int[] instruction){
int opcode = instruction[instruction.size() - 1]
if(instruction.size() > 1)
{
opcode += (10 * instruction[instruction.size() - 2])
}
return opcode
}
Integer[] getParameterModes(int[] instruction){
int[] parameterModes = [0,0,0]
int parameterCounter = instruction.size() - 2
if(parameterCounter > 3){
throw new Exception("Invalid number of parameter modes found")
}
int i = 0
while(i < parameterCounter){
parameterModes[i] = instruction[(instruction.size() - 1 - 2) - i]
i++
}
return parameterModes
}
// tag::processor[]
BigInteger[] processCode()
{
output = []
//TODO turn into while loop
while (ip < code.length) {
def instruction = splitNumberInDigits(code[ip])
int opcode = getOpcode(instruction)
println opcode
//if we reach the end of the program we stop instead of reading possible parameters
if (opcode == 99) {
println "End of program"
isActive = false
break
}
int[] paraModes = getParameterModes(instruction)
int[] operands = [0,0,0]
//currently the operator and the information how many parameter it has is decoupled (defined in the beginning of this class)
//a OO desgin would help here to keep information together.
//due to time reason I keep things as they are right now.
for(int i = 0; i <= (numberOfParameters[opcode] - 1); i++){
if(paraModes[i] == 0){
//position mode
operands[i] = code[ip + (i + 1)]
}else if(paraModes[i] == 1){
//immediate mode
operands[i] = ip + (i + 1)
}else if(paraModes[i] == 2){
//relative base mode
operands[i] = code[ip + (i + 1)] + rb
println "relative mode: ${ip + (i + 1) + rb} - $ip + ($i + 1) + $rb"
} else {
throw new Exception("Invalid number of parameter mode values found")
}
}
if ( opcode == 1 ) {
// sum
println "[${operands[2]}] = [${operands[0]}]: ${code[operands[0]]} + [${operands[1]}]: ${code[operands[1]]}"
code[operands[2]] = code[operands[0]] + code[operands[1]]
ip += 4
} else if (opcode == 2) {
//multiply
println "[${operands[2]}] = [${operands[0]}]: ${code[operands[0]]} * [${operands[1]}]: ${code[operands[1]]}"
code[operands[2]] = code[operands[0]] * code[operands[1]]
ip += 4
} else if (opcode == 3) {
//read value
println "input: " + input
if(input.isEmpty()){
println "Waiting for input"
break
} else {
code[operands[0]] = input.remove(0)
println "[${operands[0]}] << " + code[operands[0]]
ip += 2
}
} else if (opcode == 4) {
//output value
println "[${operands[0]}] >> " + code[operands[0]] + " >> " + code[operands[0]]
ip += 2
output += code[operands[0]]
} else if (opcode == 5) {
//jump if true
println "jump to [${code[operands[1]]}] if [${operands[0]}]:${code[operands[0]]} == 1"
if(code[operands[0]] != 0){
ip = code[operands[1]]
} else {
ip += 3
}
} else if (opcode == 6) {
//jump if false
println "jump to [${code[operands[1]]}] if [${operands[0]}]:${code[operands[0]]} == 0"
if(code[operands[0]] == 0){
ip = code[operands[1]]
} else {
ip += 3
}
} else if (opcode == 7) {
// less than
println "[${code[operands[2]]}] is 1 if [${operands[0]}]:${code[operands[0]]} < [${operands[1]}]:${code[operands[1]]} else 0"
if(code[operands[0]] < code[operands[1]]){
code[operands[2]] = 1
} else {
code[operands[2]] = 0
}
ip += 4
} else if (opcode == 8) {
//equals
println "[${code[operands[2]]}] is 1 if [${operands[0]}]:${code[operands[0]]} == [${operands[1]}]:${code[operands[1]]} else 0"
if(code[operands[0]] == code[operands[1]]){
code[operands[2]] = 1
} else {
code[operands[2]] = 0
}
ip += 4
} else if (opcode == 9) {
//set relative base
println "RB = ${code[operands[0]]}"
this.rb += code[operands[0]]
ip += 2
} else {
println "Opcode: ${opcode} - ip: ${ip}"
throw new Exception("Invalid opcode found!")
}
}
return output
}
// end::processor[]
}
computer = new Computer("input.txt")
map = computer.processCode()
println map
int blocktile = 0
for(int i = 2; i < map.size(); i += 3){
if(map[i] == 2){
blocktile++
}
}
println "Blocktiles found: " + blocktile