nils-braun

6116188?v=4

nils-braun
: nils-braun

About me

Nothing here yet. Update your profile at /profiles/nils-braun.adoc

Day 00: c++

I will try to solve the problems in C++ this year. Lets see how far I can get :-)

Hello World

include::hello-world.cpp

Day 01: c++

Solution for Day 01 of the AoC 2019: Day 1: The Tyranny of the Rocket Equation

Solution

The first star of the challenge is a straight-forward calculation following the exercise description.

The second part uses an iterative approach to calculate the additional fuel costs of the fuel itself. This is not the prettiest solution, but it works :-)

include::solution.cpp

Day 02: c++

Solution for Day 02 of the AoC 2019: Day 2: 1202 Program Alarm

Solution

I solved it with a rather brute-force ansatz - probably one can also solve it better but it just worked.

Array computation is quite simple in C++, I though about using iterators but in principle it makes no difference (std::vector iterators are also just index numbers) for me in this case.

I forgot about the std::getline function, which is quite handy in this context.

include::solution.cpp

Day 03: c++

Solution for Day 03 of the AoC 2019: Day 3: Crossed Wires

Solution

Things get a bit more complicated now (and to be honest, I think I over-engineered this time).

I build a class for a visited point including the x and y position as a std::pair and the travelled distance as a private member with some helper functions.

include::Point.h

Hint: add print functions to make your code debug-able.

I also built a class for the wire line, which can be constructed out of a string. After some string magic (split by comma, convert to direction and length), I store a set of visited points by stepping through all points the wire has visited. The important key here is, that I use a sorting function only respecting x and y (not the distance), so points with the same x/y are only stored once in the set. As we advance from beginning to end, we only store the first occurrence of every point.

Not very readable - but I basically wanted to use some nice comparator functions :-)

include::WirePath.h

What is missing is now only the possibility to built the intersection of those two sets. In principle there are C++ functions for that, but I wanted to have both the left and the right point (for the second star), so I needed to re-code the intersection function using some iterator magic (it is however not so hard). Then I convert to either the manhatten distance or the sum of travelled distances, build the min and print.

include::solution.cpp

Attention: this time you need to built with

g++ solution.cpp -std=c++17 -I. -o solution

Day 04: c++

Solution for Day 04 of the AoC 2019: Day 4: Secure Container

Solution

I have chosen a pretty straight-forward solution, which is fine as C++ is quite good at just doing loops and stuff.

I represent the number as a list of digits and count each digit from <0 or last highest> to 9. Then I check the two star requirements via "histogramming" over the digits.

There is tons of improvement possible. One could cache the histogrammed digits and just increase by one when I add another digit. Also, I do not need to do the two quizzes separately.

include::solution.cpp

Day 05: c++

Solution for Day 05 of the AoC 2019: Day 5: Sunny with a Chance of Astroids

Solution

This time I refactored my solution for day 02 a bit - which was a good decision. I created a Memory class which stores the current instruction pointer and added helper functions to get the next parameter depending on the instruction pointer and the current value of the parameter mode (for which I have also created a small helper class).

With these classes, the implementation was rather straight forward.

As a further TODO, one could template the parameter function to always get all 1 or 2 parameters as a parameter pack, which would make the code a bit more readable.

include::solution.cpp

Day 06: c++

Solution for Day 06 of the AoC 2019: Day 6: Universal Orbit Map

Solution

Typical graph-problem, which I solved with typical graph methods :-) While reading in, I built a map of "orbited → orbiting children" and a map "orbiting → orbited parent" (note that the second one is un-ambiguous).

The next step is the important one: for each graph node, I calculate what I called the "automaton cell number". This is the number of steps needed to travel from this node to the root element (COM). It can be calculated easily with a recursive algorithm, by starting from COM and counting up with every recursion step.

With this number, the first star is straight forward: just sum up all of those automaton cell numbers. Think of it this way: if you need N steps from this node to COM, you have 1 direct relation and N - 1 indirect ones. So by summing up all of those numbers you end up with the total number of relations.

The second star can be solved using this number also: first you need to find the node where SAN and YOU are meeting. This can be done by traversing the full path from e.g. YOU to COM and checking, which node is also in the path from SAN to COM. Now you just need to calculate the differences between SAM and the common node and YOU and the common node - which gives you the number of steps needed to travel.

include::solution.cpp

Day 07: c++

Solution for Day 07 of the AoC 2019: Day 7: Amplification Circuit

Solution

I reused solution of day 05 (of course), just did some small changes (fortunately it was already refactored): * if an input is requested, and there is no input, break out of the parsing loop (and go back one step to digest the input instruction again the next time) * add a bool to break out the parsing loop in every output

include::IntMachine.cpp

Then, the implementation was quite simple. Very useful was the std::next_permutation function.

include::solution.cpp

Day 08: c++

Solution for Day 08 of the AoC 2019: Day 8: Space Image Format

Solution

Some straight-forward array operations - I would say there is nothing really special here. The Image and Layer classes:

include::Image.h

And the final solution:

include::solution.cpp

Only thing I really had problems with, is that I mixed x and y in the beginning and the image really looks strange then…​

Day 09: c++

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

c++

