fallshare

52582314?v=4

fallshare
: fallshare

About me

Nothing here yet. Update your profile at /profiles/fallshare.adoc

Day 00: groovy

Groovy

Here is another solution written in Groovy.

For the the time being I keep it simple and just call println.

Day 01: groovy

Day01

This solution is written in Groovy. It is the solution for the first day of AoC: The Tyranny of the Rocket Equation

First Star

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.

Second Star

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

Day 02: groovy

Day01

This is the solution for the second day of AoC: 1202 Program Alarm

Star 1

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]
Second Star

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

Day 03: groovy

Day02

This is the solution for the third day of AoC: Crossed Wires

First Star

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.

Caculating the matrix size and port location

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 :)

Second Star

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.

Day 04: groovy

Day04

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.

First Star

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.

Second Star

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.

Day 05: groovy

Day05

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

Star 1

I’m currently lacking the time to write a proper documentation. What I can say is that I implemented all the thoughts mentioned above.

Day 06: groovy

Day05

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.
Star 1

Got that one done. Using some recursion got the tricky part done.

Star 2

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.

Day 07: groovy

Day07

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.

Star 1

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.

code.groovy
[0,1,2,3,4].eachPermutation{ phaseSetting ->
    // do stuff
}
Star 2

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.

Day 08: groovy

Day08

This is the solution for the second day of AoC: Space Image Format

Star 1

Finally a more simpe challenge. Not much to say. Read the input. Split into layers. Count the zeros. And so on..

Star 2

Loops for the win.

Day 09: groovy

Day09

This is the solution for the second day of AoC: Sensor Boost

Star 1

Enhanced the computer according to spec.

Star 2

Nice. No extra work this time just a different input.

Day 10: groovy

Day10

This is the solution for the second day of AoC: Monitoring Station

Star 1

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

Star 2

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.

Day 11: groovy

Day10

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.

Day 13: groovy

this documentation is autogenerated. Add a README.adoc to your solution to take over the control of this :-)

groovy

input.txt
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
solution.groovy
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