Compare commits

...
9 Commits
Author SHA1 Message Date
Thraix d0bd08c596 Add solution for 2017 Day 2 2026-09-26 19:59:52 +02:00
Thraix bcf645a6c0 Add solution for 2016 Day 1 2026-09-26 13:09:11 +02:00
Thraix 3b014b0abc Add 2017 templates 2026-09-05 17:19:46 +02:00
Thraix a56cc80169 Add solution for 2016 Day 25 2026-09-04 20:54:17 +02:00
Thraix 551df7ffb2 Add solution for 2016 Day 24 2026-09-04 19:42:12 +02:00
Thraix edc2fd0b6c Add solution for 2016 Day 23 2026-09-04 18:37:21 +02:00
Thraix bec8be80a3 Add solution for 2016 Day 22 2026-09-04 18:37:13 +02:00
Thraix c62c9dc3de Add solution for 2016 Day 21 2026-09-03 22:09:48 +02:00
Thraix 78cb890ed7 Add solution for 2016 Day 20 2026-09-03 22:09:35 +02:00
66 changed files with 2022 additions and 72 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
5-8
0-2
4-7
+8
View File
@@ -0,0 +1,8 @@
swap position 4 with position 0
swap letter d with letter b
reverse positions 0 through 4
rotate left 1
move position 1 to position 4
move position 3 to position 0
rotate based on position of letter b
rotate based on position of letter d
+11
View File
@@ -0,0 +1,11 @@
root@ebhq-gridcenter# df -h
Filesystem Size Used Avail Use%
/dev/grid/node-x0-y0 10T 8T 2T 80%
/dev/grid/node-x0-y1 11T 6T 5T 54%
/dev/grid/node-x0-y2 32T 28T 4T 87%
/dev/grid/node-x1-y0 9T 7T 2T 77%
/dev/grid/node-x1-y1 8T 0T 8T 0%
/dev/grid/node-x1-y2 11T 7T 4T 63%
/dev/grid/node-x2-y0 10T 6T 4T 60%
/dev/grid/node-x2-y1 9T 8T 1T 88%
/dev/grid/node-x2-y2 9T 6T 3T 66%
+7
View File
@@ -0,0 +1,7 @@
cpy 2 a
tgl a
tgl a
tgl a
cpy 1 a
dec a
dec a
+5
View File
@@ -0,0 +1,5 @@
###########
#0.1.....2#
#.#######.#
#4.......3#
###########
+1
View File
@@ -0,0 +1 @@
123123
+3
View File
@@ -0,0 +1,3 @@
5 9 2 8
9 4 7 3
3 8 6 5
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
View File
Whitespace-only changes.
+37 -7
View File
@@ -2,30 +2,60 @@
namespace y2016::day20
{
REGISTER_DAY(2016, Day20, std::vector<int>, int);
using Input = std::vector<std::pair<uint64_t, uint64_t>>;
REGISTER_DAY(2016, Day20, Input, uint32_t);
REGISTER_TEST_EXAMPLE(2016, Day20, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day20, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day20, ExampleInput, 2, 0);
REGISTER_TEST(2016, Day20, Input, 2, 0);
REGISTER_TEST_EXAMPLE(2016, Day20, ExampleInput, 1, 3);
REGISTER_TEST(2016, Day20, Input, 1, 19449262);
REGISTER_TEST_EXAMPLE(2016, Day20, ExampleInput, 2, 2);
REGISTER_TEST(2016, Day20, Input, 2, 119);
READ_INPUT(input)
{
std::vector<int> vec;
std::vector<std::pair<uint64_t, uint64_t>> vec;
std::string str;
while (getline(input, str))
{
std::pair<uint32_t, uint32_t> pair;
std::stringstream ss{str};
ss >> pair.first >> "-" >> pair.second;
vec.emplace_back(pair);
}
std::sort(vec.begin(), vec.end());
return vec;
}
OUTPUT1(input)
{
if (input.front().first != 0)
return 0;
for (int i = 0; i < input.size(); i++)
{
if (input[i].second + 1 < input[i + 1].first)
return input[i].second + 1;
}
return 0;
}
OUTPUT2(input)
{
return 0;
uint64_t allowed = input.front().first;
uint64_t currentMax = input.front().second;
for (int i = 1; i < input.size(); i++)
{
if (currentMax < input[i].first - 1)
{
allowed += input[i].first - currentMax - 1;
currentMax = input[i].second;
}
else
{
currentMax = std::max(currentMax, input[i].second);
}
}
uint32_t max = isExample ? 9 : std::numeric_limits<uint32_t>::max();
allowed += max - currentMax;
return allowed;
}
}
+206 -8
View File
@@ -2,30 +2,228 @@
namespace y2016::day21
{
REGISTER_DAY(2016, Day21, std::vector<int>, int);
enum class Operator
{
Swap,
SwapLetter,
Rotate,
RotatePos,
Reverse,
Move
};
REGISTER_TEST_EXAMPLE(2016, Day21, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day21, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day21, ExampleInput, 2, 0);
REGISTER_TEST(2016, Day21, Input, 2, 0);
struct Instruction
{
Operator op;
int arg1;
int arg2;
};
REGISTER_DAY(2016, Day21, std::vector<Instruction>, std::string);
REGISTER_TEST_EXAMPLE(2016, Day21, ExampleInput, 1, "decab");
REGISTER_TEST(2016, Day21, Input, 1, "hcdefbag");
REGISTER_TEST(2016, Day21, Input, 2, "fbhaegdc");
READ_INPUT(input)
{
std::vector<int> vec;
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
std::stringstream ss{str};
if (Helper::StartsWith(str, "swap position"))
{
instruction.op = Operator::Swap;
ss >> "swap position " >> instruction.arg1 >> "with position " >> instruction.arg2;
}
else if (Helper::StartsWith(str, "swap letter"))
{
instruction.op = Operator::SwapLetter;
char c1, c2;
ss >> "swap letter " >> c1 >> "with letter " >> c2;
instruction.arg1 = c1;
instruction.arg2 = c2;
}
else if (Helper::StartsWith(str, "rotate left"))
{
instruction.op = Operator::Rotate;
ss >> "rotate left" >> instruction.arg1;
instruction.arg1 = -instruction.arg1;
}
else if (Helper::StartsWith(str, "rotate right"))
{
instruction.op = Operator::Rotate;
ss >> "rotate right" >> instruction.arg1;
}
else if (Helper::StartsWith(str, "rotate based"))
{
instruction.op = Operator::RotatePos;
char c;
ss >> "rotate based on position of letter " >> c;
instruction.arg1 = c;
}
else if (str[0] == 'r')
{
instruction.op = Operator::Reverse;
ss >> "reverse positions " >> instruction.arg1 >> "through " >> instruction.arg2;
}
else
{
instruction.op = Operator::Move;
ss >> "move position " >> instruction.arg1 >> "to position " >> instruction.arg2;
}
vec.emplace_back(instruction);
}
return vec;
}
OUTPUT1(input)
{
return 0;
CyclicVector<char> data{isExample ? "abcde" : "abcdefgh"};
for (const auto& instruction : input)
{
switch (instruction.op)
{
case Operator::Swap:
{
std::swap(data[instruction.arg1], data[instruction.arg2]);
break;
}
case Operator::SwapLetter:
{
size_t i1 = data.Find(instruction.arg1);
size_t i2 = data.Find(instruction.arg2);
std::swap(data[i1], data[i2]);
break;
}
case Operator::Rotate:
{
data.Rotate(instruction.arg1);
break;
}
case Operator::RotatePos:
{
size_t pos = data.Find(instruction.arg1);
int additional = pos >= 4 ? 1 : 0;
data.Rotate(pos + 1 + additional);
break;
}
case Operator::Reverse:
{
for (size_t i = 0; i < (instruction.arg2 - instruction.arg1 + 1) / 2; i++)
{
std::swap(data[instruction.arg1 + i], data[instruction.arg2 - i]);
}
break;
}
case Operator::Move:
{
if (instruction.arg1 < instruction.arg2)
{
char c = data[instruction.arg1];
for (size_t i = instruction.arg1; i < instruction.arg2; i++)
{
data[i] = data[i + 1];
}
data[instruction.arg2] = c;
}
else
{
char c = data[instruction.arg1];
for (size_t i = instruction.arg1; i > instruction.arg2; i--)
{
data[i] = data[i - 1];
}
data[instruction.arg2] = c;
}
break;
}
}
}
std::string str;
for (size_t i = 0; i < data.size(); i++)
{
str.push_back(data[i]);
}
return str;
}
OUTPUT2(input)
{
return 0;
CyclicVector<char> data{"fbgdceah"};
std::map<int, int> rotatePosMap;
for (int i = 0; i < data.size(); i++)
{
int result = (i + i + 1 + (i >= 4 ? 1 : 0)) % data.size();
rotatePosMap.emplace(result, i - result);
}
for (int i = input.size() - 1; i >= 0; i--)
{
const auto& instruction = input[i];
switch (instruction.op)
{
case Operator::Swap:
{
std::swap(data[instruction.arg1], data[instruction.arg2]);
break;
}
case Operator::SwapLetter:
{
size_t i1 = data.Find(instruction.arg1);
size_t i2 = data.Find(instruction.arg2);
std::swap(data[i1], data[i2]);
break;
}
case Operator::Rotate:
{
data.Rotate(-instruction.arg1);
break;
}
case Operator::RotatePos:
{
size_t pos = data.Find(instruction.arg1);
data.Rotate(rotatePosMap[pos]);
break;
}
case Operator::Reverse:
{
for (size_t i = 0; i < (instruction.arg2 - instruction.arg1 + 1) / 2; i++)
{
std::swap(data[instruction.arg1 + i], data[instruction.arg2 - i]);
}
break;
}
case Operator::Move:
{
if (instruction.arg2 < instruction.arg1)
{
char c = data[instruction.arg2];
for (size_t i = instruction.arg2; i < instruction.arg1; i++)
{
data[i] = data[i + 1];
}
data[instruction.arg1] = c;
}
else
{
char c = data[instruction.arg2];
for (size_t i = instruction.arg2; i > instruction.arg1; i--)
{
data[i] = data[i - 1];
}
data[instruction.arg1] = c;
}
break;
}
}
}
std::string str;
for (auto c : data)
{
str.push_back(c);
}
return str;
}
}
+113 -8
View File
@@ -2,30 +2,135 @@
namespace y2016::day22
{
REGISTER_DAY(2016, Day22, std::vector<int>, int);
struct Fs
{
int used;
int avail;
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day22, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 2, 0);
REGISTER_TEST(2016, Day22, Input, 2, 0);
bool operator==(const Fs& other) const
{
return used == other.used && avail == other.avail;
}
};
REGISTER_DAY(2016, Day22, Array2D<Fs>, int);
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 1, 7);
REGISTER_TEST(2016, Day22, Input, 1, 1024);
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 2, 7);
REGISTER_TEST(2016, Day22, Input, 2, 230);
READ_INPUT(input)
{
std::vector<int> vec;
std::vector<std::pair<std::pair<int, int>, Fs>> fss;
Array2D<Fs> vec{};
std::string str;
getline(input, str);
getline(input, str);
int maxX = 0;
int maxY = 0;
while (getline(input, str))
{
// /dev/grid/node-x0-y0 91T 71T 20T 78%
Fs fs;
std::stringstream ss{str};
int dummy;
int x;
int y;
ss >> "/dev/grid/node-x" >> x >> "-y" >> y >> dummy >> "T" >> fs.used >> "T" >> fs.avail >> "T";
fss.emplace_back(std::pair{std::pair{x, y}, fs});
maxX = std::max(maxX, x);
maxY = std::max(maxY, y);
}
vec = Array2D<Fs>{maxX + 1, maxY + 1};
for (const auto& [pos, fs] : fss)
{
vec.Set(pos.first, pos.second, fs);
}
return vec;
}
struct State
{
Index2D goal;
Index2D empty;
bool operator<(const State& other) const
{
if (goal != other.goal)
return goal < other.goal;
return empty < other.empty;
}
friend std::ostream& operator<<(std::ostream& os, const State& state)
{
return os << state.goal << " " << state.empty;
}
};
std::vector<std::pair<int, State>> Branch(const Array2D<Fs>& initial, const State& state)
{
std::vector<std::pair<int, State>> states{};
Fs emptyFs = initial.Get(state.empty);
std::vector<Index2D> neighbors = initial.GetNeighbors(state.empty, false);
for (const auto& neighbor : neighbors)
{
if (initial.Get(neighbor).used < 400)
{
State newState = state;
if (neighbor == state.goal)
newState.goal = state.empty;
newState.empty = neighbor;
states.emplace_back(1, newState);
}
}
return states;
}
bool Goal(const Array2D<Fs>& initial, const State& state)
{
return state.goal == Index2D{0, 0};
}
int Heuristic(const Array2D<Fs>& initial, const State& state)
{
return state.goal.x + state.goal.y;
}
OUTPUT1(input)
{
return 0;
int count = 0;
for (const auto& val : input)
{
if (val.used == 0)
continue;
for (const auto& val2 : input)
{
if (val == val2)
continue;
if (val.used <= val2.avail)
{
count++;
}
}
}
return count;
}
OUTPUT2(input)
{
return 0;
State state;
state.goal = Index2D{input.width - 1, 0};
for (int i = 0; i < input.height; i++)
{
for (int j = 0; j < input.width; j++)
{
if (input.Get(j, i).used == 0)
{
state.empty = Index2D{j, i};
}
}
}
return Helper::AStar(input, state, Heuristic, Branch, Goal);
}
}
+175 -8
View File
@@ -2,30 +2,197 @@
namespace y2016::day23
{
REGISTER_DAY(2016, Day23, std::vector<int>, int);
enum class Operator
{
Cpy,
Inc,
Dec,
Jnz,
Tgl
};
REGISTER_TEST_EXAMPLE(2016, Day23, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day23, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day23, ExampleInput, 2, 0);
REGISTER_TEST(2016, Day23, Input, 2, 0);
struct Instruction
{
Operator op;
std::variant<char, int> arg1;
std::variant<char, int> arg2;
};
REGISTER_DAY(2016, Day23, std::vector<Instruction>, int);
REGISTER_TEST(2016, Day23, Input, 1, 11415);
REGISTER_TEST(2016, Day23, Input, 2, 479007975);
std::variant<char, int> ReadArg(const std::string& str, int arg)
{
size_t pos = str.find(' ');
int i = 0;
while (i < arg)
{
pos = str.find(' ', pos + 1);
i++;
}
if (str[pos + 1] >= 'a' && str[pos + 1] <= 'd')
return str[pos + 1];
return (int)std::atoi(str.c_str() + pos + 1);
}
READ_INPUT(input)
{
std::vector<int> vec;
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
if (str[0] == 'c')
{
instruction.op = Operator::Cpy;
instruction.arg1 = ReadArg(str, 0);
instruction.arg2 = ReadArg(str, 1);
}
else if (str[0] == 'i')
{
instruction.op = Operator::Inc;
instruction.arg1 = ReadArg(str, 0);
}
else if (str[0] == 'd')
{
instruction.op = Operator::Dec;
instruction.arg1 = ReadArg(str, 0);
}
else if (str[0] == 'j')
{
instruction.op = Operator::Jnz;
instruction.arg1 = ReadArg(str, 0);
instruction.arg2 = ReadArg(str, 1);
}
else if (str[0] == 't')
{
instruction.op = Operator::Tgl;
instruction.arg1 = ReadArg(str, 0);
}
vec.emplace_back(instruction);
}
return vec;
}
void Toggle(Instruction& instruction)
{
switch (instruction.op)
{
case Operator::Cpy:
instruction.op = Operator::Jnz;
break;
case Operator::Inc:
instruction.op = Operator::Dec;
break;
case Operator::Dec:
instruction.op = Operator::Inc;
break;
case Operator::Jnz:
instruction.op = Operator::Cpy;
break;
case Operator::Tgl:
instruction.op = Operator::Inc;
break;
}
}
bool IsValid(const Instruction& instruction)
{
switch (instruction.op)
{
case Operator::Cpy:
return std::holds_alternative<char>(instruction.arg2);
case Operator::Inc:
return std::holds_alternative<char>(instruction.arg1);
case Operator::Dec:
return std::holds_alternative<char>(instruction.arg1);
case Operator::Jnz:
return true;
case Operator::Tgl:
return true;
}
return false;
}
int GetRegisterIndex(const std::variant<char, int>& c)
{
return std::get<char>(c) - 'a';
}
int GetValue(const std::vector<int>& registers, const std::variant<char, int>& data)
{
if (std::holds_alternative<int>(data))
return std::get<int>(data);
else
return registers[GetRegisterIndex(data)];
}
int Run(std::vector<Instruction> instructions, std::vector<int> registers)
{
int i = 0;
for (size_t pc = 0; pc < instructions.size(); pc++)
{
i++;
if (!IsValid(instructions[pc]))
continue;
// The input program I got does a multiplication (a = b * d). So instead of using the ++, -- operators, calculate
// it directly and set the registers to expected value after the operation is done.
// Other inputs might have different pc position, and multiply different registers.
if (pc == 4)
{
registers[0] = registers[1] * registers[3];
registers[3] = 0;
registers[2] = registers[1];
pc = 9;
}
switch (instructions[pc].op)
{
case Operator::Cpy:
{
int number = GetValue(registers, instructions[pc].arg1);
registers[GetRegisterIndex(instructions[pc].arg2)] = number;
break;
}
case Operator::Inc:
{
registers[GetRegisterIndex(instructions[pc].arg1)]++;
break;
}
case Operator::Dec:
{
registers[GetRegisterIndex(instructions[pc].arg1)]--;
break;
}
case Operator::Jnz:
{
int value = GetValue(registers, instructions[pc].arg1);
if (value != 0)
pc += GetValue(registers, instructions[pc].arg2) - 1;
break;
}
case Operator::Tgl:
{
int offset = registers[GetRegisterIndex(instructions[pc].arg1)];
if (pc + offset >= 0 && pc + offset < instructions.size())
Toggle(instructions[pc + offset]);
}
break;
}
}
return registers[0];
}
OUTPUT1(input)
{
return 0;
return Run(input, std::vector<int>{7, 0, 0, 0});
}
OUTPUT2(input)
{
return 0;
return Run(input, std::vector<int>{12, 0, 0, 0});
}
}
+59 -12
View File
@@ -2,30 +2,77 @@
namespace y2016::day24
{
REGISTER_DAY(2016, Day24, std::vector<int>, int);
REGISTER_DAY(2016, Day24, Array2D<char>, int);
REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day24, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 2, 0);
REGISTER_TEST(2016, Day24, Input, 2, 0);
REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 1, 14);
REGISTER_TEST(2016, Day24, Input, 1, 448);
REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 2, 20);
REGISTER_TEST(2016, Day24, Input, 2, 672);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
return Input::ReadArray2D(input);
}
return vec;
struct State
{
Index2D pos;
char goalChar;
bool operator<(const State& other) const
{
return pos < other.pos;
}
};
std::vector<std::pair<int, State>> Branch(const Array2D<char>& map, const State& state)
{
std::vector<std::pair<int, State>> branches;
for (const auto& pos : map.GetNeighbors(state.pos, false))
{
if (map[pos] != '#')
branches.emplace_back(1, State{pos, state.goalChar});
}
return branches;
}
bool Goal(const Array2D<char>& map, const State& state)
{
return map[state.pos] == state.goalChar;
}
Graph<char, int> GetGraph(const Array2D<char>& map)
{
std::vector<Index2D> positions(10);
for (auto it = map.begin(); it != map.end(); it++)
{
if (*it >= '0' && *it <= '9')
{
positions[*it - '0'] = it.index;
}
}
while (!positions.back().IsValid())
positions.pop_back();
Graph<char, int> graph;
for (size_t i = 0; i < positions.size(); i++)
{
for (size_t j = i + 1; j < positions.size(); j++)
{
int distance = Helper::Dijkstras(map, State{positions[i], (char)(j + '0')}, Branch, Goal);
graph.AddTwoWayEdge(i + '0', j + '0', distance);
}
}
return graph;
}
OUTPUT1(input)
{
return 0;
return Helper::TSP(GetGraph(input), '0', false);
}
OUTPUT2(input)
{
return 0;
return Helper::TSP(GetGraph(input), '0', true);
}
}
+173 -7
View File
@@ -2,30 +2,196 @@
namespace y2016::day25
{
REGISTER_DAY(2016, Day25, std::vector<int>, int);
enum class Operator
{
Cpy,
Inc,
Dec,
Jnz,
Out,
};
REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 1, 0);
REGISTER_TEST(2016, Day25, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 2, 0);
struct Instruction
{
Operator op;
std::variant<char, int> arg1;
std::variant<char, int> arg2;
};
REGISTER_DAY(2016, Day25, std::vector<Instruction>, int);
REGISTER_TEST(2016, Day25, Input, 1, 182);
REGISTER_TEST(2016, Day25, Input, 2, 0);
std::variant<char, int> ReadArg(const std::string& str, int arg)
{
size_t pos = str.find(' ');
int i = 0;
while (i < arg)
{
pos = str.find(' ', pos + 1);
i++;
}
if (str[pos + 1] >= 'a' && str[pos + 1] <= 'd')
return str[pos + 1];
return (int)std::atoi(str.c_str() + pos + 1);
}
READ_INPUT(input)
{
std::vector<int> vec;
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
if (str[0] == 'c')
{
instruction.op = Operator::Cpy;
instruction.arg1 = ReadArg(str, 0);
instruction.arg2 = ReadArg(str, 1);
}
else if (str[0] == 'i')
{
instruction.op = Operator::Inc;
instruction.arg1 = ReadArg(str, 0);
}
else if (str[0] == 'd')
{
instruction.op = Operator::Dec;
instruction.arg1 = ReadArg(str, 0);
}
else if (str[0] == 'j')
{
instruction.op = Operator::Jnz;
instruction.arg1 = ReadArg(str, 0);
instruction.arg2 = ReadArg(str, 1);
}
else if (str[0] == 'o')
{
instruction.op = Operator::Out;
instruction.arg1 = ReadArg(str, 0);
}
vec.emplace_back(instruction);
}
return vec;
}
void Toggle(Instruction& instruction)
{
switch (instruction.op)
{
case Operator::Cpy:
instruction.op = Operator::Jnz;
break;
case Operator::Inc:
instruction.op = Operator::Dec;
break;
case Operator::Dec:
instruction.op = Operator::Inc;
break;
case Operator::Jnz:
instruction.op = Operator::Cpy;
break;
case Operator::Out:
instruction.op = Operator::Inc;
break;
}
}
bool IsValid(const Instruction& instruction)
{
switch (instruction.op)
{
case Operator::Cpy:
return std::holds_alternative<char>(instruction.arg2);
case Operator::Inc:
return std::holds_alternative<char>(instruction.arg1);
case Operator::Dec:
return std::holds_alternative<char>(instruction.arg1);
case Operator::Jnz:
return true;
case Operator::Out:
return true;
}
return false;
}
int GetRegisterIndex(const std::variant<char, int>& c)
{
return std::get<char>(c) - 'a';
}
int GetValue(const std::vector<int>& registers, const std::variant<char, int>& data)
{
if (std::holds_alternative<int>(data))
return std::get<int>(data);
else
return registers[GetRegisterIndex(data)];
}
bool Run(std::vector<Instruction> instructions, std::vector<int> registers)
{
int count = 0;
for (size_t pc = 0; pc < instructions.size(); pc++)
{
// From analysis of the input, it loops the same output every time we get to pc = 8.
// As such, if we get there, and count is > 0, we know that the signal alternates, since we've already returned
// false if the output to this point is not alternating
if (pc == 8 && count > 0)
return true;
switch (instructions[pc].op)
{
case Operator::Cpy:
{
int number = GetValue(registers, instructions[pc].arg1);
registers[GetRegisterIndex(instructions[pc].arg2)] = number;
break;
}
case Operator::Inc:
{
registers[GetRegisterIndex(instructions[pc].arg1)]++;
break;
}
case Operator::Dec:
{
registers[GetRegisterIndex(instructions[pc].arg1)]--;
break;
}
case Operator::Jnz:
{
int value = GetValue(registers, instructions[pc].arg1);
if (value != 0)
pc += GetValue(registers, instructions[pc].arg2) - 1;
break;
}
case Operator::Out:
{
if (GetValue(registers, instructions[pc].arg1) != count % 2)
return false;
count++;
}
break;
}
}
return false;
}
OUTPUT1(input)
{
return 0;
int i = -1;
while (!Run(input, std::vector<int>{++i, 0, 0, 0}))
;
return i;
}
OUTPUT2(input)
{
return 0;
std::cout << " ___ ___" << std::endl;
std::cout << " (o o) (o o)" << std::endl;
std::cout << "( V ) MERRY CHRISTMAS! ( V )" << std::endl;
std::cout << "--m-m----------------------m-m--" << std::endl;
return Run(input, std::vector<int>{12, 0, 0, 0});
}
}
+39
View File
@@ -0,0 +1,39 @@
#include "common/aoc.h"
namespace y2017::day01
{
REGISTER_DAY(2017, Day01, std::string, int);
REGISTER_TEST_EXAMPLE(2017, Day01, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day01, Input, 1, 1089);
REGISTER_TEST_EXAMPLE(2017, Day01, ExampleInput, 2, 12);
REGISTER_TEST(2017, Day01, Input, 2, 1156);
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
int Solve(const std::string& str, int offset)
{
int count = 0;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == str[(i + offset) % str.size()])
count += str[i] - '0';
}
return count;
}
OUTPUT1(input)
{
return Solve(input, 1);
}
OUTPUT2(input)
{
return Solve(input, input.size() / 2);
}
}
+67
View File
@@ -0,0 +1,67 @@
#include "common/aoc.h"
namespace y2017::day02
{
REGISTER_DAY(2017, Day02, std::vector<std::vector<int>>, int);
REGISTER_TEST_EXAMPLE(2017, Day02, ExampleInput, 1, 18);
REGISTER_TEST(2017, Day02, Input, 1, 48357);
REGISTER_TEST_EXAMPLE(2017, Day02, ExampleInput, 2, 9);
REGISTER_TEST(2017, Day02, Input, 2, 351);
READ_INPUT(input)
{
std::vector<std::vector<int>> vec;
std::string str;
while (getline(input, str))
{
std::vector<int> vec2;
std::stringstream ss{str};
int i;
while (ss >> i)
{
vec2.emplace_back(i);
}
vec.emplace_back(vec2);
}
return vec;
}
OUTPUT1(input)
{
int checksum = 0;
for (const auto& vec : input)
{
int min = std::numeric_limits<int>::max();
int max = 0;
for (const auto& i : vec)
{
min = std::min(min, i);
max = std::max(max, i);
}
checksum += max - min;
}
return checksum;
}
OUTPUT2(input)
{
int checksum = 0;
for (int i = 0; i < input.size(); i++)
{
std::vector<int> divisible;
for (int j = 0; j < input[i].size(); j++)
{
for (int k = 0; k < input[i].size(); k++)
{
if (j == k)
continue;
if (input[i][j] % input[i][k] == 0)
checksum += input[i][j] / input[i][k];
}
}
}
return checksum;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day03
{
REGISTER_DAY(2017, Day03, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day03, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day03, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day03, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day03, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day04
{
REGISTER_DAY(2017, Day04, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day04, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day04, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day04, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day04, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day05
{
REGISTER_DAY(2017, Day05, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day05, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day05, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day05, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day05, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day06
{
REGISTER_DAY(2017, Day06, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day06, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day06, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day06, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day06, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day07
{
REGISTER_DAY(2017, Day07, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day07, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day07, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day07, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day07, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day08
{
REGISTER_DAY(2017, Day08, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day08, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day08, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day08, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day08, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day09
{
REGISTER_DAY(2017, Day09, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day09, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day09, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day09, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day09, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day10
{
REGISTER_DAY(2017, Day10, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day10, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day10, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day10, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day10, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day11
{
REGISTER_DAY(2017, Day11, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day11, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day11, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day11, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day11, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day12
{
REGISTER_DAY(2017, Day12, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day12, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day12, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day12, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day12, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day13
{
REGISTER_DAY(2017, Day13, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day13, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day13, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day13, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day13, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day14
{
REGISTER_DAY(2017, Day14, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day14, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day14, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day14, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day14, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day15
{
REGISTER_DAY(2017, Day15, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day15, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day15, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day15, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day15, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day16
{
REGISTER_DAY(2017, Day16, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day16, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day16, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day16, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day16, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day17
{
REGISTER_DAY(2017, Day17, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day17, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day17, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day17, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day17, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day18
{
REGISTER_DAY(2017, Day18, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day18, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day18, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day18, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day18, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day19
{
REGISTER_DAY(2017, Day19, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day19, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day19, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day19, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day19, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day20
{
REGISTER_DAY(2017, Day20, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day20, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day20, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day20, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day20, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day21
{
REGISTER_DAY(2017, Day21, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day21, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day21, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day21, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day21, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day22
{
REGISTER_DAY(2017, Day22, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day22, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day22, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day22, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day22, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day23
{
REGISTER_DAY(2017, Day23, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day23, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day23, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day23, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day23, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day24
{
REGISTER_DAY(2017, Day24, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day24, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day24, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day24, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day24, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2017::day25
{
REGISTER_DAY(2017, Day25, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2017, Day25, ExampleInput, 1, 0);
REGISTER_TEST(2017, Day25, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2017, Day25, ExampleInput, 2, 0);
REGISTER_TEST(2017, Day25, Input, 2, 0);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}
+1
View File
@@ -24,6 +24,7 @@
#include "common/lib/Array2D.h"
#include "common/lib/Array3D.h"
#include "common/lib/Array4D.h"
#include "common/lib/CyclicVector.h"
#include "common/lib/Graph.h"
#include "common/lib/Helper.h"
#include "common/lib/Input.h"
+5
View File
@@ -500,6 +500,11 @@ struct Array2D
return ConstIterator{*this, Index2D{0, height}};
}
bool operator<(const Array2D<T>& other) const
{
return array2D < other.array2D;
}
friend std::ostream& operator<<(std::ostream& os, const Array2D& array2D)
{
for (int y = 0; y < array2D.height; y++)
+354
View File
@@ -0,0 +1,354 @@
#pragma once
#include <ostream>
#include <string>
#include <vector>
template <typename T>
struct CyclicVector
{
std::vector<T> vector;
size_t offset{0};
CyclicVector(const std::initializer_list<T>& vector)
: vector{vector}
{
}
CyclicVector(const std::vector<T>& vector)
: vector{vector}
{
}
template <typename U = T, typename = std::enable_if_t<std::is_same_v<U, char>>>
CyclicVector(const std::string& str)
: vector{str.begin(), str.end()}
{
}
template <std::size_t N, typename U = T, typename = std::enable_if_t<std::is_same_v<U, char>>>
CyclicVector(const char (&str)[N])
{
vector.resize(N - 1); // don't include \0 character
for (size_t i = 0; i < N - 1; i++)
{
vector[i] = str[i];
}
}
void Rotate(int i)
{
if (i < 0)
RotateLeft(-i);
else
RotateRight(i);
}
void RotateRight(int i)
{
offset = (offset + vector.size() - (i % vector.size())) % vector.size();
}
void RotateLeft(size_t i)
{
offset = (offset + i) % vector.size();
}
T& operator[](size_t i)
{
return vector[(i + offset) % vector.size()];
}
const T& operator[](size_t i) const
{
return vector[(i + offset) % vector.size()];
}
size_t size() const
{
return vector.size();
}
bool empty() const
{
return vector.empty();
}
size_t Find(const T& t) const
{
return std::find(begin(), end(), t).GetPos();
}
struct iterator;
struct const_iterator;
iterator begin()
{
return iterator{*this, 0};
}
iterator end()
{
return iterator{*this, vector.size()};
}
const_iterator begin() const
{
return const_iterator{*this, 0};
}
const_iterator end() const
{
return const_iterator{*this, vector.size()};
}
const_iterator cbegin() const
{
return const_iterator{*this, 0};
}
const_iterator cend() const
{
return const_iterator{*this, vector.size()};
}
friend std::ostream& operator<<(std::ostream& os, const CyclicVector& vector)
{
os << "[";
if (!vector.empty())
os << vector[0];
for (auto it = vector.cbegin() + 1; it != vector.cend(); it++)
{
os << ", " << *it;
}
os << "]";
return os;
}
class iterator
{
private:
CyclicVector<T>& data;
size_t pos;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = T*;
using reference = T&;
iterator(CyclicVector<T>& data, size_t pos)
: data{data},
pos{pos}
{
}
size_t GetPos() const
{
return pos;
}
reference operator*() const
{
return data[pos];
}
pointer operator->() const
{
return &data[pos];
}
iterator& operator++()
{
++pos;
return *this;
}
iterator operator++(int)
{
iterator ret = *this;
++(*this);
return ret;
}
iterator& operator--()
{
--pos;
return *this;
}
iterator operator--(int)
{
iterator ret = *this;
--(*this);
return ret;
}
iterator& operator+=(size_t advance)
{
if (std::numeric_limits<size_t>::max() - pos < advance)
{
pos = data.size();
}
else
{
pos += advance;
if (pos >= data.size())
pos = data.size();
}
return *this;
}
iterator& operator-=(size_t advance)
{
if (advance > pos)
{
pos = data.size();
}
else
{
pos -= advance;
}
return *this;
}
iterator operator+(size_t advance) const
{
iterator ret = *this;
ret += advance;
return ret;
}
iterator operator-(size_t advance) const
{
iterator ret = *this;
ret -= advance;
return ret;
}
bool operator==(const iterator& other) const
{
return pos == other.pos;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
};
class const_iterator
{
private:
const CyclicVector<T>& data;
size_t pos;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = const T*;
using reference = const T&;
const_iterator(const CyclicVector<T>& data, size_t pos)
: data{data},
pos{pos}
{
}
size_t GetPos() const
{
return pos;
}
reference operator*() const
{
return data[pos];
}
pointer operator->() const
{
return &data[pos];
}
const_iterator& operator++()
{
++pos;
return *this;
}
const_iterator operator++(int)
{
const_iterator ret = *this;
++(*this);
return ret;
}
const_iterator& operator--()
{
--pos;
return *this;
}
const_iterator operator--(int)
{
const_iterator ret = *this;
--(*this);
return ret;
}
const_iterator& operator+=(size_t advance)
{
if (std::numeric_limits<size_t>::max() - pos < advance)
{
pos = data.size();
}
else
{
pos += advance;
if (pos >= data.size())
pos = data.size();
}
return *this;
}
const_iterator& operator-=(size_t advance)
{
if (advance > pos)
{
pos = data.size();
}
else
{
pos -= advance;
}
return *this;
}
const_iterator operator+(size_t advance) const
{
const_iterator ret = *this;
ret += advance;
return ret;
}
const_iterator operator-(size_t advance) const
{
const_iterator ret = *this;
ret -= advance;
return ret;
}
bool operator==(const const_iterator& other) const
{
return pos == other.pos;
}
bool operator!=(const const_iterator& other) const
{
return !(*this == other);
}
};
};
+5
View File
@@ -106,6 +106,11 @@ public:
return graph.find(from)->second.find(to)->second;
}
const std::map<Key, std::map<Key, Value>>& GetGraph() const
{
return graph;
}
const std::map<Key, Value>& GetPaths(const Key& from) const
{
return graph.find(from)->second;
+37 -22
View File
@@ -11,6 +11,7 @@
#include <map>
#include <numeric>
#include <set>
#include <variant>
#include <vector>
#include "Array2D.h"
@@ -33,6 +34,9 @@ static std::ostream& operator<<(std::ostream& stream, const std::map<T, S>& cont
template <typename T, typename S>
static std::ostream& operator<<(std::ostream& stream, const std::pair<T, S>& pair);
template <typename Arg1, typename Arg2, typename... Args>
static std::ostream& operator<<(std::ostream& stream, const std::variant<Arg1, Arg2, Args...>& variant);
struct Helper
{
struct ScopedTraceErrorDisabler
@@ -502,17 +506,29 @@ struct Helper
static void ResetTraceErrors();
private:
template <typename Key, typename Value, typename Compare, typename Eval>
template <typename Key, typename Value>
static Value TSPCalculatePath(const Graph<Key, Value>& graph, const std::vector<Key>& path, bool returnToStart)
{
int cost = 0;
for (int i = 0; i < path.size() - 1; i++)
{
cost += graph.GetEdge(path[i], path[i + 1]);
}
if (returnToStart)
cost += graph.GetEdge(path.back(), path.front());
return cost;
}
template <typename Key, typename Value>
static int TSP(const Graph<Key, Value>& graph,
const std::set<Key>& nodesLeft,
const std::vector<Key>& order,
Compare compare,
Eval eval)
bool returnToStart)
{
if (nodesLeft.empty())
{
return eval(graph, order);
}
return TSPCalculatePath(graph, order, returnToStart);
bool hasSet = false;
Value tsp;
@@ -524,9 +540,9 @@ private:
std::vector<Key> newOrder = order;
newOrder.emplace_back(node);
if (hasSet)
tsp = compare(tsp, TSP(graph, newNodesLeft, newOrder, compare, eval));
tsp = std::min(tsp, TSP(graph, newNodesLeft, newOrder, returnToStart));
else
tsp = TSP(graph, newNodesLeft, newOrder, compare, eval);
tsp = TSP(graph, newNodesLeft, newOrder, returnToStart);
hasSet = true;
}
return tsp;
@@ -535,28 +551,20 @@ private:
public:
// Key - Node type of the graph
// Value - Edge type of the graph
// Compare - Value(Value, Value)
// Given two solutions, which one is better
// Eval - int(const Graph&, const std::vector<Key>&)
// Given the graph and order of the TSP, what is the total cost
template <typename Key, typename Value, typename Compare, typename Eval>
static int TSP(const Graph<Key, Value>& graph, const Key& start, Compare compare, Eval eval)
template <typename Key, typename Value>
static int TSP(const Graph<Key, Value>& graph, const Key& start, bool returnToStart)
{
std::set<Key> nodes = graph.GetNodes();
nodes.erase(nodes.find(start));
return TSP(graph, nodes, std::vector<Key>{start}, compare, eval);
return TSP(graph, nodes, std::vector<Key>{start}, returnToStart);
}
// Key - Node type of the graph
// Value - Edge type of the graph
// Compare - Value(Value, Value)
// Given two solutions, which one is better
// Eval - int(const Graph&, const std::vector<Key>&)
// Given the graph and order of the TSP, what is the total cost
template <typename Key, typename Value, typename Compare, typename Eval>
static int TSP(const Graph<Key, Value>& graph, Compare compare, Eval eval)
template <typename Key, typename Value>
static int TSP(const Graph<Key, Value>& graph, bool returnToStart)
{
return TSP(graph, graph.GetNodes(), std::vector<Key>{}, compare, eval);
return TSP(graph, graph.GetNodes(), std::vector<Key>{}, returnToStart);
}
static bool traceErrors;
@@ -639,3 +647,10 @@ static std::ostream& operator<<(std::ostream& stream, const std::pair<T, S>& pai
{
return stream << "(" << pair.first << ", " << pair.second << ")";
}
template <typename Arg1, typename Arg2, typename... Args>
static std::ostream& operator<<(std::ostream& stream, const std::variant<Arg1, Arg2, Args...>& variant)
{
std::visit([&stream](const auto& value) { stream << value; }, variant);
return stream;
}