input.txt
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,30,1016,1101,37,0,1005,1101,362,0,1023,1101,0,20,1014,1101,39,0,1013,1102,34,1,1007,1101,682,0,1027,1102,664,1,1025,1102,1,655,1028,1101,0,26,1002,1102,1,38,1015,1101,669,0,1024,1101,0,28,1017,1102,1,21,1000,1101,0,27,1012,1102,1,29,1008,1102,1,23,1019,1101,0,24,1011,1101,685,0,1026,1102,646,1,1029,1102,1,369,1022,1101,0,31,1003,1102,1,36,1001,1101,0,0,1020,1102,1,35,1009,1101,32,0,1010,1101,0,1,1021,1102,33,1,1004,1101,22,0,1006,1102,1,25,1018,109,14,1205,6,197,1001,64,1,64,1105,1,199,4,187,1002,64,2,64,109,-4,21107,40,39,9,1005,1019,219,1001,64,1,64,1105,1,221,4,205,1002,64,2,64,109,9,1206,1,239,4,227,1001,64,1,64,1106,0,239,1002,64,2,64,109,-9,2101,0,-8,63,1008,63,26,63,1005,63,261,4,245,1106,0,265,1001,64,1,64,1002,64,2,64,109,-6,2108,37,1,63,1005,63,287,4,271,1001,64,1,64,1105,1,287,1002,64,2,64,109,15,21108,41,44,-2,1005,1017,307,1001,64,1,64,1106,0,309,4,293,1002,64,2,64,109,-16,1207,1,34,63,1005,63,327,4,315,1105,1,331,1001,64,1,64,1002,64,2,64,109,8,1208,-9,29,63,1005,63,347,1106,0,353,4,337,1001,64,1,64,1002,64,2,64,109,4,2105,1,8,1001,64,1,64,1105,1,371,4,359,1002,64,2,64,109,-22,1201,9,0,63,1008,63,27,63,1005,63,391,1106,0,397,4,377,1001,64,1,64,1002,64,2,64,109,18,21107,42,43,5,1005,1016,415,4,403,1106,0,419,1001,64,1,64,1002,64,2,64,109,-8,1201,2,0,63,1008,63,37,63,1005,63,441,4,425,1105,1,445,1001,64,1,64,1002,64,2,64,109,27,1205,-9,463,4,451,1001,64,1,64,1106,0,463,1002,64,2,64,109,-1,1206,-8,475,1105,1,481,4,469,1001,64,1,64,1002,64,2,64,109,-6,21101,43,0,-8,1008,1015,43,63,1005,63,507,4,487,1001,64,1,64,1106,0,507,1002,64,2,64,109,-15,2101,0,-3,63,1008,63,35,63,1005,63,531,1001,64,1,64,1106,0,533,4,513,1002,64,2,64,109,-2,2102,1,-6,63,1008,63,18,63,1005,63,553,1105,1,559,4,539,1001,64,1,64,1002,64,2,64,109,7,21102,44,1,3,1008,1016,44,63,1005,63,581,4,565,1105,1,585,1001,64,1,64,1002,64,2,64,109,-11,1202,7,1,63,1008,63,34,63,1005,63,609,1001,64,1,64,1105,1,611,4,591,1002,64,2,64,109,6,1202,1,1,63,1008,63,35,63,1005,63,637,4,617,1001,64,1,64,1106,0,637,1002,64,2,64,109,16,2106,0,4,4,643,1001,64,1,64,1106,0,655,1002,64,2,64,109,-1,2105,1,1,4,661,1106,0,673,1001,64,1,64,1002,64,2,64,109,5,2106,0,-1,1105,1,691,4,679,1001,64,1,64,1002,64,2,64,109,-24,1208,-2,26,63,1005,63,709,4,697,1105,1,713,1001,64,1,64,1002,64,2,64,109,-10,2102,1,6,63,1008,63,21,63,1005,63,735,4,719,1105,1,739,1001,64,1,64,1002,64,2,64,109,25,21108,45,45,-9,1005,1010,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,-12,1207,-7,20,63,1005,63,777,1106,0,783,4,767,1001,64,1,64,1002,64,2,64,109,-13,2108,22,6,63,1005,63,799,1106,0,805,4,789,1001,64,1,64,1002,64,2,64,109,17,21102,46,1,0,1008,1011,45,63,1005,63,825,1105,1,831,4,811,1001,64,1,64,1002,64,2,64,109,-6,2107,21,1,63,1005,63,849,4,837,1105,1,853,1001,64,1,64,1002,64,2,64,109,-3,2107,27,0,63,1005,63,873,1001,64,1,64,1105,1,875,4,859,1002,64,2,64,109,12,21101,47,0,0,1008,1014,48,63,1005,63,899,1001,64,1,64,1105,1,901,4,881,4,64,99,21102,27,1,1,21101,0,915,0,1105,1,922,21201,1,42931,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1106,0,922,22201,1,-1,-2,1106,0,968,22101,0,-2,-2,109,-3,2106,0,0
IntMachine.h
// Solution for day05: 1202 Program Alarm
#include <fstream>
#include <iostream>
#include <assert.h>
#include <vector>
#include <tuple>
#include <sstream>

class Memory {
private:
    using MemoryCell = long long int;

    enum class ParameterMode {
        positionalMode = 0,
        immediateMode = 1,
        relativeMode = 2
    };

    class ParameterModes {
    public:
        ParameterModes(unsigned int parameterModes) : m_intValue(parameterModes) {}

        ParameterMode getNextMode() {
            // Grab the next parameter mode and delete it from the list of parameter modes
            const auto parameterMode = m_intValue % 10;
            m_intValue /= 10;

            return static_cast<ParameterMode>(parameterMode);
        }

    private:
        unsigned int m_intValue = 0;
    };

public:
    /// Split the input by comma
    static Memory readIn() {
        Memory result;

        std::ifstream inputFile("input.txt");
        std::string intCodeAsString;

        while(std::getline(inputFile, intCodeAsString, ',')) {
            const auto intCode = std::atoll(intCodeAsString.c_str());
            result.m_memory.push_back(intCode);
        }

        return result;
    }

    std::vector<MemoryCell> run(std::vector<MemoryCell>&& input, bool stopOnOutput = false) {
        m_input.swap(input);
        m_output.clear();

        while(hasNextInstruction()) {
            const auto instruction = getNextInstruction();
            const unsigned int opCode = instruction % 100;
            ParameterModes parameterModes(instruction / 100);

            if(not apply(opCode, parameterModes, stopOnOutput)) {
                break;
            }
        }

        return m_output;
    }

private:
    /// The memory content
    std::vector<MemoryCell> m_memory;

    /// The address of the current instruction
    MemoryCell m_ic = 0;

    /// The relative base address
    MemoryCell m_relativeBase = 0;

    /// The input vector
    std::vector<MemoryCell> m_input;

    /// The output vector
    std::vector<MemoryCell> m_output;

    /// Apply the operation given by the opcode and the parameter modes
    bool apply(unsigned int opCode, ParameterModes parameterModes, bool stopOnOutput) {
        if(opCode == 1) {
            // addition
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam + secondParam);
        } else if (opCode == 2) {
            // multiply
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam * secondParam);
        } else if (opCode == 3) {
            // read input from internal vector
            // TODO: reversed!!!
            if(m_input.empty()) {
                // Nothing to digest!
                // more one step back, so the next time we can continue here
                m_ic--;
                return false;
            }
            const auto input = m_input.back();
            m_input.pop_back();
            setAtNextParameter(parameterModes, input);
        } else if (opCode == 4) {
            // write output to internal vector
            const auto param = getNextParameter(parameterModes);
            m_output.push_back(param);
            if(stopOnOutput) {
                return false;
            }
        } else if(opCode == 5) {
            // jump if true
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam != 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 6) {
            // jump if false
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam == 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 7) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam < secondParam);
        } else if(opCode == 8) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam == secondParam);
        } else if(opCode == 9) {
            // adjust relative base
            const auto param = getNextParameter(parameterModes);
            m_relativeBase += param;
        } else if (opCode == 99) {
            return false;
        } else {
            throw std::exception();
        }

        return true;
    }

    /**
     * Helper function to read the parameter value given by the parameter.
     *
     * If the next parameterMode (the least-significant digit) is 1, use the parameter directly.
     * If the parameterMode is 0, interpret the parameter as an address in memory.
     */
    MemoryCell readNumber(ParameterMode parameterMode, MemoryCell parameterOrAddress) {
        if(parameterMode == ParameterMode::immediateMode) {
            return parameterOrAddress;
        } else if(parameterMode == ParameterMode::positionalMode) {
            // We use .at() instead of [] to have boundary checks
            return get(parameterOrAddress);
        } else if(parameterMode == ParameterMode::relativeMode) {
            return get(parameterOrAddress + m_relativeBase);
        }
    }

    /// Write at the given address. This can not be immediate mode!
    void writeNumber(ParameterMode parameterMode, MemoryCell parameterAddress, MemoryCell value) {
        assert(parameterMode != ParameterMode::immediateMode);
        if(parameterMode == ParameterMode::relativeMode) {
            parameterAddress += m_relativeBase;
        }

        get(parameterAddress) = value;
    }

    /// Get the parameter specified by the mode and the next instruction
    MemoryCell getNextParameter(ParameterModes& parameterModes) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        return readNumber(parameterMode, parameterOrAddress);
    }

    /// Use the address of the next parameter to write down the given value
    void setAtNextParameter(ParameterModes& parameterModes, MemoryCell value) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        writeNumber(parameterMode, parameterOrAddress, value);
    }

    /// Get the instruction pointed by the instruction pointer
    MemoryCell getNextInstruction() {
        const auto instruction = get(m_ic);
        m_ic++;
        return instruction;
    }

    /// Check if we are still in the range of the memory
    bool hasNextInstruction() const {
        return m_ic < m_memory.size();
    }

    MemoryCell& get(MemoryCell address) {
        if(address >= m_memory.size()) {
            m_memory.resize(address + 1, 0);
        }
        return m_memory[address];
    }
};
solution
Unresolved directive in ../../../../../../day09/c++/nils-braun/solution - include::solution[]

