Compare commits

...

31 Commits

Author SHA1 Message Date
Thraix 85f5de1be2 Add solution for 2016 Day 19 2026-08-31 22:21:13 +02:00
Thraix 8162a46091 Add solution for 2016 Day 18 2026-08-31 20:51:09 +02:00
Thraix ed11090cc2 Add solution for 2016 Day 17
- Fix Md5 algorithm
2026-08-30 22:52:01 +02:00
Thraix 7b2567a71e Add solution for 2016 Day 16 2026-08-27 21:41:22 +02:00
Thraix c669dedbb7 Move Helper functions into cpp file 2026-08-27 20:44:14 +02:00
Thraix 5111d633b7 Add solution for 2016 Day 15 2026-08-26 23:13:22 +02:00
Thraix 988c5552d0 Update clang-format to disallow single line for-loops 2026-08-23 12:12:53 +02:00
Thraix ab6c726ebc Add solution for 2016 Day 14 2026-08-23 12:11:50 +02:00
Thraix 482794f994 Add solution for 2016 Day 13 2026-08-23 10:43:10 +02:00
Thraix f26d9fd416 Add solution for 2016 Day 12 2026-08-22 18:37:41 +02:00
Thraix 5d44b9484f Add solution for 2016 Day 11 2026-08-22 14:33:45 +02:00
Thraix fc16b73a01 Add solution for 2016 Day 10 2026-08-16 20:29:20 +02:00
Thraix e5acfb8635 Add solution for 2016 Day 9 2026-08-16 11:56:04 +02:00
Thraix 3d9b19be4d Add solution for 2016 Day 8 2026-08-15 22:18:32 +02:00
Thraix b60954656b Add solution for 2016 Day 7 2026-08-15 20:48:27 +02:00
Thraix 474e662ebd Add solution for 2016 Day 6 2026-08-15 20:15:30 +02:00
Thraix bf12e141a6 Add solution for 2016 Day 5
- Add Md5 algorithm to library
2026-08-15 15:24:44 +02:00
Thraix c228e8e230 Add solution for 2016 Day 4 2026-08-14 16:09:32 +02:00
Thraix fc76349588 Add solution for 2016 Day 3 2026-08-12 21:00:56 +02:00
Thraix d71df0c742 Add solution for 2016 Day 2 2026-08-11 23:02:52 +02:00
Thraix c8f0000c4d Add solution for 2016 Day 1 2026-08-06 22:17:35 +02:00
Thraix 80eacc6ed2 Add 2016 templates 2026-08-06 21:33:10 +02:00
Thraix 9237445a13 Add solution for 2015 Day 25 2026-08-05 23:41:32 +02:00
Thraix 4de110a517 Add solution for 2015 Day 24 2026-08-04 23:13:43 +02:00
Thraix e8eb238682 Add solution for 2015 Day 23 2026-08-02 23:25:36 +02:00
Thraix 9b09fb26aa Add solution for 2015 Day 22 2026-07-31 19:57:52 +02:00
Thraix cd90db48be Add solution for 2015 Day 21 2026-07-31 14:07:17 +02:00
Thraix 48023a811a Add solution for 2015 Day 20 2026-07-31 00:42:48 +02:00
Thraix 9ef2809593 Add solution for 2015 Day 19 2026-07-30 00:59:49 +02:00
Thraix ce9bc29372 Add solution for 2015 Day 18 2026-07-26 00:13:11 +02:00
Thraix 2a7353d702 Add 2015 templates 2026-07-26 00:11:32 +02:00
131 changed files with 4293 additions and 236 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: false AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: Never AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true AllowShortLoopsOnASingleLine: false
AllowShortNamespacesOnASingleLine: false AllowShortNamespacesOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: true AlwaysBreakBeforeMultilineStrings: true
+1 -1
View File
@@ -13,7 +13,7 @@ for item in $list; do
dir="res/$year/day$day/input.txt" dir="res/$year/day$day/input.txt"
if [ ! -e $dir ]; then if [ ! -e $dir ]; then
webitem=${day#0} webitem=${day#0}
echo "Fetching $dir" echo "Fetching $dir from https://adventofcode.com/$year/day/$webitem/input"
tmp_file=$(mktemp) tmp_file=$(mktemp)
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$tmp_file" --cookie cookies.txt https://adventofcode.com/$year/day/$webitem/input) HTTP_CODE=$(curl -s -w "%{http_code}" -o "$tmp_file" --cookie cookies.txt https://adventofcode.com/$year/day/$webitem/input)
if [ "$HTTP_CODE" -eq 200 ]; then if [ "$HTTP_CODE" -eq 200 ]; then
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
+6
View File
@@ -0,0 +1,6 @@
.#.#.#
...##.
#....#
..#...
#.#..#
####..
+7
View File
@@ -0,0 +1,7 @@
e => H
e => O
H => HO
H => OH
O => HH
HOHOHO
+1
View File
@@ -0,0 +1 @@
149
View File
+2
View File
@@ -0,0 +1,2 @@
Hit Points: 13
Damage: 8
+4
View File
@@ -0,0 +1,4 @@
inc b
jio b, +2
tpl b
inc b
+10
View File
@@ -0,0 +1,10 @@
1
2
3
4
5
7
8
9
10
11
+1
View File
@@ -0,0 +1 @@
To continue, please consult the code grid in the manual. Enter the code at row 3, column 4.
+1
View File
@@ -0,0 +1 @@
R8, R4, R4, R8
+4
View File
@@ -0,0 +1,4 @@
ULL
RRDDD
LURDL
UUUUD
+3
View File
@@ -0,0 +1,3 @@
5 10 25
11 15 25
8 25 20
+4
View File
@@ -0,0 +1,4 @@
aaaaa-bbb-z-y-x-123[abxyz]
a-b-c-d-e-f-g-h-987[abcde]
not-a-real-room-404[oarel]
totally-real-room-200[decoy]
+1
View File
@@ -0,0 +1 @@
abc
+16
View File
@@ -0,0 +1,16 @@
eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar
+8
View File
@@ -0,0 +1,8 @@
abba[mnop]qrst
abcd[bddb]xyyx
aaaa[qwer]tyui
ioxxoj[asdfgh]zxcvbn
aba[bab]xyz
xyx[xyx]xyx
aaa[kek]eke
zazbz[bzb]cdb
+4
View File
@@ -0,0 +1,4 @@
rect 3x2
rotate column x=1 by 1
rotate row y=0 by 4
rotate column x=1 by 1
+1
View File
@@ -0,0 +1 @@
X(8x2)(3x3)ABCY
+6
View File
@@ -0,0 +1,6 @@
value 5 goes to bot 2
bot 2 gives low to bot 1 and high to bot 0
value 3 goes to bot 1
bot 1 gives low to output 1 and high to bot 0
bot 0 gives low to output 2 and high to output 0
value 2 goes to bot 2
+4
View File
@@ -0,0 +1,4 @@
The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
The second floor contains a hydrogen generator.
The third floor contains a lithium generator.
The fourth floor contains nothing relevant.
+6
View File
@@ -0,0 +1,6 @@
cpy 41 a
inc a
inc a
dec a
jnz a 2
dec a
+1
View File
@@ -0,0 +1 @@
10
+1
View File
@@ -0,0 +1 @@
abc
+3
View File
@@ -0,0 +1,3 @@
Disc #1 has 5 positions; at time=0, it is at position 4.
Disc #2 has 2 positions; at time=0, it is at position 1.
Disc #2 has 3 positions; at time=0, it is at position 2.
+1
View File
@@ -0,0 +1 @@
10000
+1
View File
@@ -0,0 +1 @@
ulqzkmiv
+1
View File
@@ -0,0 +1 @@
.^^.^.^^^^
+1
View File
@@ -0,0 +1 @@
5
View File
View File
View File
View File
View File
View File
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2015::day01
{
REGISTER_DAY(2015, Day01, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day01, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day01, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day01, ExampleInput, 2, 0);
REGISTER_TEST(2015, Day01, 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 y2015::day02
{
REGISTER_DAY(2015, Day02, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day02, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day02, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day02, ExampleInput, 2, 0);
REGISTER_TEST(2015, Day02, 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 y2015::day03
{
REGISTER_DAY(2015, Day03, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day03, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day03, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day03, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day04
{
REGISTER_DAY(2015, Day04, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day04, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day04, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day04, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day05
{
REGISTER_DAY(2015, Day05, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day05, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day05, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day05, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day06
{
REGISTER_DAY(2015, Day06, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day06, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day06, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day06, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day07
{
REGISTER_DAY(2015, Day07, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day07, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day07, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day07, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day08
{
REGISTER_DAY(2015, Day08, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day08, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day08, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day08, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day09
{
REGISTER_DAY(2015, Day09, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day09, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day09, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day09, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day10
{
REGISTER_DAY(2015, Day10, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day10, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day10, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day10, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day11
{
REGISTER_DAY(2015, Day11, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day11, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day11, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day11, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day12
{
REGISTER_DAY(2015, Day12, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day12, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day12, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day12, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day13
{
REGISTER_DAY(2015, Day13, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day13, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day13, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day13, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day14
{
REGISTER_DAY(2015, Day14, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day14, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day14, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day14, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day15
{
REGISTER_DAY(2015, Day15, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day15, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day15, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day15, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day16
{
REGISTER_DAY(2015, Day16, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day16, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day16, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day16, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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 y2015::day17
{
REGISTER_DAY(2015, Day17, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2015, Day17, ExampleInput, 1, 0);
REGISTER_TEST(2015, Day17, Input, 1, 0);
REGISTER_TEST_EXAMPLE(2015, Day17, ExampleInput, 2, 0);
REGISTER_TEST(2015, 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;
}
}
+114
View File
@@ -0,0 +1,114 @@
#include "common/aoc.h"
namespace y2015::day18
{
REGISTER_DAY(2015, Day18, Array2D<char>, int);
REGISTER_TEST_EXAMPLE(2015, Day18, ExampleInput, 1, 4);
REGISTER_TEST(2015, Day18, Input, 1, 814);
REGISTER_TEST_EXAMPLE(2015, Day18, ExampleInput, 2, 7);
REGISTER_TEST(2015, Day18, Input, 2, 924);
READ_INPUT(input)
{
return Input::ReadArray2D(input);
}
OUTPUT1(input)
{
Array2D<char> array1 = input;
Array2D<char> array2 = input;
Array2D<char>* current = &array1;
Array2D<char>* other = &array2;
for (int i = 0; i < 100; i++)
{
current->Each(
[&other](const Array2D<char>& array, Index2D index)
{
int neighbors = array.GetNeighbors('#', index.x, index.y, true);
if (array[index] == '#')
{
if (neighbors < 2 || neighbors > 3)
{
(*other)[index] = '.';
}
else
{
(*other)[index] = '#';
}
}
else if (array[index] == '.')
{
if (neighbors == 3)
{
(*other)[index] = '#';
}
else
{
(*other)[index] = '.';
}
}
});
std::swap(current, other);
}
return current->Count('#');
}
OUTPUT2(input)
{
Array2D<char> array1 = input;
Array2D<char> array2 = input;
Array2D<char>* current = &array1;
Array2D<char>* other = &array2;
array1[Index2D{0, 0}] = '#';
array2[Index2D{0, 0}] = '#';
array1[Index2D{0, array1.height - 1}] = '#';
array2[Index2D{0, array1.height - 1}] = '#';
array1[Index2D{array1.width - 1, 0}] = '#';
array2[Index2D{array1.width - 1, 0}] = '#';
array1[Index2D{array1.width - 1, array1.height - 1}] = '#';
array2[Index2D{array1.width - 1, array1.height - 1}] = '#';
for (int i = 0; i < 100; i++)
{
current->Each(
[&other](const Array2D<char>& array, Index2D index)
{
if (index.x == 0 && index.y == 0)
return;
if (index.x == 0 && index.y == array.height - 1)
return;
if (index.x == array.width - 1 && index.y == 0)
return;
if (index.x == array.width - 1 && index.y == array.height - 1)
return;
int neighbors = array.GetNeighbors('#', index.x, index.y, true);
if (array[index] == '#')
{
if (neighbors < 2 || neighbors > 3)
{
(*other)[index] = '.';
}
else
{
(*other)[index] = '#';
}
}
else if (array[index] == '.')
{
if (neighbors == 3)
{
(*other)[index] = '#';
}
else
{
(*other)[index] = '.';
}
}
});
std::swap(current, other);
}
return current->Count('#');
}
}
+272
View File
@@ -0,0 +1,272 @@
#include "common/aoc.h"
namespace y2015::day19
{
struct Input
{
std::multimap<std::string, std::string> conversions;
std::string molecule;
};
REGISTER_DAY(2015, Day19, Input, int);
REGISTER_TEST_EXAMPLE(2015, Day19, ExampleInput, 1, 7);
REGISTER_TEST(2015, Day19, Input, 1, 576);
// REGISTER_TEST_EXAMPLE(2015, Day19, ExampleInput, 2, 6);
REGISTER_TEST(2015, Day19, Input, 2, 207);
READ_INPUT(input)
{
Input i;
std::string str;
while (getline(input, str))
{
if (str.empty())
break;
std::string from;
std::string to;
std::stringstream ss{str};
ss >> from >> "=>" >> to;
i.conversions.emplace(from, to);
}
getline(input, i.molecule);
return i;
}
std::vector<size_t> FindAll(const std::string& str, const std::string& find)
{
std::vector<size_t> positions;
size_t pos = str.find(find);
while (pos != std::string::npos)
{
positions.emplace_back(pos);
pos = str.find(find, pos + 1);
}
return positions;
}
bool IsAtom(const std::string& sv)
{
std::regex regex{"^(e|[A-Z][a-z]?)$"};
return std::regex_match(sv, regex);
}
std::string Prettify(const std::string& molecule)
{
std::string result = molecule;
for (size_t i = 0; i < result.size(); i++)
{
if (Helper::StartsWith(result, "Rn", i))
{
result.replace(i, 2, "(");
i--;
}
else if (Helper::StartsWith(result, "Ar", i))
{
result.replace(i, 2, ")");
i--;
}
else if (Helper::StartsWith(result, "Y", i))
{
result.replace(i, 1, ",");
}
}
return result;
}
std::pair<std::string, int> Solve(const std::string& molecule,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization);
void Solve(std::string& molecule,
int& steps,
size_t& offset,
size_t pos,
size_t size,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
std::string toReduce = molecule.substr(pos, size);
auto [solveStr, solveSteps] = Solve(toReduce, conversions, memoization);
Helper::Replace(molecule, toReduce.size(), solveStr, pos);
steps += solveSteps;
offset -= toReduce.size() - solveStr.size();
}
void SolveRnAr(std::string& molecule,
int& steps,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
// Solve all parts between Rn and Ar
int stack = 0;
size_t position = 0;
for (size_t i = 0; i < molecule.size(); i++)
{
if (Helper::StartsWith(molecule, "Rn", i))
{
if (stack == 0)
position = i + 2;
i++;
stack++;
}
else if (Helper::StartsWith(molecule, "Ar", i))
{
stack--;
if (stack == 0)
{
Solve(molecule, steps, i, position, i - position, conversions, memoization);
}
i++;
}
}
}
bool SolveY(std::string& molecule,
int& steps,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
// Reduce all parts split by Y
int stack = 0;
size_t position = 0;
bool hasY = false;
for (size_t i = 0; i < molecule.size(); i++)
{
if (Helper::StartsWith(molecule, "Rn", i))
stack++;
else if (Helper::StartsWith(molecule, "Ar", i))
stack--;
if (Helper::StartsWith(molecule, "Y", i))
{
if (stack != 0)
continue;
hasY = true;
Solve(molecule, steps, i, position, i - position, conversions, memoization);
position = i + 1;
}
}
if (hasY)
{
size_t i = 0;
Solve(molecule, steps, i, position, molecule.size(), conversions, memoization);
return true;
}
return false;
}
void SolveAr(std::string& molecule,
int& steps,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
// Reduce all parts ending with Ar (except the last one)
for (size_t i = 0; i < molecule.size(); i++)
{
if (Helper::StartsWith(molecule, "Ar", i) && i != molecule.size() - 2)
{
Solve(molecule, steps, i, 0, i + 2, conversions, memoization);
}
}
}
std::pair<std::string, int> SolveToAtom(const std::string& molecule,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
if (IsAtom(molecule))
return {molecule, 0};
auto it = memoization.find(molecule);
if (it != memoization.end())
return it->second;
int steps = std::numeric_limits<int>::max();
std::string result = ".";
for (const auto& [from, to] : conversions)
{
std::vector<size_t> positions = FindAll(molecule, from);
for (const auto& pos : positions)
{
std::string moleculeCpy = molecule;
moleculeCpy.replace(pos, from.size(), to);
auto [solveStr, solveSteps] = SolveToAtom(moleculeCpy, conversions, memoization);
if (solveStr == ".")
continue;
if (solveSteps < steps)
{
steps = solveSteps;
result = solveStr;
}
}
}
memoization[molecule] = {result, steps + 1};
return {result, steps + 1};
}
void SolveToAtom(std::string& molecule,
int& steps,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
// Reduce the rest
auto [solveStr, solveSteps] = SolveToAtom(molecule, conversions, memoization);
if (solveStr == ".")
{
std::cout << "No solution found for: " << molecule << std::endl;
}
Helper::Replace(molecule, molecule.size(), solveStr, 0);
steps += solveSteps;
}
std::pair<std::string, int> Solve(const std::string& molecule,
const std::multimap<std::string, std::string>& conversions,
std::map<std::string, std::pair<std::string, int>>& memoization)
{
if (IsAtom(molecule))
return {molecule, 0};
std::string result = molecule;
int steps = 0;
SolveRnAr(result, steps, conversions, memoization);
if (SolveY(result, steps, conversions, memoization))
return {result, steps};
SolveAr(result, steps, conversions, memoization);
SolveToAtom(result, steps, conversions, memoization);
return {result, steps};
}
OUTPUT1(input)
{
std::set<std::string> uniques;
for (const auto& [from, to] : input.conversions)
{
std::vector<size_t> positions = FindAll(input.molecule, from);
for (const auto& pos : positions)
{
std::string str = input.molecule;
Helper::Replace(str, from.size(), to, pos);
uniques.emplace(str);
}
}
return uniques.size();
}
OUTPUT2(input)
{
std::multimap<std::string, std::string> reverse;
for (const auto& [from, to] : input.conversions)
{
reverse.emplace(to, from);
}
std::map<std::string, std::pair<std::string, int>> memoization;
return Solve(input.molecule, reverse, memoization).second;
}
}
+52
View File
@@ -0,0 +1,52 @@
#include "common/aoc.h"
namespace y2015::day20
{
REGISTER_DAY(2015, Day20, int, int);
REGISTER_TEST_EXAMPLE(2015, Day20, ExampleInput, 1, 8);
REGISTER_TEST(2015, Day20, Input, 1, 776160);
REGISTER_TEST_EXAMPLE(2015, Day20, ExampleInput, 2, 8);
REGISTER_TEST(2015, Day20, Input, 2, 786240);
READ_INPUT(input)
{
int i = 0;
input >> i;
return i;
}
int Solve(int input, int visits, int gifts)
{
// Assumption is that the solution can be found in 'limit' amount houses
int limit = 1'000'000;
if (visits == -1)
visits = limit;
std::vector<int> data(limit, 0);
for (int i = 1; i < limit; i++)
{
for (int j = 1; j <= visits; j++)
{
if (i * j - 1 >= limit)
break;
data[i * j - 1] += i * gifts;
}
}
for (int i = 0; i < data.size(); i++)
{
if (data[i] > input)
return i + 1;
}
return 0;
}
OUTPUT1(input)
{
return Solve(input, -1, 10);
}
OUTPUT2(input)
{
return Solve(input, 50, 11);
}
}
+118
View File
@@ -0,0 +1,118 @@
#include "common/aoc.h"
namespace y2015::day21
{
struct Entity
{
int hp;
int dmg;
int armor;
};
struct Item
{
int cost;
int dmg;
int armor;
};
REGISTER_DAY(2015, Day21, Entity, int);
REGISTER_TEST(2015, Day21, Input, 1, 91);
REGISTER_TEST(2015, Day21, Input, 2, 158);
READ_INPUT(input)
{
Entity monster;
input >> "Hit Points: " >> monster.hp >> "\n";
input >> "Damage: " >> monster.dmg >> "\n";
input >> "Armor: " >> monster.armor >> "\n";
return monster;
}
bool Win(Entity player, Entity monster)
{
int playerDmgPerRound = std::max(1, (player.dmg - monster.armor));
int monsterDmgPerRound = std::max(1, (monster.dmg - player.armor));
int i = 0;
while (true)
{
if (i % 2 == 0)
{
monster.hp -= playerDmgPerRound;
if (monster.hp <= 0)
return true;
}
else
{
player.hp -= monsterDmgPerRound;
if (player.hp <= 0)
return false;
}
i++;
}
}
std::vector<Item> weapons{Item{8, 4, 0}, Item{10, 5, 0}, Item{25, 6, 0}, Item{40, 7, 0}, Item{74, 8, 0}};
std::vector<Item> armors{
Item{13, 0, 1}, Item{31, 0, 2}, Item{53, 0, 3}, Item{75, 0, 4}, Item{102, 0, 5}, Item{0, 0, 0}};
std::vector<Item> rings{Item{25, 0, 1},
Item{50, 0, 2},
Item{100, 0, 3},
Item{20, 0, 1},
Item{40, 0, 2},
Item{80, 0, 3},
Item{0, 0, 0},
Item{0, 0, 0}};
OUTPUT1(input)
{
int minCost = std::numeric_limits<int>::max();
for (auto& weapon : weapons)
{
for (auto& armor : armors)
{
for (int i = 0; i < rings.size(); i++)
{
for (int j = i + 1; j < rings.size(); j++)
{
int cost = weapon.cost + armor.cost + rings[i].cost + rings[j].cost;
int dmgStat = weapon.dmg + armor.dmg + rings[i].dmg + rings[j].dmg;
int armorStat = weapon.armor + armor.armor + rings[i].armor + rings[j].armor;
if (cost > minCost)
continue;
if (Win(Entity{100, dmgStat, armorStat}, input))
minCost = cost;
}
}
}
}
return minCost;
}
OUTPUT2(input)
{
int maxCost = 0;
for (auto& weapon : weapons)
{
for (auto& armor : armors)
{
for (int i = 0; i < rings.size(); i++)
{
for (int j = i + 1; j < rings.size(); j++)
{
int cost = weapon.cost + armor.cost + rings[i].cost + rings[j].cost;
int dmgStat = weapon.dmg + armor.dmg + rings[i].dmg + rings[j].dmg;
int armorStat = weapon.armor + armor.armor + rings[i].armor + rings[j].armor;
if (cost < maxCost)
continue;
if (!Win(Entity{100, dmgStat, armorStat}, input))
maxCost = cost;
}
}
}
}
return maxCost;
}
}
+164
View File
@@ -0,0 +1,164 @@
#include "common/aoc.h"
namespace y2015::day22
{
struct Player
{
int hp;
int armor;
int mana;
};
struct Monster
{
int hp;
int dmg;
};
REGISTER_DAY(2015, Day22, Monster, int);
REGISTER_TEST_EXAMPLE(2015, Day22, ExampleInput, 1, 212);
REGISTER_TEST(2015, Day22, Input, 1, 900);
REGISTER_TEST_EXAMPLE(2015, Day22, ExampleInput, 2, 212);
REGISTER_TEST(2015, Day22, Input, 2, 1216);
READ_INPUT(input)
{
Monster monster;
input >> "Hit Points: " >> monster.hp >> "\n";
input >> "Damage: " >> monster.dmg >> "\n";
return monster;
}
struct Spell
{
int cost;
int timer;
int dmg;
int armor;
int manaGain;
int heal;
};
struct State
{
Player player;
Monster monster;
std::vector<int> spellTimers;
bool operator<(const State& other) const
{
if (player.hp != other.player.hp)
return player.hp < other.player.hp;
if (player.armor != other.player.armor)
return player.armor < other.player.armor;
if (player.mana != other.player.mana)
return player.mana < other.player.mana;
if (monster.hp != other.monster.hp)
return monster.hp < other.monster.hp;
if (monster.dmg != other.monster.dmg)
return monster.dmg < other.monster.dmg;
return spellTimers < other.spellTimers;
}
};
// clang-format off
// cost timer dmg armor manaGain heal
const std::vector<Spell> spells{Spell{53, 1, 4, 0, 0, 0},
Spell{73, 1, 2, 0, 0, 2},
Spell{113, 6, 0, 7, 0, 0},
Spell{173, 6, 3, 0, 0, 0},
Spell{229, 5, 0, 0, 101, 0}};
// clang-format-on
void ApplyEffects(State& state)
{
for (int i = 0; i < state.spellTimers.size(); i++)
{
if (state.spellTimers[i] == 0)
continue;
const auto& spell = spells[i];
state.spellTimers[i]--;
state.monster.hp -= spell.dmg;
state.player.hp += spell.heal;
state.player.mana += spell.manaGain;
if (state.spellTimers[i] == 0)
state.player.armor -= spell.armor;
}
}
std::pair<bool, int> PlayerTurn(State state, bool hardmode, std::map<State, std::pair<bool, int>>& memoization)
{
// Apply rules at start of turn
if (hardmode)
state.player.hp--;
if (state.player.hp <= 0)
return {false, 0};
ApplyEffects(state);
if (state.monster.hp <= 0)
return {true, 0};
auto it = memoization.find(state);
if (it != memoization.end())
return it->second;
bool canWin = false;
int minManaCost = std::numeric_limits<int>::max();
for (int i = 0; i < spells.size(); i++)
{
// Spell is already active
if (state.spellTimers[i] > 0)
continue;
const auto& spell = spells[i];
if (state.player.mana < spell.cost)
continue;
// Cast spell
State newState = state;
newState.spellTimers[i] = spell.timer;
newState.player.mana -= spell.cost;
newState.player.armor += spell.armor;
// Boss turn
ApplyEffects(newState);
if (newState.monster.hp <= 0)
{
if (spell.cost < minManaCost)
{
minManaCost = spell.cost;
canWin = true;
}
continue;
}
newState.player.hp -= std::max(1, newState.monster.dmg - newState.player.armor);
// Player turn
auto result = PlayerTurn(newState, hardmode, memoization);
if (result.first && result.second + spell.cost < minManaCost)
{
canWin = true;
minManaCost = result.second + spell.cost;
}
}
memoization[state] = {canWin, minManaCost};
return {canWin, minManaCost};
}
OUTPUT1(input)
{
std::map<State, std::pair<bool, int>> memoization;
return PlayerTurn(State{Player{50, 0, 500}, input, {0, 0, 0, 0, 0}}, false, memoization).second;
}
OUTPUT2(input)
{
std::map<State, std::pair<bool, int>> memoization;
return PlayerTurn(State{Player{50, 0, 500}, input, {0, 0, 0, 0, 0}}, true, memoization).second;
}
}
+122
View File
@@ -0,0 +1,122 @@
#include "common/aoc.h"
namespace y2015::day23
{
enum class Operation
{
Half,
Triple,
Increment,
Jump,
JumpIfEven,
JumpIfOne,
};
struct Instruction
{
Operation operation;
char reg;
int argument;
};
REGISTER_DAY(2015, Day23, std::vector<Instruction>, uint64_t);
REGISTER_TEST_EXAMPLE(2015, Day23, ExampleInput, 1, 2);
REGISTER_TEST(2015, Day23, Input, 1, 255);
REGISTER_TEST_EXAMPLE(2015, Day23, ExampleInput, 2, 2);
REGISTER_TEST(2015, Day23, Input, 2, 334);
READ_INPUT(input)
{
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
std::stringstream ss{str};
std::string s;
char c;
ss >> s;
// std::cout << s << std::endl;
if (s == "hlf")
{
instruction.operation = Operation::Half;
ss >> instruction.reg;
}
else if (s == "tpl")
{
instruction.operation = Operation::Triple;
ss >> instruction.reg;
}
else if (s == "inc")
{
instruction.operation = Operation::Increment;
ss >> instruction.reg;
}
else if (s == "jmp")
{
instruction.operation = Operation::Jump;
ss >> instruction.argument;
}
else if (s == "jie")
{
instruction.operation = Operation::JumpIfEven;
ss >> instruction.reg >> ", " >> instruction.argument;
}
else if (s == "jio")
{
instruction.operation = Operation::JumpIfOne;
ss >> instruction.reg >> ", " >> instruction.argument;
}
vec.emplace_back(instruction);
}
return vec;
}
int64_t Run(const std::vector<Instruction>& instructions, std::map<char, uint64_t> registers)
{
size_t pc = 0;
while (pc < instructions.size())
{
const auto& instruction = instructions[pc];
Operation op = instruction.operation;
switch (op)
{
case Operation::Half:
registers[instruction.reg] = registers[instruction.reg] / 2;
break;
case Operation::Triple:
registers[instruction.reg] = registers[instruction.reg] * 3;
break;
case Operation::Increment:
registers[instruction.reg]++;
break;
case Operation::Jump:
pc += instruction.argument - 1;
break;
case Operation::JumpIfEven:
if (registers[instruction.reg] % 2 == 0)
pc += instruction.argument - 1;
break;
case Operation::JumpIfOne:
if (registers[instruction.reg] == 1)
pc += instruction.argument - 1;
break;
}
pc++;
}
return registers['b'];
}
OUTPUT1(input)
{
return Run(input, std::map<char, uint64_t>{});
}
OUTPUT2(input)
{
std::map<char, uint64_t> registers;
registers['a'] = 1;
return Run(input, registers);
}
}
+137
View File
@@ -0,0 +1,137 @@
#include "common/aoc.h"
namespace y2015::day24
{
REGISTER_DAY(2015, Day24, std::vector<int>, uint64_t);
REGISTER_TEST_EXAMPLE(2015, Day24, ExampleInput, 1, 99);
REGISTER_TEST(2015, Day24, Input, 1, 11266889531);
REGISTER_TEST_EXAMPLE(2015, Day24, ExampleInput, 2, 44);
REGISTER_TEST(2015, Day24, Input, 2, 77387711);
READ_INPUT(input)
{
return Input::ReadInts(input);
}
void GetAllSumCombinations(std::vector<int>& listLeft,
std::vector<int>& currentList,
std::vector<std::vector<int>>& result,
int sumLeft,
size_t offset)
{
if (sumLeft < 0)
return;
if (sumLeft == 0)
{
result.emplace_back(currentList);
return;
}
for (size_t i = offset; i < listLeft.size(); i++)
{
if (listLeft[i] == 0)
continue;
if (sumLeft < listLeft[i])
break;
currentList.emplace_back(listLeft[i]);
int number = listLeft[i];
listLeft[i] = 0;
GetAllSumCombinations(listLeft, currentList, result, sumLeft - number, i + 1);
currentList.pop_back();
listLeft[i] = number;
}
}
std::vector<std::vector<int>> GetAllSumCombinations(std::vector<int> list, int sum, int groups)
{
std::vector<int> currentList{};
std::vector<std::vector<int>> result{};
GetAllSumCombinations(list, currentList, result, sum / groups, 0);
return result;
}
bool Overlap(const std::vector<int>& list1, const std::vector<int>& list2)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1 < list1.size() && i2 < list2.size())
{
if (list1[i1] == list2[i2])
return true;
if (list1[i1] < list2[i2])
i1++;
else
i2++;
}
return false;
}
bool Overlap(const std::vector<int>& combination, const std::vector<const std::vector<int>*>& combinationList)
{
for (const auto& elem : combinationList)
{
if (Overlap(combination, *elem))
return true;
}
return false;
}
bool HasSolution(const std::vector<std::vector<int>>& sumCombinations,
const std::vector<const std::vector<int>*>& list,
size_t offset,
int groupsLeft)
{
for (size_t i = offset; i < sumCombinations.size(); i++)
{
if (Overlap(sumCombinations[i], list))
continue;
if (groupsLeft == 1)
return true;
std::vector<const std::vector<int>*> newList = list;
newList.emplace_back(&sumCombinations[i]);
if (HasSolution(sumCombinations, newList, i + 1, groupsLeft - 1))
return true;
}
return false;
}
uint64_t Solve(const std::vector<int>& list, int groups)
{
int sum = Helper::Sum<int>(list);
std::vector<std::vector<int>> sumCombinations = GetAllSumCombinations(list, sum, groups);
size_t minSize = std::numeric_limits<size_t>::max();
for (size_t i = 0; i < sumCombinations.size(); i++)
{
minSize = std::min(minSize, sumCombinations[i].size());
}
uint64_t minProd = std::numeric_limits<uint64_t>::max();
for (size_t i = 0; i < sumCombinations.size(); i++)
{
if (sumCombinations[i].size() != minSize)
continue;
size_t product = Helper::Product<uint64_t>(sumCombinations[i]);
if (product >= minProd)
continue;
if (HasSolution(sumCombinations, {&sumCombinations[i]}, 0, groups - 1))
minProd = product;
}
return minProd;
}
OUTPUT1(input)
{
return Solve(input, 3);
}
OUTPUT2(input)
{
return Solve(input, 4);
}
}
+38
View File
@@ -0,0 +1,38 @@
#include "common/aoc.h"
namespace y2015::day25
{
using Pair = std::pair<int, int>;
REGISTER_DAY(2015, Day25, Pair, int);
REGISTER_TEST_EXAMPLE(2015, Day25, ExampleInput, 1, 7981243);
REGISTER_TEST(2015, Day25, Input, 1, 8997277);
REGISTER_TEST_EXAMPLE(2015, Day25, ExampleInput, 2, 0);
REGISTER_TEST(2015, Day25, Input, 2, 0);
READ_INPUT(input)
{
int i1;
int i2;
input >> "To continue, please consult the code grid in the manual. Enter the code at row " >> i2 >> ", column " >>
i1;
return std::pair{i1, i2};
}
int GetPower(const std::pair<int, int>& coordinate)
{
return (coordinate.first + coordinate.second - 1) * (coordinate.first + coordinate.second - 1 + 1) / 2 + 1 -
coordinate.second;
}
OUTPUT1(input)
{
return Helper::FastExponentiation(20151125, 252533, GetPower(input) - 1, 33554393);
}
OUTPUT2(input)
{
return 0;
}
}
+73
View File
@@ -0,0 +1,73 @@
#include "common/aoc.h"
namespace y2016::day01
{
struct Move
{
char r;
int count;
};
REGISTER_DAY(2016, Day01, std::vector<Move>, int);
REGISTER_TEST_EXAMPLE(2016, Day01, ExampleInput, 1, 8);
REGISTER_TEST(2016, Day01, Input, 1, 271);
REGISTER_TEST_EXAMPLE(2016, Day01, ExampleInput, 2, 4);
REGISTER_TEST(2016, Day01, Input, 2, 153);
READ_INPUT(input)
{
std::vector<Move> vec;
std::string str;
while (getline(input, str, ' '))
{
Move move;
move.r = str[0];
move.count = std::strtol(&str[1], nullptr, 10);
vec.emplace_back(move);
}
return vec;
}
OUTPUT1(input)
{
Index2D dir{1, 0};
Index2D pos{0, 0};
for (int i = 0; i < input.size(); i++)
{
if (input[i].r == 'R')
dir.RotateCW();
else
dir.RotateCCW();
pos = pos + dir * input[i].count;
}
return Helper::ManhattanDistance(pos, Index2D{0, 0});
}
OUTPUT2(input)
{
Index2D dir{1, 0};
Index2D pos{0, 0};
std::set<Index2D> visited;
visited.emplace(pos);
for (int i = 0; i < input.size(); i++)
{
if (input[i].r == 'R')
dir.RotateCW();
else
dir.RotateCCW();
for (int j = 0; j < input[i].count; j++)
{
pos = pos + dir;
if (visited.count(pos) != 0)
{
return Helper::ManhattanDistance(pos, Index2D{0, 0});
}
visited.emplace(pos);
}
}
return 0;
}
}
+126
View File
@@ -0,0 +1,126 @@
#include "common/aoc.h"
namespace y2016::day02
{
REGISTER_DAY(2016, Day02, std::vector<std::string>, std::string);
REGISTER_TEST_EXAMPLE(2016, Day02, ExampleInput, 1, "1985");
REGISTER_TEST(2016, Day02, Input, 1, "14894");
REGISTER_TEST_EXAMPLE(2016, Day02, ExampleInput, 2, "5DB3");
REGISTER_TEST(2016, Day02, Input, 2, "26B96");
READ_INPUT(input)
{
std::vector<std::string> vec;
std::string str;
while (getline(input, str))
{
vec.emplace_back(str);
}
return vec;
}
char IndexToChar1(Index2D index)
{
return (index.x + index.y * 3) + '1';
}
char IndexToChar2(Index2D index)
{
if (index.y == 0)
return '1';
if (index.y == 1)
return '2' + index.x - 1;
if (index.y == 2)
return '5' + index.x;
if (index.y == 3)
return 'A' + index.x - 1;
if (index.y == 4)
return 'D';
return 'X';
}
void ClampX(Index2D& pos)
{
if (pos.y == 0 || pos.y == 4)
pos.x = std::clamp(pos.x, 2, 2);
if (pos.y == 1 || pos.y == 3)
pos.x = std::clamp(pos.x, 1, 3);
if (pos.y == 2)
pos.x = std::clamp(pos.x, 0, 4);
}
void ClampY(Index2D& pos)
{
if (pos.x == 0 || pos.x == 4)
pos.y = std::clamp(pos.y, 2, 2);
if (pos.x == 1 || pos.x == 3)
pos.y = std::clamp(pos.y, 1, 3);
if (pos.x == 2)
pos.y = std::clamp(pos.y, 0, 4);
}
OUTPUT1(input)
{
Index2D pos{1, 1};
std::string code = "";
for (const auto& instructions : input)
{
for (const auto& instruction : instructions)
{
switch (instruction)
{
case 'R':
pos.x++;
break;
case 'L':
pos.x--;
break;
case 'U':
pos.y--;
break;
case 'D':
pos.y++;
break;
}
pos.x = std::clamp(pos.x, 0, 2);
pos.y = std::clamp(pos.y, 0, 2);
}
code += IndexToChar1(pos);
}
return code;
}
OUTPUT2(input)
{
Index2D pos{0, 2};
std::string code = "";
for (const auto& instructions : input)
{
for (const auto& instruction : instructions)
{
switch (instruction)
{
case 'R':
pos.x++;
ClampX(pos);
break;
case 'L':
pos.x--;
ClampX(pos);
break;
case 'U':
pos.y--;
ClampY(pos);
break;
case 'D':
pos.y++;
ClampY(pos);
break;
}
}
code += IndexToChar2(pos);
}
return code;
}
}
+52
View File
@@ -0,0 +1,52 @@
#include "common/aoc.h"
namespace y2016::day03
{
REGISTER_DAY(2016, Day03, Array2D<int>, int);
REGISTER_TEST_EXAMPLE(2016, Day03, ExampleInput, 1, 2);
REGISTER_TEST(2016, Day03, Input, 1, 983);
REGISTER_TEST_EXAMPLE(2016, Day03, ExampleInput, 2, 2);
REGISTER_TEST(2016, Day03, Input, 2, 1836);
READ_INPUT(input)
{
return Input::ReadIntsAsArray2D(input);
}
bool IsValid(const std::array<int, 3>& triangle)
{
for (int i = 0; i < 3; i++)
{
int length = triangle.at(i) + triangle.at((i + 1) % 3);
if (length <= triangle.at((i + 2) % 3))
return false;
}
return true;
}
OUTPUT1(input)
{
int count = 0;
for (int y = 0; y < input.height; y++)
{
if (IsValid({input.Get(0, y), input.Get(1, y), input.Get(2, y)}))
count++;
}
return count;
}
OUTPUT2(input)
{
int count = 0;
for (int y = 0; y < input.height; y += 3)
{
for (int x = 0; x < 3; x++)
{
if (IsValid({input.Get(x, y), input.Get(x, y + 1), input.Get(x, y + 2)}))
count++;
}
}
return count;
}
}
+109
View File
@@ -0,0 +1,109 @@
#include "common/aoc.h"
namespace y2016::day04
{
struct Room
{
std::string name;
int sectorId;
std::string checksum;
};
REGISTER_DAY(2016, Day04, std::vector<Room>, int);
REGISTER_TEST_EXAMPLE(2016, Day04, ExampleInput, 1, 1514);
REGISTER_TEST(2016, Day04, Input, 1, 278221);
REGISTER_TEST(2016, Day04, Input, 2, 267);
READ_INPUT(input)
{
std::vector<Room> vec;
std::string str;
while (getline(input, str))
{
Room room;
std::stringstream ss{str};
getline(ss, room.name, '[');
size_t pos = room.name.find_last_of('-');
room.sectorId = std::strtoll(room.name.c_str() + pos + 1, nullptr, 10);
room.name = room.name.substr(0, pos);
getline(ss, room.checksum, ']');
vec.emplace_back(room);
}
return vec;
}
struct CharCount
{
char c;
int count;
bool operator<(const CharCount& rhs) const
{
if (count != rhs.count)
return count > rhs.count;
return c < rhs.c;
}
};
bool ValidRoom(const Room& room)
{
std::array<int, 'z' - 'a' + 1> counts;
counts.fill(0);
for (auto c : room.name)
{
if (c >= 'a' && c <= 'z')
counts[c - 'a']++;
}
std::set<CharCount> mostUsed;
for (int i = 0; i < counts.size(); i++)
{
if (counts[i] > 0)
mostUsed.emplace(CharCount{(char)('a' + i), counts[i]});
}
int i = 0;
for (auto it = mostUsed.begin(); i < 5; it++, i++)
{
if (room.checksum[i] != it->c)
{
return false;
}
}
return true;
}
OUTPUT1(input)
{
int count = 0;
for (const auto& room : input)
{
if (ValidRoom(room))
count += room.sectorId;
}
return count;
}
OUTPUT2(input)
{
for (const auto& room : input)
{
if (!ValidRoom(room))
continue;
std::string newName = room.name;
for (auto& c : newName)
{
if (c >= 'a' && c <= 'z')
c = ((c - 'a') + room.sectorId) % ('z' - 'a' + 1) + 'a';
}
if (newName == "northpole-object-storage")
return room.sectorId;
}
return 0;
}
}
+61
View File
@@ -0,0 +1,61 @@
#include "common/aoc.h"
namespace y2016::day05
{
REGISTER_DAY(2016, Day05, std::string, std::string);
REGISTER_TEST(2016, Day05, Input, 1, "f97c354d");
REGISTER_TEST(2016, Day05, Input, 2, "863dde27");
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
OUTPUT1(input)
{
int i = 0;
std::string result;
while (true)
{
std::string str = input + std::to_string(i);
std::string s = Md5::Hash(str);
if (Helper::StartsWith(s, "00000"))
{
result.push_back(s[5]);
if (result.size() == 8)
return result;
}
i++;
}
return "";
}
OUTPUT2(input)
{
int i = 0;
std::string result{"XXXXXXXX"};
int replacements = 0;
for (int i = 0;; i++)
{
std::string str = input + std::to_string(i);
std::string s = Md5::Hash(str);
if (Helper::StartsWith(s, "00000"))
{
if (s[5] < '0' || s[5] > '7')
continue;
if (result[s[5] - '0'] == 'X')
{
result[s[5] - '0'] = s[6];
replacements++;
}
if (replacements == 8)
return result;
}
}
return "";
}
}
+66
View File
@@ -0,0 +1,66 @@
#include "common/aoc.h"
namespace y2016::day06
{
REGISTER_DAY(2016, Day06, Array2D<char>, std::string);
REGISTER_TEST_EXAMPLE(2016, Day06, ExampleInput, 1, "easter");
REGISTER_TEST(2016, Day06, Input, 1, "xhnqpqql");
REGISTER_TEST_EXAMPLE(2016, Day06, ExampleInput, 2, "advent");
REGISTER_TEST(2016, Day06, Input, 2, "brhailro");
READ_INPUT(input)
{
return Input::ReadArray2D(input);
}
OUTPUT1(input)
{
std::string result;
for (int x = 0; x < input.width; x++)
{
std::map<char, int> map;
for (int y = 0; y < input.height; y++)
{
map[input.Get(x, y)]++;
}
int max = 0;
char maxChar;
for (const auto& [c, count] : map)
{
if (count > max)
{
maxChar = c;
max = count;
}
}
result.push_back(maxChar);
}
return result;
}
OUTPUT2(input)
{
std::string result;
for (int x = 0; x < input.width; x++)
{
std::map<char, int> map;
for (int y = 0; y < input.height; y++)
{
map[input.Get(x, y)]++;
}
int min = std::numeric_limits<int>::max();
char minChar;
for (const auto& [c, count] : map)
{
if (count < min)
{
minChar = c;
min = count;
}
}
result.push_back(minChar);
}
return result;
}
}
+166
View File
@@ -0,0 +1,166 @@
#include "common/aoc.h"
namespace y2016::day07
{
struct IP
{
std::vector<std::string> s;
std::vector<std::string> hypernets;
friend std::ostream& operator<<(std::ostream& os, const IP& ip)
{
for (int i = 0; i < ip.s.size() + ip.hypernets.size(); i++)
{
if (i % 2 == 0)
os << ip.s[i / 2] << " ";
else
os << "[" << ip.hypernets[i / 2] << "] ";
}
return os;
}
};
REGISTER_DAY(2016, Day07, std::vector<IP>, int);
REGISTER_TEST_EXAMPLE(2016, Day07, ExampleInput, 1, 2);
REGISTER_TEST(2016, Day07, Input, 1, 115);
REGISTER_TEST_EXAMPLE(2016, Day07, ExampleInput, 2, 3);
REGISTER_TEST(2016, Day07, Input, 2, 231);
READ_INPUT(input)
{
std::vector<IP> vec;
std::string str;
while (getline(input, str))
{
IP ip;
bool readHypernet = false;
char c = '[';
size_t prevPos = 0;
size_t pos = str.find(c);
while (pos != std::string::npos)
{
if (!readHypernet)
{
c = ']';
ip.s.emplace_back(str.substr(prevPos, pos - prevPos));
}
else
{
c = '[';
ip.hypernets.emplace_back(str.substr(prevPos, pos - prevPos));
}
prevPos = pos + 1;
pos = str.find(c, prevPos);
readHypernet = !readHypernet;
}
ip.s.emplace_back(str.substr(prevPos));
vec.emplace_back(ip);
}
return vec;
}
bool HasABBA(const std::string& str)
{
for (size_t i = 0; i < str.size() - 3; i++)
{
if (str[i] == str[i + 3] && str[i + 1] == str[i + 2] && str[i] != str[i + 1])
return true;
}
return false;
}
bool SupportsTLS(const IP& ip)
{
for (const auto& hypernet : ip.hypernets)
{
if (HasABBA(hypernet))
{
return false;
}
}
for (const auto& s : ip.s)
{
if (HasABBA(s))
{
return true;
}
}
return false;
}
std::vector<std::pair<char, char>> GetABAs(const std::string& str)
{
std::vector<std::pair<char, char>> result;
for (size_t i = 0; i < str.size() - 2; i++)
{
if (str[i] == str[i + 2] && str[i] != str[i + 1])
result.emplace_back(str[i], str[i + 1]);
}
return result;
}
bool HasABA(const std::string& str, char c1, char c2)
{
for (size_t i = 0; i < str.size() - 2; i++)
{
if (str[i] == c1 && str[i + 1] == c2 && str[i + 2] == c1)
return true;
}
return false;
}
bool HasABA(const std::vector<std::string>& hypernets, char c1, char c2)
{
for (const auto& hypernet : hypernets)
{
if (HasABA(hypernet, c1, c2))
return true;
}
return false;
}
bool SupportsSSL(const IP& ip)
{
for (const auto& s : ip.s)
{
std::vector<std::pair<char, char>> abas = GetABAs(s);
for (const auto& aba : abas)
{
if (HasABA(ip.hypernets, aba.second, aba.first))
{
return true;
}
}
}
return false;
}
OUTPUT1(input)
{
int count = 0;
for (const auto& ip : input)
{
if (SupportsTLS(ip))
{
count++;
}
}
return count;
}
OUTPUT2(input)
{
int count = 0;
for (const auto& ip : input)
{
if (SupportsSSL(ip))
{
count++;
}
}
return count;
}
}
+101
View File
@@ -0,0 +1,101 @@
#include "common/aoc.h"
namespace y2016::day08
{
enum class Operation
{
Rect,
Col,
Row
};
struct Instruction
{
Operation operation;
int i1;
int i2;
};
REGISTER_DAY(2016, Day08, std::vector<Instruction>, int);
REGISTER_TEST_EXAMPLE(2016, Day08, ExampleInput, 1, 6);
REGISTER_TEST(2016, Day08, Input, 1, 115);
READ_INPUT(input)
{
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
std::stringstream ss{str};
if (str[1] == 'e') // rect
{
instruction.operation = Operation::Rect;
ss >> "rect " >> instruction.i1 >> "x" >> instruction.i2;
}
else if (str[7] == 'r') // rotate row
{
instruction.operation = Operation::Row;
ss >> "rotate row y=" >> instruction.i1 >> "by " >> instruction.i2;
}
else // rotate column
{
instruction.operation = Operation::Col;
ss >> "rotate column x=" >> instruction.i1 >> "by " >> instruction.i2;
}
vec.emplace_back(instruction);
}
return vec;
}
OUTPUT1(input)
{
Array2D<char> data{isExample ? 7 : 50, isExample ? 3 : 6, ' '};
for (const auto& instruction : input)
{
switch (instruction.operation)
{
case Operation::Rect:
for (int y = 0; y < instruction.i2; y++)
{
for (int x = 0; x < instruction.i1; x++)
{
data.Set(x, y, '#');
}
}
break;
case Operation::Row:
for (int i = 0; i < instruction.i2; i++)
{
char tmp = data.Get(data.width - 1, instruction.i1);
for (int x = data.width - 1; x > 0; x--)
{
data.Set(x, instruction.i1, data.Get(x - 1, instruction.i1));
}
data.Set(0, instruction.i1, tmp);
}
break;
case Operation::Col:
for (int i = 0; i < instruction.i2; i++)
{
char tmp = data.Get(instruction.i1, data.height - 1);
for (int y = data.height - 1; y > 0; y--)
{
data.Set(instruction.i1, y, data.Get(instruction.i1, y - 1));
}
data.Set(instruction.i1, 0, tmp);
}
break;
}
}
std::cout << data << std::endl;
return data.Count('#');
}
OUTPUT2(input)
{
// Solution is printed in Part 1
return 0;
}
}
+75
View File
@@ -0,0 +1,75 @@
#include "common/aoc.h"
namespace y2016::day09
{
REGISTER_DAY(2016, Day09, std::string, uint64_t);
REGISTER_TEST_EXAMPLE(2016, Day09, ExampleInput, 1, 18);
REGISTER_TEST(2016, Day09, Input, 1, 99145);
REGISTER_TEST_EXAMPLE(2016, Day09, ExampleInput, 2, 20);
REGISTER_TEST(2016, Day09, Input, 2, 10943094568);
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
std::pair<int, int> GetMarker(const char* str)
{
char* end;
int length = std::strtol(str, &end, 10);
int repeat = std::strtol(end + 1, nullptr, 10);
return {length, repeat};
}
uint64_t GetLength(const char* str, size_t strLength)
{
size_t i = 0;
uint64_t count = 0;
while (i < strLength)
{
if (str[i] == '(')
{
size_t close = std::strstr(str + i, ")") - str;
auto [length, repeat] = GetMarker(str + i + 1);
count += GetLength(str + close + 1, length) * repeat;
i = close + 1 + length;
}
else
{
count++;
i++;
}
}
return count;
}
OUTPUT1(input)
{
uint64_t count = 0;
size_t i = 0;
while (i < input.size())
{
if (input[i] == '(')
{
size_t close = input.find(')', i);
auto [length, repeat] = GetMarker(input.c_str() + i + 1);
count += length * repeat;
i = close + 1 + length;
}
else
{
count++;
i++;
}
}
return count;
}
OUTPUT2(input)
{
return GetLength(input.c_str(), input.size());
}
}
+146
View File
@@ -0,0 +1,146 @@
#include "common/aoc.h"
namespace y2016::day10
{
enum class Output
{
Output,
Bot
};
struct Bot
{
std::vector<int> inputs;
int lowId{-1};
int highId{-1};
Output lowOutput;
Output highOutput;
};
using Bots = std::map<int, Bot>;
REGISTER_DAY(2016, Day10, Bots, int);
REGISTER_TEST_EXAMPLE(2016, Day10, ExampleInput, 1, 2);
REGISTER_TEST(2016, Day10, Input, 1, 47);
REGISTER_TEST_EXAMPLE(2016, Day10, ExampleInput, 2, 30);
REGISTER_TEST(2016, Day10, Input, 2, 2666);
READ_INPUT(input)
{
std::map<int, Bot> map;
std::string str;
while (getline(input, str))
{
std::stringstream ss{str};
if (str[0] == 'v')
{
int value;
int id;
ss >> "value" >> value >> "goes to bot " >> id;
map[id].inputs.emplace_back(value);
}
else
{
int idFrom;
int idLow;
int idHigh;
std::string typeLow;
std::string typeHigh;
ss >> "bot " >> idFrom >> "gives low to " >> typeLow >> idLow >> "and high to " >> typeHigh >> idHigh;
Bot& from = map[idFrom];
from.lowId = idLow;
from.highId = idHigh;
if (typeLow == "bot")
from.lowOutput = Output::Bot;
else
from.lowOutput = Output::Output;
if (typeHigh == "bot")
from.highOutput = Output::Bot;
else
from.highOutput = Output::Output;
}
}
return map;
}
bool HasInput(const Bot& bot, int input1, int input2)
{
return bot.inputs.size() == 2 && ((bot.inputs[0] == input1 && bot.inputs[1] == input2) ||
(bot.inputs[0] == input2 && bot.inputs[1] == input1));
}
OUTPUT1(input)
{
int input1 = isExample ? 5 : 61;
int input2 = isExample ? 2 : 17;
std::map<int, Bot> bots = input;
while (true)
{
for (auto it = bots.begin(); it != bots.end();)
{
if (HasInput(it->second, input1, input2))
return it->first;
if (it->second.inputs.size() == 2)
{
int low = Helper::Min(it->second.inputs);
int high = Helper::Max(it->second.inputs);
if (it->second.lowOutput == Output::Bot)
{
bots[it->second.lowId].inputs.emplace_back(low);
if (HasInput(bots[it->second.lowId], input1, input2))
return it->second.lowId;
}
if (it->second.highOutput == Output::Bot)
{
bots[it->second.highId].inputs.emplace_back(high);
if (HasInput(bots[it->second.highId], input1, input2))
return it->second.highId;
}
it = bots.erase(it);
}
else
{
it++;
}
}
}
return -1;
}
OUTPUT2(input)
{
std::map<int, int> outputs;
int input1 = isExample ? 5 : 61;
int input2 = isExample ? 2 : 17;
std::map<int, Bot> bots = input;
while (!bots.empty())
{
for (auto it = bots.begin(); it != bots.end();)
{
if (it->second.inputs.size() == 2)
{
int low = Helper::Min(it->second.inputs);
int high = Helper::Max(it->second.inputs);
if (it->second.lowOutput == Output::Bot)
bots[it->second.lowId].inputs.emplace_back(low);
else
outputs[it->second.lowId] = low;
if (it->second.highOutput == Output::Bot)
bots[it->second.highId].inputs.emplace_back(high);
else
outputs[it->second.highId] = high;
it = bots.erase(it);
}
else
{
it++;
}
}
}
return outputs[0] * outputs[1] * outputs[2];
}
}
+220
View File
@@ -0,0 +1,220 @@
#include "common/aoc.h"
namespace y2016::day11
{
struct Item
{
int floorPos;
bool generator;
int id;
bool operator==(const Item& item) const
{
return floorPos == item.floorPos && id == item.id && generator == item.generator;
}
};
static int FLOORS = 4;
REGISTER_DAY(2016, Day11, std::vector<Item>, int);
REGISTER_TEST_EXAMPLE(2016, Day11, ExampleInput, 1, 11);
REGISTER_TEST(2016, Day11, Input, 1, 37);
REGISTER_TEST(2016, Day11, Input, 2, 61);
Item ParseItem(const std::string_view& str, int floorPos, std::map<std::string, int>& nameToId)
{
size_t posDash = str.find('-');
std::string name;
bool generator;
if (posDash == std::string::npos)
{
name = str.substr(0, str.find(' '));
generator = true;
}
else
{
name = str.substr(0, posDash);
generator = false;
}
auto it = nameToId.find(name);
if (it != nameToId.end())
return Item{floorPos, generator, it->second};
int size = nameToId.size();
nameToId[name] = size;
return Item{floorPos, generator, size};
}
READ_INPUT(input)
{
std::vector<Item> vec;
std::string str;
std::map<std::string, int> nameToId;
for (int i = 0; i < FLOORS; i++)
{
getline(input, str);
std::vector<std::string_view> split = Helper::Split(str, " a ");
for (size_t j = 1; j < split.size(); j++)
{
vec.emplace_back(ParseItem(split[j], i, nameToId));
}
}
return vec;
}
struct State
{
std::vector<Item> items;
int elevatorPos;
int amountOfPairs;
std::vector<std::pair<int, int>> GetPairs() const
{
// Convert the data to a format where the pairs of generator/microchip don't matter. All that matters are their
// positions
std::vector<std::pair<int, int>> pairs(amountOfPairs);
for (const auto& item : items)
{
if (item.generator)
pairs[item.id].first = item.floorPos;
else
pairs[item.id].second = item.floorPos;
}
std::sort(pairs.begin(), pairs.end());
return pairs;
}
bool operator<(const State& state) const
{
if (elevatorPos != state.elevatorPos)
return elevatorPos < state.elevatorPos;
return GetPairs() < state.GetPairs();
}
};
bool HasItem(const State& state, int floor, bool generator, int id)
{
return std::find(state.items.begin(), state.items.end(), Item{floor, generator, id}) != state.items.end();
}
bool IsValidState(const State& state)
{
for (int i = 0; i < FLOORS; i++)
{
bool hasChipNotConnected = false;
int generators = 0;
for (const auto& item : state.items)
{
if (item.floorPos != i)
continue;
if (item.generator)
{
generators++;
continue;
}
if (HasItem(state, i, true, item.id))
continue;
hasChipNotConnected = true;
}
if (hasChipNotConnected && generators > 0)
{
return false;
}
}
return true;
}
std::vector<std::pair<int, State>> Branch(const std::vector<Item>& input, const State& state)
{
std::vector<std::pair<int, State>> branches;
for (int i = -1; i <= 1; i += 2)
{
if (state.elevatorPos + i < 0 || state.elevatorPos + i > 3)
continue;
State newState = state;
newState.elevatorPos += i;
for (auto& item : newState.items)
{
if (item.floorPos != state.elevatorPos)
continue;
item.floorPos = newState.elevatorPos;
if (IsValidState(newState))
branches.emplace_back(1, newState);
item.floorPos = state.elevatorPos;
}
for (size_t i = 0; i < newState.items.size(); i++)
{
if (newState.items[i].floorPos != state.elevatorPos)
continue;
newState.items[i].floorPos = newState.elevatorPos;
for (size_t j = i + 1; j < newState.items.size(); j++)
{
if (newState.items[j].floorPos != state.elevatorPos)
continue;
newState.items[j].floorPos = newState.elevatorPos;
if (IsValidState(newState))
branches.emplace_back(1, newState);
newState.items[j].floorPos = state.elevatorPos;
}
newState.items[i].floorPos = state.elevatorPos;
}
}
return branches;
}
bool Goal(const std::vector<Item>& input, const State& state)
{
for (size_t i = 0; i < state.items.size(); i++)
{
if (state.items[i].floorPos != 3)
return false;
}
return true;
}
int Heuristic(const std::vector<Item>& input, const State& state)
{
int heuristic = 0;
int moves = 0;
for (size_t i = 0; i < state.items.size(); i++)
{
moves += (3 - state.items[i].floorPos);
}
heuristic += moves / 2;
return heuristic;
}
OUTPUT1(input)
{
int max = 0;
for (const auto& item : input)
{
max = std::max(max, item.id);
}
State state{input, 0, max + 1};
return Helper::AStar(input, state, Heuristic, Branch, Goal);
}
OUTPUT2(input)
{
std::vector<Item> items = input;
int max = 0;
for (const auto& item : items)
{
max = std::max(max, item.id);
}
items.emplace_back(Item{0, true, max + 1});
items.emplace_back(Item{0, false, max + 1});
items.emplace_back(Item{0, true, max + 2});
items.emplace_back(Item{0, false, max + 2});
State state{items, 0, max + 3};
return Helper::AStar(input, state, Heuristic, Branch, Goal);
}
}
+116
View File
@@ -0,0 +1,116 @@
#include "common/aoc.h"
namespace y2016::day12
{
enum class Operator
{
Cpy,
Inc,
Dec,
Jnz
};
struct Instruction
{
Operator op;
std::variant<char, int> arg1;
std::variant<char, int> arg2;
};
REGISTER_DAY(2016, Day12, std::vector<Instruction>, int);
REGISTER_TEST_EXAMPLE(2016, Day12, ExampleInput, 1, 42);
REGISTER_TEST(2016, Day12, Input, 1, 318007);
REGISTER_TEST_EXAMPLE(2016, Day12, ExampleInput, 2, 42);
REGISTER_TEST(2016, Day12, Input, 2, 9227661);
READ_INPUT(input)
{
std::vector<Instruction> vec;
std::string str;
while (getline(input, str))
{
Instruction instruction;
if (str[0] == 'c')
{
instruction.op = Operator::Cpy;
if (str[4] >= 'a' && str[4] <= 'd')
instruction.arg1 = str[4];
else
instruction.arg1 = (int)std::atoi(str.c_str() + 4);
instruction.arg2 = str[str.size() - 1];
}
else if (str[0] == 'i')
{
instruction.op = Operator::Inc;
instruction.arg1 = str[4];
}
else if (str[0] == 'd')
{
instruction.op = Operator::Dec;
instruction.arg1 = str[4];
}
else if (str[0] == 'j')
{
instruction.op = Operator::Jnz;
if (str[4] >= 'a' && str[4] <= 'd')
instruction.arg1 = str[4];
else
instruction.arg1 = (int)std::atoi(str.c_str() + 4);
instruction.arg2 = atoi(str.c_str() + 6);
}
vec.emplace_back(instruction);
}
return vec;
}
int Run(const std::vector<Instruction>& instructions, std::vector<int> registers)
{
size_t pc = 0;
while (pc < instructions.size())
{
switch (instructions[pc].op)
{
case Operator::Cpy:
{
int number = 0;
if (std::holds_alternative<int>(instructions[pc].arg1))
number = std::get<int>(instructions[pc].arg1);
else
number = registers[std::get<char>(instructions[pc].arg1) - 'a'];
registers[std::get<char>(instructions[pc].arg2) - 'a'] = number;
break;
}
case Operator::Inc:
registers[std::get<char>(instructions[pc].arg1) - 'a']++;
break;
case Operator::Dec:
registers[std::get<char>(instructions[pc].arg1) - 'a']--;
break;
case Operator::Jnz:
int value = 0;
if (std::holds_alternative<int>(instructions[pc].arg1))
value = std::get<int>(instructions[pc].arg1);
else
value = registers[std::get<char>(instructions[pc].arg1) - 'a'];
if (value != 0)
pc += std::get<int>(instructions[pc].arg2) - 1;
break;
}
pc++;
}
return registers[0];
}
OUTPUT1(input)
{
return Run(input, std::vector<int>(4));
}
OUTPUT2(input)
{
std::vector<int> registers(4);
registers[2] = 1;
return Run(input, registers);
}
}
+103
View File
@@ -0,0 +1,103 @@
#include "common/aoc.h"
namespace y2016::day13
{
REGISTER_DAY(2016, Day13, int, int);
REGISTER_TEST_EXAMPLE(2016, Day13, ExampleInput, 1, 11);
REGISTER_TEST(2016, Day13, Input, 1, 82);
REGISTER_TEST_EXAMPLE(2016, Day13, ExampleInput, 2, 151);
REGISTER_TEST(2016, Day13, Input, 2, 138);
READ_INPUT(input)
{
int i;
input >> i;
return i;
}
bool IsWall(int x, int y, int number)
{
int i = x * x + 3 * x + 2 * x * y + y + y * y;
i += number;
std::string str = std::bitset<32>(i).to_string();
// std::cout << str << ": " << std::count(str.begin(), str.end(), '1') % 2 << std::endl;
return std::count(str.begin(), str.end(), '1') % 2 != 0;
}
struct State
{
int x;
int y;
bool operator==(const State& state) const
{
return x == state.x && y == state.y;
}
bool operator<(const State& state) const
{
if (x != state.x)
return x < state.x;
return y < state.y;
}
friend std::ostream& operator<<(std::ostream& os, const State& state)
{
return os << "(" << state.x << ", " << state.y << ")";
}
};
std::vector<std::pair<int, State>> Branch(int input, const State& state)
{
std::vector<std::pair<int, State>> branches;
if (state.x > 0 && !IsWall(state.x - 1, state.y, input))
branches.emplace_back(1, State{state.x - 1, state.y});
if (state.y > 0 && !IsWall(state.x, state.y - 1, input))
branches.emplace_back(1, State{state.x, state.y - 1});
if (!IsWall(state.x + 1, state.y, input))
branches.emplace_back(1, State{state.x + 1, state.y});
if (!IsWall(state.x, state.y + 1, input))
branches.emplace_back(1, State{state.x, state.y + 1});
return branches;
}
bool Goal(int input, const State& state)
{
if (input == 10)
return state == State{7, 4};
else
return state == State{31, 39};
}
OUTPUT1(input)
{
State state{1, 1};
return Helper::Dijkstras(input, state, Branch, Goal);
}
OUTPUT2(input)
{
std::queue<std::pair<int, State>> queue{};
queue.emplace(0, State{1, 1});
std::set<State> visited;
while (!queue.empty())
{
std::pair<int, State> state = queue.front();
queue.pop();
std::vector<std::pair<int, State>> branches = Branch(input, state.second);
for (const auto& branch : branches)
{
if (!visited.emplace(branch.second).second)
continue;
if (state.first >= 49)
continue;
else
queue.emplace(state.first + 1, branch.second);
}
}
return visited.size();
}
}
+113
View File
@@ -0,0 +1,113 @@
#include "common/aoc.h"
namespace y2016::day14
{
REGISTER_DAY(2016, Day14, std::string, int);
REGISTER_TEST_EXAMPLE(2016, Day14, ExampleInput, 1, 22728);
REGISTER_TEST(2016, Day14, Input, 1, 15035);
REGISTER_TEST_EXAMPLE(2016, Day14, ExampleInput, 2, 22551);
REGISTER_TEST(2016, Day14, Input, 2, 19968);
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
char GetConsecutive(const std::string& s, int count)
{
for (size_t i = 0; i < s.size(); i++)
{
bool found = true;
char c = s[i];
for (int j = 1; j < count; j++)
{
if (s[i + j] != c)
{
found = false;
break;
}
}
if (found)
return c;
}
return '\0';
}
std::set<char> GetConsecutives(const std::string& s, int count)
{
std::set<char> consecutives;
for (size_t i = 0; i < s.size(); i++)
{
char c = s[i];
bool found = true;
for (int j = 0; j < count; j++)
{
if (s[i + j] != c)
{
found = false;
break;
}
}
if (found)
consecutives.emplace(c);
}
return consecutives;
}
void Hash(std::string& s, int count)
{
for (int i = 0; i < count; i++)
s = Md5::Hash(s);
}
int FindKeys(const std::string& str, int repeat)
{
std::vector<int> foundKeys;
std::map<int, char> keys;
int i = 0;
int upperLimit = std::numeric_limits<int>::max();
while (i < upperLimit)
{
keys.erase(i - 1000);
std::string hash = str + std::to_string(i);
Hash(hash, repeat + 1);
char c = GetConsecutive(hash, 3);
std::set<char> consecutives = GetConsecutives(hash, 5);
for (auto it = keys.begin(); it != keys.end();)
{
if (consecutives.count(it->second) != 0)
{
foundKeys.emplace_back(it->first);
if (foundKeys.size() == 64)
upperLimit = it->first + 1000;
it = keys.erase(it);
}
else
{
it++;
}
}
if (c != '\0')
keys.emplace(i, c);
i++;
}
std::sort(foundKeys.begin(), foundKeys.end());
return foundKeys[63];
}
OUTPUT1(input)
{
return FindKeys(input, 0);
}
OUTPUT2(input)
{
return FindKeys(input, 2016);
}
}
+58
View File
@@ -0,0 +1,58 @@
#include "common/aoc.h"
namespace y2016::day15
{
struct Disc
{
int positions;
int position;
};
REGISTER_DAY(2016, Day15, std::vector<Disc>, int64_t);
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 1, 25);
REGISTER_TEST(2016, Day15, Input, 1, 400589);
REGISTER_TEST_EXAMPLE(2016, Day15, ExampleInput, 2, 205);
REGISTER_TEST(2016, Day15, Input, 2, 3045959);
READ_INPUT(input)
{
std::vector<Disc> vec;
std::string str;
while (getline(input, str))
{
std::stringstream ss{str};
int i;
Disc disc;
ss >> "Disc #" >> i >> "has " >> disc.positions >> "positions; at time=" >> i >> ", it is at position " >>
disc.position;
vec.emplace_back(disc);
}
return vec;
}
int64_t Solve(const std::vector<Disc>& discs)
{
std::vector<int64_t> starts;
std::vector<int64_t> mods;
std::vector<int64_t> remainders(discs.size(), 0);
for (int j = 0; j < discs.size(); j++)
{
starts.emplace_back(discs[j].position + j + 1);
mods.emplace_back(discs[j].positions);
}
return Helper::ChineseRemainderTheorem(mods, remainders, starts);
}
OUTPUT1(input)
{
return Solve(input);
}
OUTPUT2(input)
{
auto discs = input;
discs.emplace_back(Disc{11, 0});
return Solve(discs);
}
}
+58
View File
@@ -0,0 +1,58 @@
#include "common/aoc.h"
namespace y2016::day16
{
REGISTER_DAY(2016, Day16, std::string, std::string);
REGISTER_TEST_EXAMPLE(2016, Day16, ExampleInput, 1, "01100");
REGISTER_TEST(2016, Day16, Input, 1, "10100011010101011");
REGISTER_TEST(2016, Day16, Input, 2, "01010001101011001");
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
std::string ReverseFlip(const std::string& str)
{
std::string reverse;
for (int i = str.size() - 1; i >= 0; i--)
{
reverse.push_back(str[i] == '1' ? '0' : '1');
}
return reverse;
}
std::string Solve(std::string str, int length)
{
while (str.size() < length)
{
str = str + "0" + ReverseFlip(str);
}
str = str.substr(0, length);
std::string checksum;
while (str.size() % 2 == 0)
{
for (int i = 0; i < str.size(); i += 2)
{
checksum.push_back(str[i] == str[i + 1] ? '1' : '0');
}
str = checksum;
checksum.clear();
}
return str;
}
OUTPUT1(input)
{
return Solve(input, isExample ? 20 : 272);
}
OUTPUT2(input)
{
return Solve(input, 35651584);
}
}
+85
View File
@@ -0,0 +1,85 @@
#include "common/aoc.h"
namespace y2016::day17
{
REGISTER_DAY(2016, Day17, std::string, std::string);
REGISTER_TEST_EXAMPLE(2016, Day17, ExampleInput, 1, "DRURDRUDDLLDLUURRDULRLDUUDDDRR");
REGISTER_TEST(2016, Day17, Input, 1, "DUDDRLRRRD");
REGISTER_TEST_EXAMPLE(2016, Day17, ExampleInput, 2, "830");
REGISTER_TEST(2016, Day17, Input, 2, "578");
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
getline(input, str);
return str;
}
struct State
{
std::string str{""};
int x{0};
int y{0};
};
bool IsOpen(char c)
{
return c >= 'b' && c <= 'f';
}
void Branch(const State& state, std::queue<State>& queue)
{
std::string hash = Md5::Hash(state.str);
if (state.y > 0 && IsOpen(hash[0]))
queue.emplace(State{state.str + "U", state.x, state.y - 1});
if (state.y < 3 && IsOpen(hash[1]))
queue.emplace(State{state.str + "D", state.x, state.y + 1});
if (state.x > 0 && IsOpen(hash[2]))
queue.emplace(State{state.str + "L", state.x - 1, state.y});
if (state.x < 3 && IsOpen(hash[3]))
queue.emplace(State{state.str + "R", state.x + 1, state.y});
}
bool IsGoal(const State& state)
{
return state.x == 3 && state.y == 3;
}
OUTPUT1(input)
{
std::queue<State> queue;
queue.emplace(State{input, 0, 0});
while (!queue.empty())
{
State state = queue.front();
queue.pop();
if (IsGoal(state))
return state.str.substr(input.size());
Branch(state, queue);
}
return "";
}
OUTPUT2(input)
{
std::queue<State> queue;
queue.emplace(State{input, 0, 0});
int longest = 0;
while (!queue.empty())
{
State state = queue.front();
queue.pop();
if (IsGoal(state))
{
longest = state.str.size() - input.size();
continue;
}
Branch(state, queue);
}
return std::to_string(longest);
}
}
+57
View File
@@ -0,0 +1,57 @@
#include "common/aoc.h"
namespace y2016::day18
{
REGISTER_DAY(2016, Day18, std::string, int);
REGISTER_TEST_EXAMPLE(2016, Day18, ExampleInput, 1, 38);
REGISTER_TEST(2016, Day18, Input, 1, 1913);
REGISTER_TEST_EXAMPLE(2016, Day18, ExampleInput, 2, 1935478);
REGISTER_TEST(2016, Day18, Input, 2, 19993564);
READ_INPUT(input)
{
std::string str;
getline(input, str);
return str;
}
int Solve(const std::string& str, int rows)
{
int safes = std::count(str.begin(), str.end(), '.');
std::vector<char> row(str.size() + 2, false);
for (int i = 0; i < str.size(); i++)
row[i + 1] = str[i] == '^';
for (int i = 1; i < rows; i++)
{
std::vector<char> newRow(row.size(), false);
for (int j = 1; j < newRow.size() - 1; j++)
{
bool isTrap = false;
if (row[j - 1] && row[j] && !row[j + 1])
newRow[j] = true;
else if (!row[j - 1] && row[j] && row[j + 1])
newRow[j] = true;
else if (row[j - 1] && !row[j] && !row[j + 1])
newRow[j] = true;
else if (!row[j - 1] && !row[j] && row[j + 1])
newRow[j] = true;
else
safes++;
}
row = newRow;
}
return safes;
}
OUTPUT1(input)
{
return Solve(input, isExample ? 10 : 40);
}
OUTPUT2(input)
{
return Solve(input, 400000);
}
}
+69
View File
@@ -0,0 +1,69 @@
#include "common/aoc.h"
namespace y2016::day19
{
REGISTER_DAY(2016, Day19, int, int);
REGISTER_TEST_EXAMPLE(2016, Day19, ExampleInput, 1, 3);
REGISTER_TEST(2016, Day19, Input, 1, 1842613);
REGISTER_TEST_EXAMPLE(2016, Day19, ExampleInput, 2, 2);
REGISTER_TEST(2016, Day19, Input, 2, 1424135);
READ_INPUT(input)
{
int i;
input >> i;
return i;
}
OUTPUT1(input)
{
std::vector<int> elves(input, 0);
for (int i = 0; i < input; i++)
{
elves[i] = i + 1;
}
int offset = 0;
while (elves.size() > 1)
{
std::vector<int> newElves;
for (int i = offset; i < elves.size(); i += 2)
{
newElves.emplace_back(elves[i]);
}
offset = (offset + (elves.size() % 2)) % 2;
elves = newElves;
}
return elves[0];
}
OUTPUT2(input)
{
std::deque<int> start;
std::deque<int> end;
for (int i = 0; i < input / 2; i++)
{
start.push_back(i + 1);
}
for (int i = input / 2; i < input; i++)
{
end.push_back(i + 1);
}
while (!start.empty())
{
end.pop_front();
end.push_back(start.front());
start.pop_front();
if (end.size() - start.size() == 2)
{
start.push_back(end.front());
end.pop_front();
}
}
return end.front();
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "common/aoc.h"
namespace y2016::day20
{
REGISTER_DAY(2016, Day20, std::vector<int>, int);
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);
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 y2016::day21
{
REGISTER_DAY(2016, Day21, std::vector<int>, int);
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);
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 y2016::day22
{
REGISTER_DAY(2016, Day22, std::vector<int>, int);
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);
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 y2016::day23
{
REGISTER_DAY(2016, Day23, std::vector<int>, int);
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);
READ_INPUT(input)
{
std::vector<int> vec;
std::string str;
while (getline(input, str))
{
}
return vec;
}
OUTPUT1(input)
{
return 0;
}
OUTPUT2(input)
{
return 0;
}
}

Some files were not shown because too many files have changed in this diff Show More