.solution.cpp
[source]

include::solution.cpp[]

:leveloffset!:


++++
<a id="day10" />
++++

=== Day 10: c++

:leveloffset: +2


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

== c++


.input.txt
[source]

…​.…​...…​…​…​…​.…​…​.…​…​ …​..…​..…​…​…​…​…​…​…​.. ..…​…​…​…​.…​...…​…​.…​..# ...…​…​…​.......…​…​.…​... ..…​…​…​…​…​..…​…​…​…​... ...…​…​.....…​....…​.…​. …​…​…​…​…​..…​…​…​.…​…​.. ........…​…​...…​…​…​…​.. …​..…​.…​…​..…​…​…​…​…​…​…​ …​....…​…​.…​…​…​…​.....# …​..…​.…​…​…​…​…​…​…​…​ …​…​…​.…​....…​…​........…​ …​.…​..…​…​.....…​.…​…​.. …​…​…​…​…​.#…​…​…​…​…​. …​…​…​..…​.…​…​…​.…​.…​…​ …​…​…​...…​.…​.…​..…​... ..…​..…​…​…​.…​…​…​.…​…​…​.. .....…​…​…​…​…​..…​…​…​.. ...…​.…​…​…​…​…​…​.…​…​…​.. ...…​..…​…​…​…​.…​…​…​... …​…​.…​.…​…​.…​.…​..…​…​.. …​…​…​..…​…​.…​.…​…​.... .…​…​…​..…​…​…​…​…​..…​…​.. …​…​…​…​…​.…​…​..…​…​…​.... ...…​…​.…​…​…​...…​…​…​…​…​ …​.…​…​…​…​…​…​…​…​..#.... …​..…​...…​…​…​..…​…​..…​. .…​..…​.…​..…​…​…​....…​…​ ..…​…​…​....…​…​…​…​... #…​…​.…​…​..…​...…​…​…​…​ …​..…​…​..…​…​…​…​... ..…​.....…​....…​..…​.…​... …​..…​..…​…​…​…​..#.…​…​…​. .......…​..…​…​…​...…​.…​... …​...…​…​…​..…​…​…​…​.... ...…​…​…​..…​…​…​.…​…​…​…​. …​..…​.…​..…​…​…​…​..…​.# …​..…​…​…​.....…​...…​…​.. .…​…​…​…​...…​..…​…​..…​ …​.…​.…​…​…​...…​..…​... …​…​....…​…​…​…​…​...…​…​ …​…​…​…​…​..…​…​…​…​…​…​…​. …​…​…​…​…​…​…​…​…​...…​…​..#

.solution
[source]

Unresolved directive in ../../../../../../day10/c++/nils-braun/solution - include::solution[]

solution.cpp
include::solution.cpp[]
Day 11: c++

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

c++
input.txt
3,8,1005,8,325,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,28,2,3,7,10,2,1109,3,10,2,102,0,10,2,1005,12,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,101,0,8,67,2,109,12,10,1,1003,15,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,96,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1002,8,1,119,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,141,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,162,1,106,17,10,1006,0,52,1006,0,73,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,194,1006,0,97,1,1004,6,10,1006,0,32,2,8,20,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,231,1,1,15,10,1006,0,21,1,6,17,10,2,1005,8,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,267,2,1007,10,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,294,1006,0,74,2,1003,2,10,1,107,1,10,101,1,9,9,1007,9,1042,10,1005,10,15,99,109,647,104,0,104,1,21101,936333018008,0,1,21101,342,0,0,1106,0,446,21102,937121129228,1,1,21101,0,353,0,1105,1,446,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,209383001255,1,21102,400,1,0,1106,0,446,21101,0,28994371675,1,21101,411,0,0,1105,1,446,3,10,104,0,104,0,3,10,104,0,104,0,21101,867961824000,0,1,21101,0,434,0,1106,0,446,21102,1,983925674344,1,21101,0,445,0,1106,0,446,99,109,2,21201,-1,0,1,21102,40,1,2,21101,477,0,3,21102,467,1,0,1106,0,510,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,472,473,488,4,0,1001,472,1,472,108,4,472,10,1006,10,504,1101,0,0,472,109,-2,2106,0,0,0,109,4,1201,-1,0,509,1207,-3,0,10,1006,10,527,21102,1,0,-3,21202,-3,1,1,21201,-2,0,2,21102,1,1,3,21102,1,546,0,1106,0,551,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,574,2207,-4,-2,10,1006,10,574,22101,0,-4,-4,1105,1,642,21202,-4,1,1,21201,-3,-1,2,21202,-2,2,3,21101,0,593,0,1105,1,551,22102,1,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,612,21102,1,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,634,21201,-1,0,1,21101,634,0,0,105,1,509,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0
IntMachine.h
// Solution for day05: 1202 Program Alarm
#include <fstream>
#include <iostream>
#include <assert.h>
#include <vector>
#include <tuple>
#include <sstream>

class Memory {
private:
    using MemoryCell = long long int;

    enum class ParameterMode {
        positionalMode = 0,
        immediateMode = 1,
        relativeMode = 2
    };

    class ParameterModes {
    public:
        ParameterModes(unsigned int parameterModes) : m_intValue(parameterModes) {}

        ParameterMode getNextMode() {
            // Grab the next parameter mode and delete it from the list of parameter modes
            const auto parameterMode = m_intValue % 10;
            m_intValue /= 10;

            return static_cast<ParameterMode>(parameterMode);
        }

    private:
        unsigned int m_intValue = 0;
    };

public:
    /// Split the input by comma
    static Memory readIn() {
        Memory result;

        std::ifstream inputFile("input.txt");
        std::string intCodeAsString;

        while(std::getline(inputFile, intCodeAsString, ',')) {
            const auto intCode = std::atoll(intCodeAsString.c_str());
            result.m_memory.push_back(intCode);
        }

        return result;
    }

    std::vector<MemoryCell> run(std::vector<MemoryCell>&& input, bool stopOnOutput = false) {
        m_input.swap(input);
        m_output.clear();

        while(hasNextInstruction()) {
            const auto instruction = getNextInstruction();
            const unsigned int opCode = instruction % 100;
            ParameterModes parameterModes(instruction / 100);

            if(not apply(opCode, parameterModes, stopOnOutput)) {
                break;
            }
        }

        return m_output;
    }

private:
    /// The memory content
    std::vector<MemoryCell> m_memory;

    /// The address of the current instruction
    MemoryCell m_ic = 0;

    /// The relative base address
    MemoryCell m_relativeBase = 0;

    /// The input vector
    std::vector<MemoryCell> m_input;

    /// The output vector
    std::vector<MemoryCell> m_output;

    /// Apply the operation given by the opcode and the parameter modes
    bool apply(unsigned int opCode, ParameterModes parameterModes, bool stopOnOutput) {
        if(opCode == 1) {
            // addition
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam + secondParam);
        } else if (opCode == 2) {
            // multiply
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam * secondParam);
        } else if (opCode == 3) {
            // read input from internal vector
            // TODO: reversed!!!
            if(m_input.empty()) {
                // Nothing to digest!
                // more one step back, so the next time we can continue here
                m_ic--;
                return false;
            }
            const auto input = m_input.back();
            m_input.pop_back();
            setAtNextParameter(parameterModes, input);
        } else if (opCode == 4) {
            // write output to internal vector
            const auto param = getNextParameter(parameterModes);
            m_output.push_back(param);
            if(stopOnOutput) {
                return false;
            }
        } else if(opCode == 5) {
            // jump if true
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam != 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 6) {
            // jump if false
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam == 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 7) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam < secondParam);
        } else if(opCode == 8) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam == secondParam);
        } else if(opCode == 9) {
            // adjust relative base
            const auto param = getNextParameter(parameterModes);
            m_relativeBase += param;
        } else if (opCode == 99) {
            return false;
        } else {
            throw std::exception();
        }

        return true;
    }

    /**
     * Helper function to read the parameter value given by the parameter.
     *
     * If the next parameterMode (the least-significant digit) is 1, use the parameter directly.
     * If the parameterMode is 0, interpret the parameter as an address in memory.
     */
    MemoryCell readNumber(ParameterMode parameterMode, MemoryCell parameterOrAddress) {
        if(parameterMode == ParameterMode::immediateMode) {
            return parameterOrAddress;
        } else if(parameterMode == ParameterMode::positionalMode) {
            // We use .at() instead of [] to have boundary checks
            return get(parameterOrAddress);
        } else if(parameterMode == ParameterMode::relativeMode) {
            return get(parameterOrAddress + m_relativeBase);
        }
    }

    /// Write at the given address. This can not be immediate mode!
    void writeNumber(ParameterMode parameterMode, MemoryCell parameterAddress, MemoryCell value) {
        assert(parameterMode != ParameterMode::immediateMode);
        if(parameterMode == ParameterMode::relativeMode) {
            parameterAddress += m_relativeBase;
        }

        get(parameterAddress) = value;
    }

    /// Get the parameter specified by the mode and the next instruction
    MemoryCell getNextParameter(ParameterModes& parameterModes) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        return readNumber(parameterMode, parameterOrAddress);
    }

    /// Use the address of the next parameter to write down the given value
    void setAtNextParameter(ParameterModes& parameterModes, MemoryCell value) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        writeNumber(parameterMode, parameterOrAddress, value);
    }

    /// Get the instruction pointed by the instruction pointer
    MemoryCell getNextInstruction() {
        const auto instruction = get(m_ic);
        m_ic++;
        return instruction;
    }

    /// Check if we are still in the range of the memory
    bool hasNextInstruction() const {
        return m_ic < m_memory.size();
    }

    MemoryCell& get(MemoryCell address) {
        if(address >= m_memory.size()) {
            m_memory.resize(address + 1, 0);
        }
        return m_memory[address];
    }
};
solution
Unresolved directive in ../../../../../../day11/c++/nils-braun/solution - include::solution[]

.solution.cpp
[source]

include::solution.cpp[]

:leveloffset: 2


++++
<a id="day12" />
++++

=== Day 12: c++

:leveloffset: +2


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

== c++


.input.txt
[source]

3,8,1005,8,325,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,28,2,3,7,10,2,1109,3,10,2,102,0,10,2,1005,12,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,101,0,8,67,2,109,12,10,1,1003,15,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,96,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1002,8,1,119,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,141,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,162,1,106,17,10,1006,0,52,1006,0,73,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,194,1006,0,97,1,1004,6,10,1006,0,32,2,8,20,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,231,1,1,15,10,1006,0,21,1,6,17,10,2,1005,8,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,267,2,1007,10,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,294,1006,0,74,2,1003,2,10,1,107,1,10,101,1,9,9,1007,9,1042,10,1005,10,15,99,109,647,104,0,104,1,21101,936333018008,0,1,21101,342,0,0,1106,0,446,21102,937121129228,1,1,21101,0,353,0,1105,1,446,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,209383001255,1,21102,400,1,0,1106,0,446,21101,0,28994371675,1,21101,411,0,0,1105,1,446,3,10,104,0,104,0,3,10,104,0,104,0,21101,867961824000,0,1,21101,0,434,0,1106,0,446,21102,1,983925674344,1,21101,0,445,0,1106,0,446,99,109,2,21201,-1,0,1,21102,40,1,2,21101,477,0,3,21102,467,1,0,1106,0,510,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,472,473,488,4,0,1001,472,1,472,108,4,472,10,1006,10,504,1101,0,0,472,109,-2,2106,0,0,0,109,4,1201,-1,0,509,1207,-3,0,10,1006,10,527,21102,1,0,-3,21202,-3,1,1,21201,-2,0,2,21102,1,1,3,21102,1,546,0,1106,0,551,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,574,2207,-4,-2,10,1006,10,574,22101,0,-4,-4,1105,1,642,21202,-4,1,1,21201,-3,-1,2,21202,-2,2,3,21101,0,593,0,1105,1,551,22102,1,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,612,21102,1,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,634,21201,-1,0,1,21101,634,0,0,105,1,509,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0

.solution
[source]

Unresolved directive in ../../../../../../day12/c++/nils-braun/solution - include::solution[]

solution.cpp
include::solution.cpp[]
Day 13: c++

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

c++
input.txt
1,380,379,385,1008,2267,610415,381,1005,381,12,99,109,2268,1101,0,0,383,1101,0,0,382,20102,1,382,1,20101,0,383,2,21101,37,0,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,37,381,1005,381,22,1001,383,1,383,1007,383,22,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,1105,1,161,107,1,392,381,1006,381,161,1101,-1,0,384,1106,0,119,1007,392,35,381,1006,381,161,1101,0,1,384,21001,392,0,1,21102,1,20,2,21101,0,0,3,21102,138,1,0,1105,1,549,1,392,384,392,21002,392,1,1,21101,0,20,2,21101,3,0,3,21101,161,0,0,1106,0,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21102,1,180,0,1105,1,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,21002,389,1,2,21101,205,0,0,1106,0,393,1002,390,-1,390,1102,1,1,384,21002,388,1,1,20001,389,391,2,21102,228,1,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,20101,0,388,1,20001,389,391,2,21101,253,0,0,1105,1,393,1002,391,-1,391,1101,1,0,384,1005,384,161,20001,388,390,1,20001,389,391,2,21102,1,279,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,304,0,0,1105,1,393,1002,390,-1,390,1002,391,-1,391,1101,1,0,384,1005,384,161,20102,1,388,1,20101,0,389,2,21101,0,0,3,21102,338,1,0,1105,1,549,1,388,390,388,1,389,391,389,20102,1,388,1,20101,0,389,2,21101,0,4,3,21102,1,365,0,1106,0,549,1007,389,21,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,265,16,17,1,1,18,109,3,21202,-2,1,1,21201,-1,0,2,21102,1,0,3,21102,414,1,0,1105,1,549,22101,0,-2,1,21202,-1,1,2,21101,429,0,0,1105,1,601,2102,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,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,22101,0,-3,-7,109,-8,2106,0,0,109,4,1202,-2,37,566,201,-3,566,566,101,639,566,566,2102,1,-1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,37,593,201,-2,593,593,101,639,593,593,21001,0,0,-2,109,-3,2105,1,0,109,3,22102,22,-2,1,22201,1,-1,1,21102,1,409,2,21102,1,463,3,21102,1,814,4,21102,1,630,0,1106,0,456,21201,1,1453,-2,109,-3,2105,1,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,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,2,2,0,2,2,0,2,2,2,0,0,0,2,2,2,2,0,2,2,2,2,2,0,2,2,2,2,0,2,0,0,0,0,1,1,0,0,2,0,0,2,2,0,0,0,2,2,0,2,2,0,0,0,2,2,0,2,2,2,2,0,0,2,2,0,0,2,0,2,0,1,1,0,0,2,2,2,0,0,0,2,2,2,2,0,0,2,2,0,2,0,2,0,2,2,0,2,2,2,0,2,2,0,2,2,2,0,1,1,0,2,0,0,2,2,2,0,2,2,0,2,0,2,2,2,2,0,0,2,2,2,0,2,2,0,0,0,0,2,2,0,0,2,0,1,1,0,2,2,2,0,0,0,2,2,2,0,2,2,2,2,2,0,0,0,2,2,0,2,2,2,0,2,0,0,0,0,0,2,2,0,1,1,0,2,2,2,2,2,2,0,0,2,2,2,0,0,0,0,2,0,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,1,1,0,0,0,2,0,0,2,2,2,0,2,0,0,0,0,2,0,0,0,0,2,0,2,0,0,0,2,0,0,2,0,2,2,2,0,1,1,0,2,0,0,2,2,0,0,0,2,0,0,0,2,2,2,2,0,2,2,0,2,2,0,2,2,2,2,2,2,2,2,0,0,0,1,1,0,2,0,0,0,2,0,2,2,2,2,2,0,0,2,0,2,2,0,0,2,2,0,2,2,0,2,2,0,2,0,0,2,2,0,1,1,0,2,0,2,2,0,2,2,0,0,0,0,0,2,2,0,2,0,0,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,1,1,0,0,0,0,2,0,2,2,2,2,0,2,2,0,2,2,2,0,2,2,0,2,2,2,0,2,0,0,2,2,0,2,0,0,0,1,1,0,0,2,2,2,0,2,0,2,0,2,2,2,0,0,2,2,0,2,2,2,0,0,0,0,2,0,2,2,0,2,0,2,2,0,1,1,0,0,2,2,2,2,0,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,2,0,2,2,2,0,2,0,0,1,1,0,2,0,2,2,2,2,2,2,0,0,0,0,0,0,2,2,0,2,2,2,2,0,0,2,2,2,2,2,0,0,0,2,2,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,1,1,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,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,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,1,1,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,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,1,72,10,67,45,58,25,55,73,97,49,19,51,58,95,30,82,74,9,98,96,38,64,30,45,14,73,42,5,3,61,68,23,18,14,9,16,21,7,77,39,38,16,82,17,58,87,90,64,52,1,96,67,66,16,65,15,22,41,69,90,93,92,96,45,68,17,63,51,15,61,51,93,65,55,42,76,48,52,31,98,6,88,69,65,65,30,51,88,4,13,36,90,80,23,31,42,63,86,52,15,79,78,59,77,57,71,84,81,73,56,1,5,7,86,75,31,63,76,21,73,16,41,86,15,78,85,2,79,63,54,79,65,87,13,86,96,81,69,27,76,8,48,5,79,10,74,76,86,95,55,72,52,23,41,50,46,68,29,86,61,96,29,34,40,86,86,1,20,90,35,69,64,50,51,75,65,93,19,5,15,96,3,88,8,43,66,88,72,84,69,42,4,95,51,80,81,27,75,92,22,45,54,63,51,82,91,13,25,54,41,84,84,29,98,50,91,11,40,69,13,47,42,72,46,87,31,27,98,65,94,26,51,79,39,29,38,42,46,25,36,26,66,12,93,58,1,61,41,37,57,60,60,9,70,63,26,56,1,27,5,11,93,17,48,95,19,79,16,14,16,29,79,56,16,26,37,50,10,38,53,4,10,3,57,20,59,16,51,88,66,74,91,56,42,84,30,36,31,36,58,68,66,91,36,71,30,39,96,50,84,76,95,14,89,75,59,77,66,36,88,62,60,3,45,13,39,48,33,59,21,19,35,90,81,66,52,75,34,70,55,56,47,22,20,87,73,73,76,73,8,96,55,46,5,1,64,27,8,37,87,50,8,79,74,63,26,43,44,2,85,91,28,13,16,15,55,87,94,28,86,66,29,34,46,18,41,37,94,63,31,78,48,17,4,25,62,15,10,18,19,97,50,78,5,79,5,70,64,86,61,58,59,61,5,71,68,14,24,17,56,85,52,64,92,45,90,94,55,47,5,56,59,20,15,41,36,58,55,25,47,45,69,58,36,44,80,94,52,84,17,27,20,44,51,93,10,56,77,45,29,93,63,96,95,47,31,63,69,64,74,53,34,36,20,14,40,30,61,86,15,3,94,61,43,75,59,64,41,34,98,32,65,73,18,30,46,66,38,68,25,96,16,37,54,38,44,26,52,1,2,21,93,37,26,4,45,69,82,59,34,55,34,77,88,46,70,32,56,82,10,20,31,40,20,55,3,3,93,95,65,56,61,68,41,35,62,20,58,55,42,41,40,33,51,6,52,84,27,62,81,32,35,87,97,79,7,97,77,40,48,74,4,6,36,58,59,25,6,5,84,7,44,51,88,37,9,30,29,26,91,41,72,39,24,68,58,49,80,49,43,98,43,92,9,49,64,10,96,50,86,56,2,72,58,80,57,77,61,74,14,42,50,55,40,21,77,20,19,16,80,84,92,27,32,37,80,59,69,13,11,19,6,94,54,88,51,69,41,54,68,36,82,68,19,77,85,37,5,58,61,72,5,67,17,35,29,18,71,46,5,29,8,93,97,36,37,25,93,27,33,93,79,10,84,75,6,91,98,34,32,37,70,18,84,52,32,11,88,44,69,58,92,52,68,77,39,90,9,58,74,1,53,56,64,75,46,59,39,52,32,41,62,81,75,7,93,29,89,51,34,31,93,70,94,30,98,68,3,60,2,2,49,31,15,65,11,78,70,2,50,29,9,9,85,65,52,28,95,55,77,98,29,65,56,51,32,44,42,82,14,29,22,5,29,65,86,84,88,58,63,10,13,13,51,97,17,57,19,39,83,72,93,15,54,31,83,3,43,21,83,74,2,86,47,25,89,20,11,68,80,29,21,58,69,610415
IntMachine.h
// Solution for day05: 1202 Program Alarm
#include <fstream>
#include <iostream>
#include <assert.h>
#include <vector>
#include <tuple>
#include <sstream>

class Memory {
private:
    using MemoryCell = long long int;

    enum class ParameterMode {
        positionalMode = 0,
        immediateMode = 1,
        relativeMode = 2
    };

    class ParameterModes {
    public:
        ParameterModes(unsigned int parameterModes) : m_intValue(parameterModes) {}

        ParameterMode getNextMode() {
            // Grab the next parameter mode and delete it from the list of parameter modes
            const auto parameterMode = m_intValue % 10;
            m_intValue /= 10;

            return static_cast<ParameterMode>(parameterMode);
        }

    private:
        unsigned int m_intValue = 0;
    };

public:
    /// Split the input by comma
    static Memory readIn() {
        Memory result;

        std::ifstream inputFile("input.txt");
        std::string intCodeAsString;

        while(std::getline(inputFile, intCodeAsString, ',')) {
            const auto intCode = std::atoll(intCodeAsString.c_str());
            result.m_memory.push_back(intCode);
        }

        return result;
    }

    void adjustMemory(unsigned int offset, const MemoryCell& content) {
        m_memory.at(offset) = content;
    }

    std::vector<MemoryCell> run(std::vector<MemoryCell>&& input, unsigned int stopOnOutput = 0) {
        m_input.swap(input);
        m_output.clear();

        while(hasNextInstruction()) {
            const auto instruction = getNextInstruction();
            const unsigned int opCode = instruction % 100;
            ParameterModes parameterModes(instruction / 100);

            if(not apply(opCode, parameterModes, stopOnOutput)) {
                break;
            }
        }

        return m_output;
    }

private:
    /// The memory content
    std::vector<MemoryCell> m_memory;

    /// The address of the current instruction
    MemoryCell m_ic = 0;

    /// The relative base address
    MemoryCell m_relativeBase = 0;

    /// The input vector
    std::vector<MemoryCell> m_input;

    /// The output vector
    std::vector<MemoryCell> m_output;

    /// Apply the operation given by the opcode and the parameter modes
    bool apply(unsigned int opCode, ParameterModes parameterModes, unsigned int stopOnOutput) {
        if(opCode == 1) {
            // addition
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam + secondParam);
        } else if (opCode == 2) {
            // multiply
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam * secondParam);
        } else if (opCode == 3) {
            // read input from internal vector
            // TODO: reversed!!!
            if(m_input.empty()) {
                // Nothing to digest!
                // more one step back, so the next time we can continue here
                m_ic--;
                return false;
            }
            const auto input = m_input.back();
            m_input.pop_back();
            setAtNextParameter(parameterModes, input);
        } else if (opCode == 4) {
            // write output to internal vector
            const auto param = getNextParameter(parameterModes);
            m_output.push_back(param);
            if(stopOnOutput > 0 and m_output.size() == stopOnOutput) {
                return false;
            }
        } else if(opCode == 5) {
            // jump if true
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam != 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 6) {
            // jump if false
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam == 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 7) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam < secondParam);
        } else if(opCode == 8) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam == secondParam);
        } else if(opCode == 9) {
            // adjust relative base
            const auto param = getNextParameter(parameterModes);
            m_relativeBase += param;
        } else if (opCode == 99) {
            return false;
        } else {
            throw std::exception();
        }

        return true;
    }

    /**
     * Helper function to read the parameter value given by the parameter.
     *
     * If the next parameterMode (the least-significant digit) is 1, use the parameter directly.
     * If the parameterMode is 0, interpret the parameter as an address in memory.
     */
    MemoryCell readNumber(ParameterMode parameterMode, MemoryCell parameterOrAddress) {
        if(parameterMode == ParameterMode::immediateMode) {
            return parameterOrAddress;
        } else if(parameterMode == ParameterMode::positionalMode) {
            // We use .at() instead of [] to have boundary checks
            return get(parameterOrAddress);
        } else if(parameterMode == ParameterMode::relativeMode) {
            return get(parameterOrAddress + m_relativeBase);
        }
    }

    /// Write at the given address. This can not be immediate mode!
    void writeNumber(ParameterMode parameterMode, MemoryCell parameterAddress, MemoryCell value) {
        assert(parameterMode != ParameterMode::immediateMode);
        if(parameterMode == ParameterMode::relativeMode) {
            parameterAddress += m_relativeBase;
        }

        get(parameterAddress) = value;
    }

    /// Get the parameter specified by the mode and the next instruction
    MemoryCell getNextParameter(ParameterModes& parameterModes) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        return readNumber(parameterMode, parameterOrAddress);
    }

    /// Use the address of the next parameter to write down the given value
    void setAtNextParameter(ParameterModes& parameterModes, MemoryCell value) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        writeNumber(parameterMode, parameterOrAddress, value);
    }

    /// Get the instruction pointed by the instruction pointer
    MemoryCell getNextInstruction() {
        const auto instruction = get(m_ic);
        m_ic++;
        return instruction;
    }

    /// Check if we are still in the range of the memory
    bool hasNextInstruction() const {
        return m_ic < m_memory.size();
    }

    MemoryCell& get(MemoryCell address) {
        if(address >= m_memory.size()) {
            m_memory.resize(address + 1, 0);
        }
        return m_memory[address];
    }
};
solution
Unresolved directive in ../../../../../../day13/c++/nils-braun/solution - include::solution[]

.solution.cpp
[source]

include::solution.cpp[]

:leveloffset: 4


++++
<a id="day14" />
++++

=== Day 14: c++

:leveloffset: +2


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

== c++


.input.txt
[source]

10 KVPH ⇒ 5 HPRK 5 RSTBJ ⇒ 5 QKBQL 2 GZWFN, 21 WBPFQ ⇒ 5 KMFWH 5 JDJB, 1 FSWFT, 1 NKVSV ⇒ 6 MGKSL 5 BCRHK ⇒ 9 KXFTL 23 NKVSV, 2 RSTBJ ⇒ 9 QPBVD 19 BKFVS, 7 JZBFT ⇒ 7 XWTQ 14 JLXP, 4 LSCL ⇒ 8 FWLTD 173 ORE ⇒ 5 TZSDV 2 FPVH, 1 JDJB, 3 KHRW ⇒ 2 QLNJ 1 HTGMX, 1 GVJVK, 2 RLRK ⇒ 2 HWBM 1 GLVHT, 1 PBCT, 5 ZWKGV, 1 QSVJ, 2 FWLTD, 3 CNVPB, 1 QGNL ⇒ 8 RNLTX 1 KXZTS ⇒ 2 BKFVS 1 KVPH, 6 PVHPV, 2 TZSDV ⇒ 4 RLRK 118 ORE ⇒ 1 VRVZ 7 MGKSL, 4 HWBM ⇒ 2 GZWFN 5 PVHPV ⇒ 7 HTGMX 25 LSCL, 12 GVMFW ⇒ 6 ZWKGV 1 CTPND, 1 KXZTS ⇒ 3 FRQH 1 KXFTL ⇒ 3 PBCT 1 CMPX ⇒ 4 KZNBL 2 HDQVB, 1 QPBVD ⇒ 5 CTPND 14 KVPH ⇒ 1 FCBQN 3 XWTQ, 22 CTHM, 4 KVPH, 4 BZTV, 1 KMFWH, 12 NRFK ⇒ 7 CXVR 1 GVJVK ⇒ 7 RSTBJ 1 GVJVK ⇒ 4 NSQHW 3 NKVSV ⇒ 8 KHRW 8 HDQVB, 9 BCRHK ⇒ 6 GVMFW 142 ORE ⇒ 7 KVPH 4 TZSDV ⇒ 2 GVJVK 4 KVPH, 10 HWBM ⇒ 3 NRFK 47 PBCT, 15 CXVR, 45 GVJVK, 23 KZNBL, 1 WFPNP, 14 RNLTX ⇒ 1 FUEL 1 PCBNG ⇒ 4 QLJXM 1 SHTQF ⇒ 2 FNWBZ 2 FCBQN, 1 BCRHK ⇒ 5 HVFBV 1 BZTQ ⇒ 9 CTHM 16 SHTQF ⇒ 3 BZTQ 11 PBCT, 5 PCBNG, 2 CTPND ⇒ 1 WBPFQ 3 KHRW ⇒ 4 FSWFT 12 HDQVB, 1 PBCT, 9 NRFK ⇒ 9 VLWJL 5 SHTQF, 8 HVFBV ⇒ 6 BZTV 2 KZNBL, 7 NRFK ⇒ 3 DVFS 18 HTLSF, 14 DVFS ⇒ 6 TLFNL 1 RSTBJ ⇒ 1 NKVSV 2 QLNJ, 7 BZTQ ⇒ 6 PCBNG 1 HTLSF, 19 CMPX ⇒ 7 JDJB 6 KZNBL, 3 QSVJ ⇒ 8 SHTQF 3 HTLSF, 1 VRVZ ⇒ 6 CMPX 1 MGKSL, 15 CTPND ⇒ 6 STNPH 2 NKVSV, 7 JDJB ⇒ 4 KXZTS 3 KVPH ⇒ 4 QSVJ 1 HPRK, 9 PCBNG, 2 KXFTL ⇒ 9 CNVPB 27 GZWFN, 1 VLWJL, 15 LSCL ⇒ 3 GLVHT 162 ORE ⇒ 4 HTLSF 193 ORE ⇒ 8 PVHPV 9 TLFNL, 1 KHRW ⇒ 6 HDQVB 6 QLJXM, 4 FCBQN ⇒ 7 JLXP 3 HTLSF, 21 NSQHW, 18 GVJVK ⇒ 7 BCRHK 1 HTGMX, 20 CMPX, 6 RSTBJ ⇒ 6 FPVH 4 KXZTS, 7 CNVPB, 1 STNPH ⇒ 2 LSCL 3 KXZTS, 1 PCBNG ⇒ 3 JZBFT 22 WBPFQ, 22 FRQH, 1 QLNJ, 4 CTHM, 3 GVMFW, 1 KMFWH, 4 QKBQL ⇒ 4 WFPNP 3 QLJXM, 11 FNWBZ, 3 WBPFQ ⇒ 5 QGNL

.solution
[source]

Unresolved directive in ../../../../../../day14/c++/nils-braun/solution - include::solution[]

solution.cpp
include::solution.cpp[]
Day 15: c++

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

c++
input.txt
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,101,0,1034,1039,101,0,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,101,0,1038,1043,1002,1037,1,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,1,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,0,2,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1101,1,0,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,43,1044,1105,1,224,1101,0,0,1044,1106,0,224,1006,1044,247,1002,1039,1,1034,1002,1040,1,1035,102,1,1041,1036,1001,1043,0,1038,101,0,1042,1037,4,1044,1105,1,0,13,30,60,64,5,28,36,24,67,12,1,67,32,39,14,78,29,17,38,88,79,9,62,25,15,18,88,25,7,81,38,41,10,69,86,32,11,33,1,10,22,84,14,92,48,79,10,3,62,33,61,13,93,78,20,63,68,17,80,34,12,8,23,61,90,51,17,84,37,46,64,25,3,73,19,45,99,41,62,21,77,8,17,89,9,13,84,75,85,14,53,60,6,29,76,63,14,23,63,61,93,72,17,41,28,94,5,3,19,47,57,55,14,34,38,79,85,40,13,22,99,67,72,15,62,15,6,63,3,90,2,87,20,84,15,50,70,27,18,78,21,70,48,52,2,99,92,55,3,46,41,93,99,88,13,39,4,45,71,3,96,1,91,59,31,53,23,25,82,32,50,16,60,38,78,34,59,30,15,51,92,3,22,26,62,60,37,42,74,28,21,76,7,24,70,18,40,11,81,41,9,73,62,12,66,81,9,3,74,62,11,6,56,16,34,20,78,79,1,97,17,39,87,15,12,77,94,28,22,66,45,59,39,2,6,52,6,72,49,17,92,15,86,18,92,79,67,20,22,72,10,72,3,52,26,77,78,41,97,36,59,88,24,57,12,38,90,53,14,38,67,2,36,44,93,99,10,41,49,3,16,7,63,32,11,15,81,12,91,39,62,19,83,6,91,28,19,80,38,23,63,31,71,14,58,8,21,71,21,21,81,38,26,32,29,82,52,28,72,54,97,41,65,96,75,1,48,28,80,66,25,47,49,29,87,51,12,50,70,36,60,81,29,77,76,55,25,40,45,83,91,26,72,99,12,47,11,20,27,52,9,98,17,99,27,37,62,25,3,15,73,66,22,5,85,5,20,98,20,38,62,78,21,16,59,28,98,38,31,2,40,46,87,14,48,33,80,48,36,27,56,21,1,50,83,3,61,92,20,52,16,50,10,86,9,98,39,56,25,50,42,39,91,81,56,25,70,44,24,15,99,4,20,55,12,98,27,65,20,77,97,76,36,42,87,6,11,79,65,16,65,44,13,90,13,48,79,13,95,60,19,55,24,66,4,53,11,23,68,14,97,53,45,14,16,93,18,29,83,5,6,77,19,70,97,34,20,70,52,11,74,14,72,10,36,44,33,45,19,38,36,77,5,37,51,1,55,17,2,48,23,18,2,34,90,97,24,30,51,66,33,70,51,37,31,51,37,65,55,18,8,66,4,65,62,26,93,29,88,3,75,73,24,23,67,1,13,68,7,36,87,62,48,1,31,45,28,62,86,24,98,1,59,49,37,26,62,36,44,66,18,17,97,92,40,36,65,80,84,5,84,6,79,87,36,31,96,15,71,96,2,72,11,81,95,94,41,54,31,58,25,74,24,51,81,38,32,73,22,96,40,62,22,59,74,39,25,86,2,55,20,61,40,37,88,69,1,60,42,18,31,54,13,27,19,93,34,41,99,33,89,20,16,52,84,32,94,31,6,61,25,1,61,1,38,78,87,39,31,39,26,68,42,36,2,94,66,2,67,30,80,2,95,65,40,54,50,33,11,23,97,89,1,31,56,9,35,49,92,55,23,84,48,91,20,7,72,25,55,3,85,3,16,40,90,22,99,44,38,86,98,11,76,26,76,13,82,80,24,93,4,15,64,95,58,15,85,25,57,29,66,3,66,19,98,57,24,44,59,35,76,48,31,92,33,94,68,56,41,45,15,46,5,68,15,65,34,73,49,68,17,78,28,80,24,59,26,74,21,52,1,94,5,61,41,88,37,56,1,49,0,0,21,21,1,10,1,0,0,0,0,0,0
IntMachine.h
// Solution for day05: 1202 Program Alarm
#include <fstream>
#include <iostream>
#include <assert.h>
#include <vector>
#include <tuple>
#include <sstream>

class Memory {
private:
    using MemoryCell = long long int;

    enum class ParameterMode {
        positionalMode = 0,
        immediateMode = 1,
        relativeMode = 2
    };

    class ParameterModes {
    public:
        ParameterModes(unsigned int parameterModes) : m_intValue(parameterModes) {}

        ParameterMode getNextMode() {
            // Grab the next parameter mode and delete it from the list of parameter modes
            const auto parameterMode = m_intValue % 10;
            m_intValue /= 10;

            return static_cast<ParameterMode>(parameterMode);
        }

    private:
        unsigned int m_intValue = 0;
    };

public:
    /// Split the input by comma
    static Memory readIn() {
        Memory result;

        std::ifstream inputFile("input.txt");
        std::string intCodeAsString;

        while(std::getline(inputFile, intCodeAsString, ',')) {
            const auto intCode = std::atoll(intCodeAsString.c_str());
            result.m_memory.push_back(intCode);
        }

        return result;
    }

    void adjustMemory(unsigned int offset, const MemoryCell& content) {
        m_memory.at(offset) = content;
    }

    std::vector<MemoryCell> run(std::vector<MemoryCell>&& input, unsigned int stopOnOutput = 0) {
        m_input.swap(input);
        m_output.clear();

        while(hasNextInstruction()) {
            const auto instruction = getNextInstruction();
            const unsigned int opCode = instruction % 100;
            ParameterModes parameterModes(instruction / 100);

            if(not apply(opCode, parameterModes, stopOnOutput)) {
                break;
            }
        }

        return m_output;
    }

private:
    /// The memory content
    std::vector<MemoryCell> m_memory;

    /// The address of the current instruction
    MemoryCell m_ic = 0;

    /// The relative base address
    MemoryCell m_relativeBase = 0;

    /// The input vector
    std::vector<MemoryCell> m_input;

    /// The output vector
    std::vector<MemoryCell> m_output;

    /// Apply the operation given by the opcode and the parameter modes
    bool apply(unsigned int opCode, ParameterModes parameterModes, unsigned int stopOnOutput) {
        if(opCode == 1) {
            // addition
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam + secondParam);
        } else if (opCode == 2) {
            // multiply
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam * secondParam);
        } else if (opCode == 3) {
            // read input from internal vector
            // TODO: reversed!!!
            if(m_input.empty()) {
                // Nothing to digest!
                // more one step back, so the next time we can continue here
                m_ic--;
                return false;
            }
            const auto input = m_input.back();
            m_input.pop_back();
            setAtNextParameter(parameterModes, input);
        } else if (opCode == 4) {
            // write output to internal vector
            const auto param = getNextParameter(parameterModes);
            m_output.push_back(param);
            if(stopOnOutput > 0 and m_output.size() == stopOnOutput) {
                return false;
            }
        } else if(opCode == 5) {
            // jump if true
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam != 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 6) {
            // jump if false
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            if(firstParam == 0) {
                m_ic = secondParam;
            }
        } else if(opCode == 7) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam < secondParam);
        } else if(opCode == 8) {
            // less then
            const auto firstParam = getNextParameter(parameterModes);
            const auto secondParam = getNextParameter(parameterModes);
            setAtNextParameter(parameterModes, firstParam == secondParam);
        } else if(opCode == 9) {
            // adjust relative base
            const auto param = getNextParameter(parameterModes);
            m_relativeBase += param;
        } else if (opCode == 99) {
            return false;
        } else {
            throw std::exception();
        }

        return true;
    }

    /**
     * Helper function to read the parameter value given by the parameter.
     *
     * If the next parameterMode (the least-significant digit) is 1, use the parameter directly.
     * If the parameterMode is 0, interpret the parameter as an address in memory.
     */
    MemoryCell readNumber(ParameterMode parameterMode, MemoryCell parameterOrAddress) {
        if(parameterMode == ParameterMode::immediateMode) {
            return parameterOrAddress;
        } else if(parameterMode == ParameterMode::positionalMode) {
            // We use .at() instead of [] to have boundary checks
            return get(parameterOrAddress);
        } else if(parameterMode == ParameterMode::relativeMode) {
            return get(parameterOrAddress + m_relativeBase);
        }
    }

    /// Write at the given address. This can not be immediate mode!
    void writeNumber(ParameterMode parameterMode, MemoryCell parameterAddress, MemoryCell value) {
        assert(parameterMode != ParameterMode::immediateMode);
        if(parameterMode == ParameterMode::relativeMode) {
            parameterAddress += m_relativeBase;
        }

        get(parameterAddress) = value;
    }

    /// Get the parameter specified by the mode and the next instruction
    MemoryCell getNextParameter(ParameterModes& parameterModes) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        return readNumber(parameterMode, parameterOrAddress);
    }

    /// Use the address of the next parameter to write down the given value
    void setAtNextParameter(ParameterModes& parameterModes, MemoryCell value) {
        const auto parameterMode = parameterModes.getNextMode();
        const auto parameterOrAddress = getNextInstruction();
        writeNumber(parameterMode, parameterOrAddress, value);
    }

    /// Get the instruction pointed by the instruction pointer
    MemoryCell getNextInstruction() {
        const auto instruction = get(m_ic);
        m_ic++;
        return instruction;
    }

    /// Check if we are still in the range of the memory
    bool hasNextInstruction() const {
        return m_ic < m_memory.size();
    }

    MemoryCell& get(MemoryCell address) {
        if(address >= m_memory.size()) {
            m_memory.resize(address + 1, 0);
        }
        return m_memory[address];
    }
};
solution
Unresolved directive in ../../../../../../day15/c++/nils-braun/solution - include::solution[]

.solution.cpp
[source]

include::solution.cpp[]

:leveloffset: 6