Add 2021 solutions

This commit is contained in:
Thraix
2025-11-26 23:40:34 +01:00
parent ff9bd6ce01
commit 76d824471c
51 changed files with 3314 additions and 4 deletions
-4
View File
@@ -8,13 +8,9 @@ fi
list=$(find -name "Day*.cpp" | awk -F '/' '{print $3 "/" $4}' | awk -F '.' '{print $1}' | sed 's/Day//g' | sort)
for item in $list; do
echo $item
year=$(echo $item | awk -F '/' '{print $1}')
day=$(echo $item | awk -F '/' '{print $2}')
echo "year: $year"
echo "day: $day"
dir="res/$year/day$day/input.txt"
echo $dir
if [ ! -e $dir ]; then
webitem=$(echo $day | sed 's/^0//g')
echo "Fetching $dir"
+10
View File
@@ -0,0 +1,10 @@
199
200
208
210
200
207
240
269
260
263
+6
View File
@@ -0,0 +1,6 @@
forward 5
down 5
forward 8
up 3
down 8
forward 2
+12
View File
@@ -0,0 +1,12 @@
00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010
+19
View File
@@ -0,0 +1,19 @@
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
+10
View File
@@ -0,0 +1,10 @@
0,9 -> 5,9
8,0 -> 0,8
9,4 -> 3,4
2,2 -> 2,1
7,0 -> 7,4
6,4 -> 2,0
0,9 -> 2,9
3,4 -> 1,4
0,0 -> 8,8
5,5 -> 8,2
+1
View File
@@ -0,0 +1 @@
3,4,3,1,2
+1
View File
@@ -0,0 +1 @@
16,1,2,0,4,2,7,1,2,14
+10
View File
@@ -0,0 +1,10 @@
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
+5
View File
@@ -0,0 +1,5 @@
2199943210
3987894921
9856789892
8767896789
9899965678
+10
View File
@@ -0,0 +1,10 @@
[({(<(())[]>[[{[]{<()<>>
[(()[<>])]({[<{<<[]>>(
{([(<{}[<>[]}>{[]{[(<()>
(((({<>}<{<{<>}{[]{[]{}
[[<[([]))<([[{}[[()]]]
[{[{({}]{}}([{[{{{}}([]
{<[[]]>}<{[{[{[]{()[[[]
[<(<(<(<{}))><([]([]()
<{([([[(<>()){}]>(<<{{
<{([{{}}[<[[[<>{}]]]>[]]
+10
View File
@@ -0,0 +1,10 @@
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
+7
View File
@@ -0,0 +1,7 @@
start-A
start-b
A-c
A-b
b-d
A-end
b-end
+21
View File
@@ -0,0 +1,21 @@
6,10
0,14
9,10
0,3
10,4
4,11
6,0
6,12
4,1
0,13
10,12
3,4
3,0
8,4
1,10
2,14
8,10
9,0
fold along y=7
fold along x=5
+18
View File
@@ -0,0 +1,18 @@
NNCB
CH -> B
HH -> N
CB -> H
NH -> C
HB -> C
HC -> B
HN -> C
NN -> C
BH -> H
NC -> B
NB -> B
BN -> B
BB -> N
BC -> B
CC -> N
CN -> C
+10
View File
@@ -0,0 +1,10 @@
1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581
+1
View File
@@ -0,0 +1 @@
9C0141080250320F1802104A08
+1
View File
@@ -0,0 +1 @@
target area: x=20..30, y=-10..-5
+10
View File
@@ -0,0 +1,10 @@
[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
[[[5,[2,8]],4],[5,[[9,9],0]]]
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
[[[[5,4],[7,7]],8],[[8,3],8]]
[[9,3],[[9,9],[6,[4,9]]]]
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
+136
View File
@@ -0,0 +1,136 @@
--- scanner 0 ---
404,-588,-901
528,-643,409
-838,591,734
390,-675,-793
-537,-823,-458
-485,-357,347
-345,-311,381
-661,-816,-575
-876,649,763
-618,-824,-621
553,345,-567
474,580,667
-447,-329,318
-584,868,-557
544,-627,-890
564,392,-477
455,729,728
-892,524,684
-689,845,-530
423,-701,434
7,-33,-71
630,319,-379
443,580,662
-789,900,-551
459,-707,401
--- scanner 1 ---
686,422,578
605,423,415
515,917,-361
-336,658,858
95,138,22
-476,619,847
-340,-569,-846
567,-361,727
-460,603,-452
669,-402,600
729,430,532
-500,-761,534
-322,571,750
-466,-666,-811
-429,-592,574
-355,545,-477
703,-491,-529
-328,-685,520
413,935,-424
-391,539,-444
586,-435,557
-364,-763,-893
807,-499,-711
755,-354,-619
553,889,-390
--- scanner 2 ---
649,640,665
682,-795,504
-784,533,-524
-644,584,-595
-588,-843,648
-30,6,44
-674,560,763
500,723,-460
609,671,-379
-555,-800,653
-675,-892,-343
697,-426,-610
578,704,681
493,664,-388
-671,-858,530
-667,343,800
571,-461,-707
-138,-166,112
-889,563,-600
646,-828,498
640,759,510
-630,509,768
-681,-892,-333
673,-379,-804
-742,-814,-386
577,-820,562
--- scanner 3 ---
-589,542,597
605,-692,669
-500,565,-823
-660,373,557
-458,-679,-417
-488,449,543
-626,468,-788
338,-750,-386
528,-832,-391
562,-778,733
-938,-730,414
543,643,-506
-524,371,-870
407,773,750
-104,29,83
378,-903,-323
-778,-728,485
426,699,580
-438,-605,-362
-469,-447,-387
509,732,623
647,635,-688
-868,-804,481
614,-800,639
595,780,-596
--- scanner 4 ---
727,592,562
-293,-554,779
441,611,-461
-714,465,-776
-743,427,-804
-660,-479,-426
832,-632,460
927,-485,-438
408,393,-506
466,436,-512
110,16,151
-258,-428,682
-393,719,612
-211,-452,876
808,-476,-593
-575,615,604
-485,667,467
-680,325,-822
-627,-443,-432
872,-547,-609
833,512,582
807,604,487
839,-516,451
891,-625,532
-652,-548,-490
30,-46,-14
+7
View File
@@ -0,0 +1,7 @@
..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
#..#.
#....
##..#
..#..
..###
+2
View File
@@ -0,0 +1,2 @@
Player 1 starting position: 4
Player 2 starting position: 8
+60
View File
@@ -0,0 +1,60 @@
on x=-5..47,y=-31..22,z=-19..33
on x=-44..5,y=-27..21,z=-14..35
on x=-49..-1,y=-11..42,z=-10..38
on x=-20..34,y=-40..6,z=-44..1
off x=26..39,y=40..50,z=-2..11
on x=-41..5,y=-41..6,z=-36..8
off x=-43..-33,y=-45..-28,z=7..25
on x=-33..15,y=-32..19,z=-34..11
off x=35..47,y=-46..-34,z=-11..5
on x=-14..36,y=-6..44,z=-16..29
on x=-57795..-6158,y=29564..72030,z=20435..90618
on x=36731..105352,y=-21140..28532,z=16094..90401
on x=30999..107136,y=-53464..15513,z=8553..71215
on x=13528..83982,y=-99403..-27377,z=-24141..23996
on x=-72682..-12347,y=18159..111354,z=7391..80950
on x=-1060..80757,y=-65301..-20884,z=-103788..-16709
on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856
on x=-52752..22273,y=-49450..9096,z=54442..119054
on x=-29982..40483,y=-108474..-28371,z=-24328..38471
on x=-4958..62750,y=40422..118853,z=-7672..65583
on x=55694..108686,y=-43367..46958,z=-26781..48729
on x=-98497..-18186,y=-63569..3412,z=1232..88485
on x=-726..56291,y=-62629..13224,z=18033..85226
on x=-110886..-34664,y=-81338..-8658,z=8914..63723
on x=-55829..24974,y=-16897..54165,z=-121762..-28058
on x=-65152..-11147,y=22489..91432,z=-58782..1780
on x=-120100..-32970,y=-46592..27473,z=-11695..61039
on x=-18631..37533,y=-124565..-50804,z=-35667..28308
on x=-57817..18248,y=49321..117703,z=5745..55881
on x=14781..98692,y=-1341..70827,z=15753..70151
on x=-34419..55919,y=-19626..40991,z=39015..114138
on x=-60785..11593,y=-56135..2999,z=-95368..-26915
on x=-32178..58085,y=17647..101866,z=-91405..-8878
on x=-53655..12091,y=50097..105568,z=-75335..-4862
on x=-111166..-40997,y=-71714..2688,z=5609..50954
on x=-16602..70118,y=-98693..-44401,z=5197..76897
on x=16383..101554,y=4615..83635,z=-44907..18747
off x=-95822..-15171,y=-19987..48940,z=10804..104439
on x=-89813..-14614,y=16069..88491,z=-3297..45228
on x=41075..99376,y=-20427..49978,z=-52012..13762
on x=-21330..50085,y=-17944..62733,z=-112280..-30197
on x=-16478..35915,y=36008..118594,z=-7885..47086
off x=-98156..-27851,y=-49952..43171,z=-99005..-8456
off x=2032..69770,y=-71013..4824,z=7471..94418
on x=43670..120875,y=-42068..12382,z=-24787..38892
off x=37514..111226,y=-45862..25743,z=-16714..54663
off x=25699..97951,y=-30668..59918,z=-15349..69697
off x=-44271..17935,y=-9516..60759,z=49131..112598
on x=-61695..-5813,y=40978..94975,z=8655..80240
off x=-101086..-9439,y=-7088..67543,z=33935..83858
off x=18020..114017,y=-48931..32606,z=21474..89843
off x=-77139..10506,y=-89994..-18797,z=-80..59318
off x=8476..79288,y=-75520..11602,z=-96624..-24783
on x=-47488..-1262,y=24338..100707,z=16292..72967
off x=-84341..13987,y=2429..92914,z=-90671..-1318
off x=-37810..49457,y=-71013..-7894,z=-105357..-13188
off x=-27365..46395,y=31009..98017,z=15428..76570
off x=-70369..-16548,y=22648..78696,z=-1892..86821
on x=-53470..21291,y=-120233..-33476,z=-44150..38147
off x=-93533..-4276,y=-16170..68771,z=-104985..-24507
+5
View File
@@ -0,0 +1,5 @@
#############
#...........#
###B#C#B#D###
#A#D#C#A#
#########
View File
+9
View File
@@ -0,0 +1,9 @@
v...>>.vv>
.vv>>.vv..
>>.>v>...v
>>v>>.>.v.
v>v.vv.v..
>.>>..v...
.vv..>.>v.
v.v..>>v.v
....v..v.>
+38
View File
@@ -0,0 +1,38 @@
#include "common/aoc.h"
namespace y2021::day01
{
REGISTER_DAY(2021, Day01, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2021, Day01, ExampleInput, 1, 7);
REGISTER_TEST(2021, Day01, Input, 1, 1722);
REGISTER_TEST_EXAMPLE(2021, Day01, ExampleInput, 2, 5);
REGISTER_TEST(2021, Day01, Input, 2, 1748);
READ_INPUT(input)
{
return Input::ReadInts(input);
}
OUTPUT1(input)
{
int count = 0;
for (size_t i = 0; i < input.size() - 1; i++)
{
if (input[i] < input[i + 1])
count++;
}
return count;
}
OUTPUT2(input)
{
int count = 0;
for (size_t i = 0; i < input.size() - 3; i++)
{
if (input[i] + input[i + 1] + input[i + 2] < input[i + 1] + input[i + 2] + input[i + 3])
count++;
}
return count;
}
}
+90
View File
@@ -0,0 +1,90 @@
#include "common/aoc.h"
namespace y2021::day02
{
enum class Dir
{
Forward,
Down,
Up
};
struct Move
{
Dir dir;
int amount;
};
REGISTER_DAY(2021, Day02, std::vector<Move>, int);
REGISTER_TEST_EXAMPLE(2021, Day02, ExampleInput, 1, 150);
REGISTER_TEST(2021, Day02, Input, 1, 1815044);
REGISTER_TEST_EXAMPLE(2021, Day02, ExampleInput, 2, 900);
REGISTER_TEST(2021, Day02, Input, 2, 1739283308);
READ_INPUT(input)
{
std::vector<Move> moves;
std::string str;
while (getline(input, str))
{
std::stringstream ss{str};
std::string s;
int i;
ss >> s >> i;
if (s == "forward")
moves.emplace_back(Move{Dir::Forward, i});
else if (s == "down")
moves.emplace_back(Move{Dir::Down, i});
else if (s == "up")
moves.emplace_back(Move{Dir::Up, i});
}
return moves;
}
OUTPUT1(input)
{
int x = 0;
int y = 0;
for (auto&& move : input)
{
switch (move.dir)
{
case Dir::Forward:
x += move.amount;
break;
case Dir::Down:
y += move.amount;
break;
case Dir::Up:
y -= move.amount;
break;
}
}
return x * y;
}
OUTPUT2(input)
{
int x = 0;
int y = 0;
int aim = 0;
for (auto&& move : input)
{
switch (move.dir)
{
case Dir::Forward:
x += move.amount;
y += aim * move.amount;
break;
case Dir::Down:
aim += move.amount;
break;
case Dir::Up:
aim -= move.amount;
break;
}
}
return x * y;
}
}
+94
View File
@@ -0,0 +1,94 @@
#include "common/aoc.h"
namespace y2021::day03
{
REGISTER_DAY(2021, Day03, std::set<std::string>, int);
REGISTER_TEST_EXAMPLE(2021, Day03, ExampleInput, 1, 198);
REGISTER_TEST(2021, Day03, Input, 1, 2498354);
REGISTER_TEST_EXAMPLE(2021, Day03, ExampleInput, 2, 230);
REGISTER_TEST(2021, Day03, Input, 2, 3277956);
READ_INPUT(input)
{
std::set<std::string> strings;
std::string str;
while (getline(input, str))
{
strings.emplace(str);
}
return strings;
}
OUTPUT1(input)
{
int gamma = 0;
int width = input.begin()->size();
for (int x = 0; x < width; x++)
{
size_t count = 0;
for (auto&& str : input)
{
if (str[x] == '1')
count++;
}
if (count >= input.size() / 2)
{
gamma |= BIT(width - x - 1);
}
}
int invertMask = BIT(width) - 1;
return gamma * (gamma ^ invertMask);
}
OUTPUT2(input)
{
int width = input.begin()->size();
std::set<std::string> oxygen = input;
std::set<std::string> carbon = input;
for (int i = 0; i < width; i++)
{
char mostCommon = '0';
size_t count = 0;
for (auto it = oxygen.begin(); it != oxygen.end(); it++)
{
if (it->at(i) == '1')
count++;
}
if (count * 2 >= oxygen.size())
mostCommon = '1';
for (auto it = oxygen.begin(); it != oxygen.end();)
{
if (oxygen.size() == 1)
break;
if (it->at(i) != mostCommon)
it = oxygen.erase(it);
else
it++;
}
char leastCommon = '0';
count = 0;
for (auto it = carbon.begin(); it != carbon.end(); it++)
{
if (it->at(i) == '1')
count++;
}
if (count * 2 < carbon.size())
leastCommon = '1';
for (auto it = carbon.begin(); it != carbon.end();)
{
if (carbon.size() == 1)
break;
if (it->at(i) != leastCommon)
it = carbon.erase(it);
else
it++;
}
}
int oxygenVal = Helper::BinStrToInt(*oxygen.begin());
int carbonVal = Helper::BinStrToInt(*carbon.begin());
return oxygenVal * carbonVal;
}
}
+127
View File
@@ -0,0 +1,127 @@
#include "common/aoc.h"
namespace y2021::day04
{
struct Game
{
std::vector<int> input;
std::vector<Array2D<int>> boards;
};
bool MarkAndCheck(Array2D<int>& board, int number)
{
Index2D index = board.Find(number);
if (index)
{
board[index] = -1;
// Check board is filled
bool filledX = true;
bool filledY = true;
for (int i = 0; i < 5; i++)
{
if (board.Get(i, index.y) != -1)
filledX = false;
if (board.Get(index.x, i) != -1)
filledY = false;
}
return filledX || filledY;
}
return false;
}
REGISTER_DAY(2021, Day04, Game, int);
REGISTER_TEST_EXAMPLE(2021, Day04, ExampleInput, 1, 4512);
REGISTER_TEST(2021, Day04, Input, 1, 54275);
REGISTER_TEST_EXAMPLE(2021, Day04, ExampleInput, 2, 1924);
REGISTER_TEST(2021, Day04, Input, 2, 13158);
READ_INPUT(input)
{
Game game;
std::string str;
getline(input, str);
std::stringstream ss{str};
while (getline(ss, str, ','))
{
game.input.emplace_back(atoi(str.c_str()));
}
getline(input, str);
while (!input.eof())
{
Array2D<int> array2D{5, 5};
for (int y = 0; y < 5; y++)
{
getline(input, str);
std::stringstream ss{str};
for (int x = 0; x < 5; x++)
{
int i;
ss >> i;
array2D.Set(x, y, i);
}
}
game.boards.emplace_back(array2D);
getline(input, str);
}
return game;
}
OUTPUT1(input)
{
Game game = input; // Copy the data to be able to modify it
int winner = -1;
int i = 0;
while (winner == -1)
{
int number = game.input[i];
for (auto& board : game.boards)
{
if (MarkAndCheck(board, number))
{
int total = 0;
for (auto& val : board)
{
if (val != -1)
total += val;
}
return total * number;
}
}
i++;
}
return 0;
}
OUTPUT2(input)
{
Game game = input; // Copy the data to be able to modify it
int winner = -1;
int i = 0;
while (winner == -1)
{
int number = game.input[i];
for (auto it = game.boards.begin(); it != game.boards.end();)
{
if (MarkAndCheck(*it, number))
{
if (game.boards.size() == 1)
{
int total = 0;
for (auto& val : game.boards.front())
{
if (val != -1)
total += val;
}
return total * number;
}
it = game.boards.erase(it);
}
else
it++;
}
i++;
}
return 0;
}
}
+96
View File
@@ -0,0 +1,96 @@
#include "common/aoc.h"
namespace y2021::day05
{
struct Line
{
int x1;
int y1;
int x2;
int y2;
};
REGISTER_DAY(2021, Day05, std::vector<Line>, int);
REGISTER_TEST_EXAMPLE(2021, Day05, ExampleInput, 1, 5);
REGISTER_TEST(2021, Day05, Input, 1, 5442);
REGISTER_TEST_EXAMPLE(2021, Day05, ExampleInput, 2, 12);
REGISTER_TEST(2021, Day05, Input, 2, 19571);
READ_INPUT(input)
{
std::string str;
std::vector<Line> lines;
while (getline(input, str))
{
std::stringstream ss{str};
Line line;
ss >> line.x1 >> "," >> line.y1 >> "->" >> line.x2 >> "," >> line.y2;
lines.emplace_back(line);
}
return lines;
}
OUTPUT1(input)
{
Index2D max;
for (auto& line : input)
{
max.x = std::max({max.x, line.x1, line.x2});
max.y = std::max({max.y, line.y1, line.y2});
}
Array2D<uint8_t> overlap{max.x + 1, max.y + 1};
for (auto& line : input)
{
if (line.x1 == line.x2 || line.y1 == line.y2)
{
int width = std::max(std::abs(line.x1 - line.x2), std::abs(line.y1 - line.y2)) + 1;
int deltaX = Helper::Sign(line.x2 - line.x1);
int deltaY = Helper::Sign(line.y2 - line.y1);
for (int i = 0; i < width; i++)
{
Index2D index{line.x1 + deltaX * i, line.y1 + deltaY * i};
overlap[index]++;
}
}
}
int count = 0;
overlap.Each(
[&](const Array2D<uint8_t>& overlap, const Index2D& index)
{
if (overlap[index] > 1)
count++;
});
return count;
}
OUTPUT2(input)
{
Index2D max;
for (auto& line : input)
{
max.x = std::max({max.x, line.x1, line.x2});
max.y = std::max({max.y, line.y1, line.y2});
}
Array2D<uint8_t> overlap{max.x + 1, max.y + 1};
for (auto& line : input)
{
int width = std::max(std::abs(line.x1 - line.x2), std::abs(line.y1 - line.y2)) + 1;
int deltaX = Helper::Sign(line.x2 - line.x1);
int deltaY = Helper::Sign(line.y2 - line.y1);
for (int i = 0; i < width; i++)
{
Index2D index{line.x1 + deltaX * i, line.y1 + deltaY * i};
overlap[index]++;
}
}
int count = 0;
overlap.Each(
[&](const Array2D<uint8_t>& overlap, const Index2D& index)
{
if (overlap[index] > 1)
count++;
});
return count;
}
}
+52
View File
@@ -0,0 +1,52 @@
#include "common/aoc.h"
namespace y2021::day06
{
int64_t GetPopulation(std::vector<int64_t>& lenternfishes, int days)
{
for (int i = 0; i < days; i++)
{
int64_t newBorn = lenternfishes[0];
for (size_t j = 1; j < lenternfishes.size(); j++)
{
lenternfishes[j - 1] = lenternfishes[j];
}
lenternfishes[8] = newBorn;
lenternfishes[6] += newBorn;
}
return Helper::Sum<int64_t>(lenternfishes);
}
REGISTER_DAY(2021, Day06, std::vector<int64_t>, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day06, ExampleInput, 1, 5934);
REGISTER_TEST(2021, Day06, Input, 1, 374994);
REGISTER_TEST_EXAMPLE(2021, Day06, ExampleInput, 2, 26984457539);
REGISTER_TEST(2021, Day06, Input, 2, 1686252324092);
READ_INPUT(input)
{
std::vector<int64_t> ints;
ints.resize(9);
std::string str;
while (getline(input, str, ','))
{
ints[atoi(str.c_str())]++;
}
return ints;
}
OUTPUT1(inputConst)
{
InputType input = inputConst;
return GetPopulation(input, 80);
}
OUTPUT2(inputConst)
{
InputType input = inputConst;
return GetPopulation(input, 256);
}
}
+51
View File
@@ -0,0 +1,51 @@
#include "common/aoc.h"
namespace y2021::day07
{
REGISTER_DAY(2021, Day07, std::vector<int>, int);
REGISTER_TEST_EXAMPLE(2021, Day07, ExampleInput, 1, 37);
REGISTER_TEST(2021, Day07, Input, 1, 359648);
REGISTER_TEST_EXAMPLE(2021, Day07, ExampleInput, 2, 168);
REGISTER_TEST(2021, Day07, Input, 2, 100727924);
READ_INPUT(input)
{
return Input::ReadInts(input, ',');
}
OUTPUT1(input)
{
int max = Helper::Max(input);
int min = Helper::Min(input);
int minCost = std::numeric_limits<int>::max();
for (int i = min; i < max + 1; i++)
{
int cost = 0;
for (auto num : input)
{
cost += std::abs(num - i);
}
minCost = std::min(minCost, cost);
}
return minCost;
}
OUTPUT2(input)
{
int max = Helper::Max(input);
int min = Helper::Min(input);
int minCost = std::numeric_limits<int>::max();
for (int i = min; i < max + 1; i++)
{
int cost = 0;
for (auto num : input)
{
int steps = std::abs(num - i);
cost += steps * (steps + 1) / 2;
}
minCost = std::min(minCost, cost);
}
return minCost;
}
}
+154
View File
@@ -0,0 +1,154 @@
#include "common/aoc.h"
namespace y2021::day08
{
struct Signal
{
std::vector<std::set<char>> numbers;
std::vector<std::set<char>> display;
};
REGISTER_DAY(2021, Day08, std::vector<Signal>, int);
REGISTER_TEST_EXAMPLE(2021, Day08, ExampleInput, 1, 26);
REGISTER_TEST(2021, Day08, Input, 1, 301);
REGISTER_TEST_EXAMPLE(2021, Day08, ExampleInput, 2, 61229);
REGISTER_TEST(2021, Day08, Input, 2, 908067);
READ_INPUT(input)
{
std::string str;
std::vector<Signal> signals;
while (getline(input, str))
{
Signal signal;
std::stringstream ss{str};
for (int i = 0; i < 10; i++)
{
std::string s;
ss >> s;
std::set<char> set;
for (char c : s) set.emplace(c);
signal.numbers.emplace_back(set);
}
char c;
ss >> c;
for (int i = 0; i < 4; i++)
{
std::string s;
ss >> s;
std::set<char> set;
for (char c : s) set.emplace(c);
signal.display.emplace_back(set);
}
signals.emplace_back(signal);
}
return signals;
}
OUTPUT1(input)
{
int count = 0;
for (auto&& signal : input)
{
for (auto&& number : signal.display)
{
if (number.size() == 2 || number.size() == 3 || number.size() == 4 || number.size() == 7)
count++;
}
}
return count;
}
OUTPUT2(input)
{
int sum = 0;
for (auto&& signal : input)
{
std::vector<std::set<char>> numbers(10);
// Find all numbers with unique amount of segments
for (auto&& number : signal.numbers)
{
if (number.size() == 2)
numbers[1] = number;
if (number.size() == 3)
numbers[7] = number;
if (number.size() == 4)
numbers[4] = number;
if (number.size() == 7)
numbers[8] = number;
}
// Find all numbers with five and six segments
std::vector<std::set<char>> fivesegs;
std::vector<std::set<char>> sixsegs;
for (auto&& number : signal.numbers)
{
if (number.size() == 5)
fivesegs.emplace_back(number);
if (number.size() == 6)
sixsegs.emplace_back(number);
}
// Find number 3 (only five segment number which 1 is a subset of)
for (auto it = fivesegs.begin(); it != fivesegs.end(); it++)
{
if (Helper::IsSubset(numbers[1], *it))
{
numbers[3] = *it;
fivesegs.erase(it);
break;
}
}
// Find number 6 (only six segment number which is not a subset of 1)
for (auto it = sixsegs.begin(); it != sixsegs.end(); it++)
{
if (!Helper::IsSubset(numbers[1], *it))
{
numbers[6] = *it;
sixsegs.erase(it);
break;
}
}
// Find number 5 (only five segment number which is a subset of 6)
for (auto it = fivesegs.begin(); it != fivesegs.end(); it++)
{
if (Helper::IsSubset(*it, numbers[6]))
{
numbers[5] = *it;
fivesegs.erase(it);
break;
}
}
// Find number 2 (last five segment number)
numbers[2] = fivesegs.front();
// Find number 9 (only six segment number which 4 is a subset of)
for (auto it = sixsegs.begin(); it != sixsegs.end(); it++)
{
if (Helper::IsSubset(numbers[4], *it))
{
numbers[9] = *it;
sixsegs.erase(it);
break;
}
}
// Find number 0 (last six segment number)
numbers[0] = sixsegs.front();
// Calculate the segment display
int num = 0;
for (auto number : signal.display)
{
auto it = std::find(numbers.begin(), numbers.end(), number);
int i = it - numbers.begin();
num = num * 10 + i;
}
sum += num;
}
return sum;
}
}
+91
View File
@@ -0,0 +1,91 @@
#include "common/aoc.h"
namespace y2021::day09
{
REGISTER_DAY(2021, Day09, Array2D<int>, int);
REGISTER_TEST_EXAMPLE(2021, Day09, ExampleInput, 1, 15);
REGISTER_TEST(2021, Day09, Input, 1, 478);
REGISTER_TEST_EXAMPLE(2021, Day09, ExampleInput, 2, 1134);
REGISTER_TEST(2021, Day09, Input, 2, 1327014);
READ_INPUT(input)
{
return Input::ReadDigitsAsArray2D(input);
}
OUTPUT1(input)
{
int count = 0;
Index2D index{0, 0};
for (auto& val : input)
{
Index2D indices[4]{
{index.x - 1, index.y}, {index.x, index.y - 1}, {index.x + 1, index.y}, {index.x, index.y + 1}};
bool all = true;
for (auto& ind : indices)
{
if (input.IsInside(ind) && input[ind] <= val)
{
all = false;
break;
}
}
if (all)
count += val + 1;
input.Increment(index);
}
return count;
}
OUTPUT2(input)
{
std::vector<Index2D> basins;
Index2D index{0, 0};
for (auto& val : input)
{
Index2D indices[4]{
{index.x - 1, index.y}, {index.x, index.y - 1}, {index.x + 1, index.y}, {index.x, index.y + 1}};
bool all = true;
for (auto& ind : indices)
{
if (input.IsInside(ind) && input[ind] <= val)
{
all = false;
break;
}
}
if (all)
basins.emplace_back(index);
input.Increment(index);
}
std::vector<int> numbers;
for (auto&& basin : basins)
{
std::stack<Index2D> stack;
std::set<Index2D> visited;
stack.emplace(basin);
visited.emplace(basin);
while (!stack.empty())
{
auto index = stack.top();
stack.pop();
Index2D indices[4]{
{index.x - 1, index.y}, {index.x, index.y - 1}, {index.x + 1, index.y}, {index.x, index.y + 1}};
for (auto&& ind : indices)
{
if (input.IsInside(ind) && input[ind] != 9 && visited.find(ind) == visited.end())
{
stack.emplace(ind);
visited.emplace(ind);
}
}
}
numbers.emplace_back(visited.size());
}
std::sort(numbers.begin(), numbers.end());
return numbers[numbers.size() - 1] * numbers[numbers.size() - 2] * numbers[numbers.size() - 3];
}
}
+90
View File
@@ -0,0 +1,90 @@
#include "common/aoc.h"
namespace y2021::day10
{
REGISTER_DAY(2021, Day10, std::vector<std::string>, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day10, ExampleInput, 1, 26397);
REGISTER_TEST(2021, Day10, Input, 1, 240123);
REGISTER_TEST_EXAMPLE(2021, Day10, ExampleInput, 2, 288957);
REGISTER_TEST(2021, Day10, Input, 2, 3260812321);
READ_INPUT(input)
{
return Input::ReadLines(input);
}
OUTPUT1(input)
{
std::map<char, int64_t> values{{')', 3}, {']', 57}, {'}', 1197}, {'>', 25137}};
Mapper<char, char> mapper{{'(', ')'}, {'[', ']'}, {'{', '}'}, {'<', '>'}};
int64_t count = 0;
for (auto&& str : input)
{
std::stack<char> stack;
stack.emplace(str[0]);
for (size_t i = 1; i < str.size(); i++)
{
char* ptr = mapper.GetFirst(str[i]);
if (ptr)
{
if (stack.top() != *ptr)
{
count += values[str[i]];
break;
}
stack.pop();
}
else
{
stack.emplace(str[i]);
}
}
}
return count;
}
OUTPUT2(input)
{
Mapper<char, char> mapper{{'(', ')'}, {'[', ']'}, {'{', '}'}, {'<', '>'}};
std::map<char, int64_t> values{{'(', 1}, {'[', 2}, {'{', 3}, {'<', 4}};
int64_t count = 0;
std::vector<int64_t> scores;
for (auto&& str : input)
{
std::stack<char> stack;
stack.emplace(str[0]);
bool valid = true;
for (size_t i = 1; i < str.size(); i++)
{
char* ptr = mapper.GetFirst(str[i]);
if (ptr)
{
if (stack.top() != *ptr)
{
valid = false;
break;
}
stack.pop();
}
else
{
stack.emplace(str[i]);
}
}
if (valid)
{
int64_t score = 0;
while (!stack.empty())
{
score *= 5;
score += values[stack.top()];
stack.pop();
}
scores.emplace_back(score);
}
}
std::sort(scores.begin(), scores.end());
return scores[scores.size() / 2];
}
}
+82
View File
@@ -0,0 +1,82 @@
#include "common/aoc.h"
namespace y2021::day11
{
std::set<Index2D> CalculateFlashing(Array2D<int>& array)
{
for (auto& val : array) val++;
std::set<Index2D> flashed;
bool hasChanged = true;
while (hasChanged)
{
Array2D<int> arrayCpy = array;
hasChanged = false;
Index2D index{0, 0};
for (auto& val : array)
{
if (val > 9 && flashed.find(index) == flashed.end())
{
flashed.emplace(index);
hasChanged = true;
for (int y = -1; y < 2; y++)
{
for (int x = -1; x < 2; x++)
{
if (x == 0 && y == 0)
continue;
Index2D newIndex{index.x + x, index.y + y};
if (array.IsInside(newIndex))
arrayCpy[newIndex]++;
}
}
}
array.Increment(index);
}
array = arrayCpy;
}
return flashed;
}
REGISTER_DAY(2021, Day11, Array2D<int>, int);
REGISTER_TEST_EXAMPLE(2021, Day11, ExampleInput, 1, 1656);
REGISTER_TEST(2021, Day11, Input, 1, 1667);
REGISTER_TEST_EXAMPLE(2021, Day11, ExampleInput, 2, 195);
REGISTER_TEST(2021, Day11, Input, 2, 488);
READ_INPUT(input)
{
return Input::ReadDigitsAsArray2D(input);
}
OUTPUT1(input)
{
InputType array = input;
int count = 0;
for (int i = 0; i < 100; i++)
{
std::set<Index2D> flashed = CalculateFlashing(array);
count += flashed.size();
for (auto& flash : flashed) array[flash] = 0;
}
return count;
}
OUTPUT2(input)
{
InputType array = input;
int count = 1;
while (true)
{
std::set<Index2D> flashed = CalculateFlashing(array);
if (flashed.size() == array.width * array.height)
return count;
for (auto& flash : flashed) array[flash] = 0;
count++;
}
return count;
}
}
+128
View File
@@ -0,0 +1,128 @@
#include "common/aoc.h"
namespace y2021::day12
{
struct Node
{
std::set<std::string> connections;
};
struct Path
{
std::vector<std::string> path{"start"};
bool hasDuplicate = false;
};
using NodeMap = std::map<std::string, Node>;
REGISTER_DAY(2021, Day12, NodeMap, int);
REGISTER_TEST_EXAMPLE(2021, Day12, ExampleInput, 1, 10);
REGISTER_TEST(2021, Day12, Input, 1, 3887);
REGISTER_TEST_EXAMPLE(2021, Day12, ExampleInput, 2, 36);
REGISTER_TEST(2021, Day12, Input, 2, 104834);
READ_INPUT(input)
{
NodeMap nodes;
std::string str;
while (getline(input, str))
{
std::stringstream ss{str};
std::string from, to;
getline(ss, from, '-');
getline(ss, to);
auto itFrom = nodes.find(from);
auto itTo = nodes.find(to);
if (itFrom == nodes.end())
itFrom = nodes.emplace(from, Node{}).first;
if (itTo == nodes.end())
itTo = nodes.emplace(to, Node{}).first;
itFrom->second.connections.emplace(to);
itTo->second.connections.emplace(from);
}
return nodes;
}
OUTPUT1(input)
{
int count = 0;
std::stack<std::vector<std::string>> paths;
paths.emplace(std::vector<std::string>{"start"});
while (!paths.empty())
{
auto path = paths.top();
paths.pop();
if (path.back() == "end")
{
count++;
continue;
}
auto it = input.find(path.back());
for (auto& connection : it->second.connections)
{
if (connection[0] >= 'a' && connection[0] <= 'z')
{
if (std::find(path.begin(), path.end(), connection) == path.end())
{
std::vector<std::string> cpy = path;
cpy.emplace_back(connection);
paths.emplace(cpy);
}
}
else
{
std::vector<std::string> cpy = path;
cpy.emplace_back(connection);
paths.emplace(cpy);
}
}
}
return count;
}
OUTPUT2(input)
{
int count = 0;
std::stack<Path> paths;
paths.emplace(Path{});
while (!paths.empty())
{
auto path = paths.top();
paths.pop();
if (path.path.back() == "end")
{
count++;
continue;
}
auto it = input.find(path.path.back());
for (auto& connection : it->second.connections)
{
if (connection[0] >= 'a' && connection[0] <= 'z')
{
if (std::find(path.path.begin(), path.path.end(), connection) == path.path.end())
{
Path cpy = path;
cpy.path.emplace_back(connection);
paths.emplace(cpy);
}
else if (!path.hasDuplicate && connection != "start")
{
Path cpy = path;
cpy.path.emplace_back(connection);
cpy.hasDuplicate = true;
paths.emplace(cpy);
}
}
else
{
Path cpy = path;
cpy.path.emplace_back(connection);
paths.emplace(cpy);
}
}
}
return count;
}
}
+100
View File
@@ -0,0 +1,100 @@
#include "common/aoc.h"
namespace y2021::day13
{
void Fold(std::set<Index2D>& indices, bool x, int fold)
{
std::set<Index2D> newIndices;
for (auto& index : indices)
{
// y axis
if (x)
{
Index2D newIndex = index;
if (newIndex.x > fold)
newIndex.x = fold - (newIndex.x - 1) % fold - 1;
newIndices.emplace(newIndex);
}
else
{
Index2D newIndex = index;
if (newIndex.y > fold)
newIndex.y = fold - (newIndex.y - 1) % fold - 1;
newIndices.emplace(newIndex);
}
}
indices = newIndices;
}
struct Paper
{
std::set<Index2D> indices;
std::vector<std::pair<bool, int>> folds;
};
REGISTER_DAY(2021, Day13, Paper, int);
REGISTER_TEST_EXAMPLE(2021, Day13, ExampleInput, 1, 17);
REGISTER_TEST(2021, Day13, Input, 1, 716);
REGISTER_TEST_EXAMPLE(2021, Day13, ExampleInput, 2, 16);
REGISTER_TEST(2021, Day13, Input, 2, 97);
READ_INPUT(input)
{
Paper paper;
std::string str;
while (getline(input, str))
{
if (str.empty())
break;
Index2D index;
std::stringstream ss{str};
ss >> index.x >> "," >> index.y;
paper.indices.emplace(index);
}
while (getline(input, str))
{
char c, c2;
std::string s;
int i;
std::stringstream ss{str};
ss >> s >> s >> c >> c2 >> i;
paper.folds.emplace_back(c == 'x', i);
}
return paper;
}
OUTPUT1(input)
{
std::set<Index2D> indices = input.indices;
Fold(indices, input.folds.front().first, input.folds.front().second);
return indices.size();
}
OUTPUT2(input)
{
std::set<Index2D> indices = input.indices;
for (auto& fold : input.folds)
{
Fold(indices, fold.first, fold.second);
}
Index2D max = *indices.begin();
for (auto index : indices)
{
max.x = std::max(index.x, max.x);
max.y = std::max(index.y, max.y);
}
Array2D<char> board{max.x + 1, max.y + 1};
board.Fill(' ');
for (auto& index : indices)
{
board[index] = '#';
}
std::cout << board;
// Not the "correct" output to part 2, but it verifies something at least
return indices.size();
}
}
+121
View File
@@ -0,0 +1,121 @@
#include "common/aoc.h"
namespace y2021::day14
{
struct Data
{
std::string str;
std::map<std::string, char> pairs;
};
REGISTER_DAY(2021, Day14, Data, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day14, ExampleInput, 1, 1588);
REGISTER_TEST(2021, Day14, Input, 1, 4517);
REGISTER_TEST_EXAMPLE(2021, Day14, ExampleInput, 2, 2188189693529);
REGISTER_TEST(2021, Day14, Input, 2, 4704817645083);
READ_INPUT(input)
{
Data data;
getline(input, data.str);
std::string str;
getline(input, str);
while (getline(input, str))
{
data.pairs.emplace(str.substr(0, 2), str[6]);
}
return data;
}
OUTPUT1(input)
{
std::string str = input.str;
for (int i = 0; i < 10; i++)
{
std::string newString;
for (size_t j = 0; j < str.size() - 1; j++)
{
auto it = input.pairs.find(str.substr(j, 2));
newString.push_back(str[j]);
newString.push_back(it->second);
}
newString.push_back(str.back());
str = newString;
}
std::map<char, int64_t> occurences;
for (char c : str)
{
occurences[c]++;
}
int64_t min = occurences.begin()->second;
char minChar = occurences.begin()->first;
int64_t max = occurences.begin()->second;
char maxChar = occurences.begin()->first;
for (auto& occurence : occurences)
{
if (occurence.second < min)
{
min = occurence.second;
minChar = occurence.first;
}
if (occurence.second > max)
{
max = occurence.second;
maxChar = occurence.first;
}
}
return occurences[maxChar] - occurences[minChar];
}
OUTPUT2(input)
{
std::string str = input.str;
std::map<std::string, int64_t> pairCounts;
for (size_t j = 0; j < str.size() - 1; j++)
{
pairCounts[input.str.substr(j, 2)]++;
}
for (int i = 0; i < 40; i++)
{
std::map<std::string, int64_t> cpy = pairCounts;
for (auto& pairCount : cpy)
{
if (pairCount.second <= 0)
continue;
auto it = input.pairs.find(pairCount.first);
std::string firstPair = pairCount.first.substr(0, 1) + it->second;
std::string secondPair = it->second + pairCount.first.substr(1, 1);
pairCounts[firstPair] += pairCount.second;
pairCounts[secondPair] += pairCount.second;
pairCounts[pairCount.first] -= pairCount.second;
}
}
std::map<char, int64_t> occurences;
for (auto& pairCount : pairCounts)
{
if (pairCount.second != 0)
occurences[pairCount.first[0]] += pairCount.second;
}
occurences[str.back()]++;
int64_t min = occurences.begin()->second;
char minChar = occurences.begin()->first;
int64_t max = occurences.begin()->second;
char maxChar = occurences.begin()->first;
for (auto& occurence : occurences)
{
if (occurence.second < min)
{
min = occurence.second;
minChar = occurence.first;
}
if (occurence.second > max)
{
max = occurence.second;
maxChar = occurence.first;
}
}
return occurences[maxChar] - occurences[minChar];
}
}
+63
View File
@@ -0,0 +1,63 @@
#include "common/aoc.h"
namespace y2021::day15
{
int Heuristic(const Array2D<int>& array, const Index2D& index)
{
return std::abs(index.x - array.width + 1) && std::abs(index.y - array.height + 1);
}
std::vector<std::pair<int, Index2D>> Branch(const Array2D<int>& array, const Index2D& index)
{
Index2D indices[4]{{index.x - 1, index.y}, {index.x, index.y - 1}, {index.x + 1, index.y}, {index.x, index.y + 1}};
std::vector<std::pair<int, Index2D>> moves;
for (auto& index : indices)
{
if (array.IsInside(index))
moves.emplace_back(std::pair<int, Index2D>{array[index], index});
}
return moves;
}
int Goal(const Array2D<int>& array, const Index2D& index)
{
return index.x == array.width - 1 && index.y == array.height - 1;
}
int Pathfinder(const Array2D<int>& array)
{
return Helper::AStar(array, Index2D{0, 0}, Heuristic, Branch, Goal);
}
REGISTER_DAY(2021, Day15, Array2D<int>, int);
REGISTER_TEST_EXAMPLE(2021, Day15, ExampleInput, 1, 40);
REGISTER_TEST(2021, Day15, Input, 1, 714);
REGISTER_TEST_EXAMPLE(2021, Day15, ExampleInput, 2, 315);
REGISTER_TEST(2021, Day15, Input, 2, 2948);
READ_INPUT(input)
{
return Input::ReadDigitsAsArray2D(input);
}
OUTPUT1(input)
{
return Pathfinder(input);
}
OUTPUT2(input)
{
Array2D<int> array{input.width * 5, input.height * 5};
Index2D index{0, 0};
for (auto& val : array)
{
val = input.GetMod(index.x, index.y) + index.x / input.width + index.y / input.height;
if (val >= 10)
val = val % 10 + 1;
array.Increment(index);
}
return Pathfinder(array);
}
}
+128
View File
@@ -0,0 +1,128 @@
#include "common/aoc.h"
namespace y2021::day16
{
int64_t Read(const std::string& str, int& offset, int size)
{
int64_t i = Helper::BinStrToInt64(str.substr(offset, size));
offset += size;
return i;
}
std::pair<int64_t, int64_t> ReadPacket(const std::string& str, int& offset)
{
int64_t version = Read(str, offset, 3);
int64_t type = Read(str, offset, 3);
if (type == 4)
{
// Normal packet
int64_t type = Read(str, offset, 1);
int64_t val = 0;
while (type == 1)
{
val = (val << 4) | Read(str, offset, 4);
type = Read(str, offset, 1);
}
val = (val << 4) | Read(str, offset, 4);
return {version, val};
}
else
{
// Packet containing packets
int64_t lengthId = Read(str, offset, 1);
std::vector<int64_t> values;
int64_t versionTotal = version;
if (lengthId == 0)
{
int64_t totalLength = Read(str, offset, 15);
int64_t start = offset;
while (offset < start + totalLength)
{
auto [version, value] = ReadPacket(str, offset);
values.emplace_back(value);
versionTotal += version;
}
}
else
{
int64_t totalPackets = Read(str, offset, 11);
for (int64_t i = 0; i < totalPackets; i++)
{
auto [version, value] = ReadPacket(str, offset);
values.emplace_back(value);
versionTotal += version;
}
}
if (type == 0)
return {versionTotal,
std::accumulate(values.begin(), values.end(), 0ll, [](int64_t sum, int64_t val) { return sum + val; })};
else if (type == 1)
return {
versionTotal,
std::accumulate(values.begin(), values.end(), 1ll, [](int64_t prod, int64_t val) { return prod * val; })};
else if (type == 2)
return {
versionTotal,
std::accumulate(
values.begin(), values.end(), values.front(), [](int64_t max, int64_t val) { return std::min(max, val); })};
else if (type == 3)
return {
versionTotal,
std::accumulate(
values.begin(), values.end(), values.front(), [](int64_t min, int64_t val) { return std::max(min, val); })};
else if (type == 5)
return {versionTotal, values[0] > values[1] ? 1 : 0};
else if (type == 6)
return {versionTotal, values[0] < values[1] ? 1 : 0};
else if (type == 7)
return {versionTotal, values[0] == values[1] ? 1 : 0};
}
return {0, 0};
}
std::pair<int64_t, int64_t> ReadPacket(const std::string& str)
{
int offset = 0;
return ReadPacket(str, offset);
}
REGISTER_DAY(2021, Day16, std::string, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day16, ExampleInput, 1, 20);
REGISTER_TEST(2021, Day16, Input, 1, 984);
REGISTER_TEST_EXAMPLE(2021, Day16, ExampleInput, 2, 1);
REGISTER_TEST(2021, Day16, Input, 2, 1015320896946);
READ_INPUT(input)
{
std::string str;
getline(input, str);
std::string bin;
for (char c : str)
{
if (c >= '0' && c <= '9')
{
char val = c - '0'; // vs compiler throws warnings if this is inlined into the bitset function...
bin += std::bitset<4>(val).to_string();
}
else if (c >= 'A' && c <= 'F')
{
char val = c - 'A' + 10; // vs compiler throws warnings if this is inlined into the bitset function...
bin += std::bitset<4>(val).to_string();
}
}
return bin;
}
OUTPUT1(input)
{
return ReadPacket(input).first;
}
OUTPUT2(input)
{
return ReadPacket(input).second;
}
}
+61
View File
@@ -0,0 +1,61 @@
#include "common/aoc.h"
namespace y2021::day17
{
struct Area
{
Index2D p1;
Index2D p2;
};
REGISTER_DAY(2021, Day17, Area, int);
REGISTER_TEST_EXAMPLE(2021, Day17, ExampleInput, 1, 45);
REGISTER_TEST(2021, Day17, Input, 1, 2701);
REGISTER_TEST_EXAMPLE(2021, Day17, ExampleInput, 2, 112);
REGISTER_TEST(2021, Day17, Input, 2, 1070);
READ_INPUT(input)
{
Area area;
input >> "target area: x=" >> area.p1.x >> ".." >> area.p2.x >> ", y=" >> area.p1.y >> ".." >> area.p2.y;
return area;
}
OUTPUT1(input)
{
int v = -input.p1.y;
return v * (v - 1) / 2;
}
OUTPUT2(input)
{
int count = 0;
for (int y = input.p1.y - 1; y <= -input.p1.y; y++)
{
for (int x = 1; x <= input.p2.x; x++)
{
int xPos = 0;
int yPos = 0;
int vx = x;
int vy = y;
while (xPos <= input.p2.x && yPos >= input.p1.y)
{
if (xPos >= input.p1.x && xPos <= input.p2.x && yPos >= input.p1.y && yPos <= input.p2.y)
{
count++;
break;
}
xPos += vx;
yPos += vy;
vx--;
if (vx < 0)
vx = 0;
vy--;
}
}
}
return count;
}
}
+323
View File
@@ -0,0 +1,323 @@
#include "common/aoc.h"
namespace y2021::day18
{
struct Node
{
Node* parent = nullptr;
int value = 0;
std::vector<Node> nodes;
Node() = default;
Node(const std::string& str)
: nodes{Node{}, Node{}}
{
UpdateParents();
std::stringstream ss{str};
ss >> *this;
}
Node(int value)
: value{value}
{
}
Node(const Node& left, const Node& right)
: nodes{left, right}
{
UpdateParents();
}
Node& Left()
{
return nodes[0];
}
const Node& Left() const
{
return nodes[0];
}
Node& Right()
{
return nodes[1];
}
const Node& Right() const
{
return nodes[1];
}
bool IsNumber() const
{
return nodes.size() == 0;
}
int& Number()
{
return value;
}
int Number() const
{
return value;
}
int Calculate()
{
int i = 0;
if (Left().IsNumber())
i += 3 * Left().Number();
else
i += 3 * Left().Calculate();
if (Right().IsNumber())
i += 2 * Right().Number();
else
i += 2 * Right().Calculate();
return i;
}
void AddToLeft(int value, Node* from)
{
if (Left().IsNumber())
Left().Number() += value;
else
{
Node& node = Left();
if (&node == from)
{
if (parent != nullptr)
parent->AddToLeft(value, this);
}
else
node.AddToRightDown(value);
}
}
void AddToRightDown(int value)
{
if (Right().IsNumber())
Right().Number() += value;
else
{
Right().AddToRightDown(value);
}
}
void AddToRight(int value, Node* from)
{
if (Right().IsNumber())
Right().Number() += value;
else
{
Node& node = Right();
if (&node == from)
{
if (parent != nullptr)
parent->AddToRight(value, this);
}
else
node.AddToLeftDown(value);
}
}
void AddToLeftDown(int value)
{
if (Left().IsNumber())
Left().Number() += value;
else
{
Left().AddToLeftDown(value);
}
}
bool Explode(int depth = 0)
{
if (depth >= 4)
{
parent->AddToLeft(Left().Number(), this);
parent->AddToRight(Right().Number(), this);
if (!parent->Left().IsNumber() && &parent->Left() == this)
parent->Left() = 0;
if (!parent->Right().IsNumber() && &parent->Right() == this)
parent->Right() = 0;
return true;
}
if (!Left().IsNumber())
if (Left().Explode(depth + 1))
return true;
if (!Right().IsNumber())
if (Right().Explode(depth + 1))
return true;
return false;
}
bool Split()
{
if (!Left().IsNumber())
{
if (Left().Split())
return true;
}
else if (Left().Number() >= 10)
{
int val = Left().Number();
Node node{(val >> 1), (val >> 1) + (val % 2)};
node.parent = this;
Left() = node;
return true;
}
if (!Right().IsNumber())
{
if (Right().Split())
return true;
}
else if (Right().Number() >= 10)
{
int val = Right().Number();
Node node{(val >> 1), (val >> 1) + (val % 2)};
node.parent = this;
Right() = node;
return true;
}
return false;
}
void UpdateParents()
{
if (!Left().IsNumber())
{
Left().parent = this;
Left().UpdateParents();
}
if (!Right().IsNumber())
{
Right().parent = this;
Right().UpdateParents();
}
}
void Print(std::ostream& stream, int depth) const
{
std::vector<char> depthStart{'|', '<', '{', '(', '['};
std::vector<char> depthEnd{'|', '>', '}', ')', ']'};
stream << depthStart[depth];
if (Left().IsNumber())
stream << Left().Number();
else
Left().Print(stream, depth + 1);
stream << ",";
if (Right().IsNumber())
stream << Right().Number();
else
Right().Print(stream, depth + 1);
stream << depthEnd[depth];
}
void operator=(int value)
{
nodes.clear();
this->value = value;
}
friend std::ostream& operator<<(std::ostream& stream, const Node& node)
{
node.Print(stream, 0);
return stream;
}
friend std::istream& operator>>(std::istream& stream, Node& node)
{
stream >> "[";
if (stream.peek() == '[')
{
Node left{Node{}, Node{}};
stream >> left;
left.parent = &node;
node.Left() = left;
}
else
{
int i;
stream >> i;
node.Left() = i;
}
stream >> ",";
if (stream.peek() == '[')
{
Node right{Node{}, Node{}};
stream >> right;
right.parent = &node;
node.Right() = right;
}
else
{
int i;
stream >> i;
node.Right() = i;
}
stream >> "]";
return stream;
}
};
Node Reduce(const Node& lhs, const Node& rhs)
{
Node node{lhs, rhs};
bool changed = true;
while (changed)
{
changed = false;
while (node.Explode()) changed = true;
if (node.Split())
changed = true;
}
return node;
}
REGISTER_DAY(2021, Day18, std::vector<Node>, int);
REGISTER_TEST_EXAMPLE(2021, Day18, ExampleInput, 1, 4140);
REGISTER_TEST(2021, Day18, Input, 1, 4137);
REGISTER_TEST_EXAMPLE(2021, Day18, ExampleInput, 2, 3993);
REGISTER_TEST(2021, Day18, Input, 2, 4573);
READ_INPUT(input)
{
std::vector<Node> nodes;
std::string str;
while (getline(input, str))
{
nodes.emplace_back(str);
}
return nodes;
}
OUTPUT1(input)
{
Node node = input[0];
for (size_t i = 1; i < input.size(); i++)
{
node = Reduce(node, input[i]);
}
return node.Calculate();
}
OUTPUT2(input)
{
int max = 0;
for (size_t i = 0; i < input.size() - 1; i++)
{
for (size_t j = 1; j < input.size(); j++)
{
max = std::max(max, Reduce(input[j], input[i]).Calculate());
max = std::max(max, Reduce(input[i], input[j]).Calculate());
}
}
return max;
}
}
+278
View File
@@ -0,0 +1,278 @@
#include "common/aoc.h"
namespace y2021::day19
{
constexpr int MAX_ORIENTATIONS = 24;
constexpr int MIN_OVERLAP = 12;
struct Scanner
{
std::set<Index3D> beacons;
};
struct Overlap
{
bool overlapping = false;
int orientation = 0;
Index3D offset{0, 0};
friend std::ostream& operator<<(std::ostream& stream, const Overlap& overlap)
{
if (overlap.overlapping)
return stream << "true " << overlap.orientation << " " << overlap.offset;
else
return stream << "false";
}
operator bool()
{
return overlapping;
}
};
Index3D RotateY(const Index3D& index)
{
return Index3D{-index.z, index.y, index.x};
}
Index3D RotateY2(const Index3D& index)
{
return Index3D{-index.x, index.y, -index.z};
}
Index3D RotateY3(const Index3D& index)
{
return Index3D{index.z, index.y, -index.x};
}
Index3D RotateX(const Index3D& index)
{
return Index3D{index.x, -index.z, index.y};
}
Index3D RotateX2(const Index3D& index)
{
return Index3D{index.x, -index.y, -index.z};
}
Index3D RotateX3(const Index3D& index)
{
return Index3D{index.x, index.z, -index.y};
}
Index3D RotateZ(const Index3D& index)
{
return Index3D{-index.y, index.x, index.z};
}
Index3D RotateZ2(const Index3D& index)
{
return Index3D{-index.x, -index.y, index.z};
}
Index3D RotateZ3(const Index3D& index)
{
return Index3D{index.y, -index.x, index.z};
}
Index3D Orient(const Index3D& index, int i)
{
switch (i)
{
// Facing forward
case 0:
return index;
case 1:
return RotateZ(index);
case 2:
return RotateZ2(index);
case 3:
return RotateZ3(index);
// Facing left
case 4:
return RotateY(index);
case 5:
return RotateX(RotateY(index));
case 6:
return RotateX2(RotateY(index));
case 7:
return RotateX3(RotateY(index));
// Facing backward
case 8:
return RotateY2(index);
case 9:
return RotateZ(RotateY2(index));
case 10:
return RotateZ2(RotateY2(index));
case 11:
return RotateZ3(RotateY2(index));
// Facing right
case 12:
return RotateY3(index);
case 13:
return RotateX(RotateY3(index));
case 14:
return RotateX2(RotateY3(index));
case 15:
return RotateX3(RotateY3(index));
// Facing down
case 16:
return RotateX(index);
case 17:
return RotateY(RotateX(index));
case 18:
return RotateY2(RotateX(index));
case 19:
return RotateY3(RotateX(index));
// Facing up
case 20:
return RotateX3(index);
case 21:
return RotateY(RotateX3(index));
case 22:
return RotateY2(RotateX3(index));
case 23:
return RotateY3(RotateX3(index));
}
std::cout << "Invalid orientation: " << i << std::endl;
return index;
}
Overlap IsOverlapping(const std::set<Index3D>& layout, const Scanner& scanner)
{
for (auto& index : layout)
{
int beaconsLeft = scanner.beacons.size();
for (auto it = scanner.beacons.begin(); it != scanner.beacons.end(); it++)
{
if (beaconsLeft < MIN_OVERLAP)
break;
beaconsLeft--;
for (int i = 0; i < MAX_ORIENTATIONS; i++)
{
Index3D offset = index - Orient(*it, i);
int count = 0;
for (auto it2 = scanner.beacons.begin(); it2 != scanner.beacons.end(); it2++)
{
if (layout.count(offset + Orient(*it2, i)))
{
count++;
}
}
if (count >= MIN_OVERLAP)
return {true, i, offset};
}
}
}
return {false, 0, Index3D{0, 0}};
}
std::pair<int, int> Solve(std::vector<Scanner> scanners)
{
// Find first overlap to initialize the "correct" layout
std::set<Index3D> layout;
for (auto it = scanners.begin(); it != scanners.end(); it++)
{
bool found = false;
for (auto it2 = it; it2 != scanners.end(); it2++)
{
if (it == it2)
continue;
Overlap overlap = IsOverlapping(it->beacons, *it2);
if (overlap)
{
layout = it->beacons;
scanners.erase(it);
found = true;
break;
}
}
if (found)
break;
}
// Find overlapping scanners one by one
std::vector<Index3D> scannerPos{Index3D{0, 0, 0}};
while (!scanners.empty())
{
bool removed = false;
for (auto it = scanners.begin(); it != scanners.end(); it++)
{
Overlap overlap = IsOverlapping(layout, *it);
if (overlap)
{
for (auto& beacon : it->beacons)
{
layout.emplace(overlap.offset + Orient(beacon, overlap.orientation));
}
scannerPos.emplace_back(overlap.offset);
scanners.erase(it);
removed = true;
break;
}
}
if (!removed)
{
std::cout << "Could not find position of any remaining scanners" << std::endl;
break;
}
}
// Find largest manhattan distance between two scanners
int maxDistance = 0;
for (size_t i = 0; i < scannerPos.size(); i++)
{
for (size_t j = i + 1; j < scannerPos.size(); j++)
{
Index3D distance = scannerPos[i] - scannerPos[j];
maxDistance = std::max(maxDistance, std::abs(distance.x) + std::abs(distance.y) + std::abs(distance.z));
}
}
return {layout.size(), maxDistance};
}
REGISTER_DAY(2021, Day19, std::vector<Scanner>, int);
REGISTER_TEST_EXAMPLE(2021, Day19, ExampleInput, 1, 79);
REGISTER_TEST(2021, Day19, Input, 1, 359);
REGISTER_TEST_EXAMPLE(2021, Day19, ExampleInput, 2, 3621);
REGISTER_TEST(2021, Day19, Input, 2, 12292);
READ_INPUT(input)
{
std::vector<Scanner> scanners;
std::string str;
while (getline(input, str))
{
Scanner scanner;
getline(input, str);
while (!str.empty())
{
std::stringstream ss{str};
Index3D index;
ss >> index.x >> "," >> index.y >> "," >> index.z;
scanner.beacons.emplace(index);
str.clear();
getline(input, str);
}
scanners.emplace_back(scanner);
}
return scanners;
}
OUTPUT1(input)
{
return Solve(input).first;
}
OUTPUT2(input)
{
return Solve(input).second;
}
}
+86
View File
@@ -0,0 +1,86 @@
#include "common/aoc.h"
namespace y2021::day20
{
struct Data
{
std::string line;
Array2D<char> grid;
};
int GetNumber(const Array2D<char>& array, Index2D index)
{
int num = 0;
for (int y = index.y - 1; y <= index.y + 1; y++)
{
for (int x = index.x - 1; x <= index.x + 1; x++)
{
num <<= 1;
Index2D newIndex{x, y};
if (array.IsInside(newIndex) && array[newIndex] == '#')
num |= 1;
}
}
return num;
}
int Solve(const Data& input, int iter)
{
int SIZE = (2 * iter) * 2;
Array2D<char> output{input.grid.width + SIZE, input.grid.height + SIZE};
Index2D index{0, 0};
output.Fill('.');
for (auto& val : input.grid)
{
output.Set(index.x + SIZE / 2, index.y + SIZE / 2, val);
input.grid.Increment(index);
}
for (int i = 0; i < iter; i++)
{
Array2D<char> cpy = output;
Index2D index{0, 0};
for (auto& grid : output)
{
int num = GetNumber(cpy, index);
output[index] = input.line[num];
output.Increment(index);
}
std::string str;
}
int count = 0;
for (int y = iter; y < output.height - iter; y++)
for (int x = iter; x < output.width - iter; x++)
if (output.Get(x, y) == '#')
count++;
return count;
}
REGISTER_DAY(2021, Day20, Data, int);
REGISTER_TEST_EXAMPLE(2021, Day20, ExampleInput, 1, 35);
REGISTER_TEST(2021, Day20, Input, 1, 5203);
REGISTER_TEST_EXAMPLE(2021, Day20, ExampleInput, 2, 3351);
REGISTER_TEST(2021, Day20, Input, 2, 18806);
READ_INPUT(input)
{
Data data;
std::getline(input, data.line);
std::string str;
getline(input, str);
data.grid = Input::ReadArray2D(input);
return data;
}
OUTPUT1(input)
{
return Solve(input, 2);
}
OUTPUT2(input)
{
return Solve(input, 50);
}
}
+107
View File
@@ -0,0 +1,107 @@
#include "common/aoc.h"
namespace y2021::day21
{
int Mod(int i)
{
return (i - 1) % 10 + 1;
}
std::pair<int64_t, int64_t> Roll(int position1, int points1, int position2, int points2, bool player1, int depth)
{
if (points2 >= 21)
return {0, 1};
else if (points1 >= 21)
return {1, 0};
// 3: 111
// 4: 211 121 112
// 5: 221 212 122 311 131 113
// 6: 222 321 312 213 231 123 132
// 7: 223 232 323 133 331 313
// 8: 233 323 322
// 9: 333
std::map<int, int> outcomes{{3, 1}, {4, 3}, {5, 6}, {6, 7}, {7, 6}, {8, 3}, {9, 1}};
std::pair<int64_t, int64_t> wins{0, 0};
int initialPos = 0;
int initialPoints = 0;
if (player1)
{
initialPos = position1;
initialPoints = points1;
}
else
{
initialPos = position2;
initialPoints = points2;
}
for (auto [value, times] : outcomes)
{
if (player1)
{
position1 = initialPos;
points1 = initialPoints;
position1 = Mod(position1 + value);
points1 += position1;
}
else
{
position2 = initialPos;
points2 = initialPoints;
position2 = Mod(position2 + value);
points2 += position2;
}
auto subwins = Roll(position1, points1, position2, points2, !player1, depth + 1);
wins.first += times * subwins.first;
wins.second += times * subwins.second;
}
return wins;
}
REGISTER_DAY(2021, Day21, std::vector<int>, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day21, ExampleInput, 1, 739785);
REGISTER_TEST(2021, Day21, Input, 1, 503478);
REGISTER_TEST_EXAMPLE(2021, Day21, ExampleInput, 2, 444356092776315);
REGISTER_TEST(2021, Day21, Input, 2, 716241959649754);
READ_INPUT(input)
{
std::vector<int> players;
int i;
std::string str;
while (getline(input, str))
{
std::stringstream ss{str};
ss >> "Player" >> i >> "starting position:" >> i;
players.emplace_back(i);
}
return players;
}
OUTPUT1(input)
{
std::vector<int> positions = input;
std::vector<int> points;
points.resize(input.size());
for (int i = 1; i < 10000; i += 3)
{
int index = (i - 1) % 2;
positions[index] = Mod(positions[index] + 3 * (i + 1));
points[index] += positions[index];
if (points[index] >= 1000)
{
return ((int64_t)i + 2ll) * (int64_t)points[(index + 1) % 2];
}
}
return 0;
}
OUTPUT2(input)
{
std::pair<int64_t, int64_t> wins = Roll(input[0], 0, input[1], 0, true, 0);
return std::max(wins.first, wins.second);
}
}
+138
View File
@@ -0,0 +1,138 @@
#include "common/aoc.h"
namespace y2021::day22
{
struct Overlap;
struct Volume
{
int sign = 0;
Index3D min = Index3D{0, 0};
Index3D max = Index3D{0, 0};
Volume()
{
}
Volume(int sign, const Index3D& min, const Index3D& max)
: sign{sign},
min{min},
max{max}
{
}
int64_t GetCubes() const
{
return ((int64_t)max.x - (int64_t)min.x + 1ll) * ((int64_t)max.y - (int64_t)min.y + 1ll) *
((int64_t)max.z - (int64_t)min.z + 1ll);
}
Overlap GetOverlap(const Volume& other) const;
friend std::ostream& operator<<(std::ostream& stream, const Volume& volume)
{
return stream << volume.min << " " << volume.max;
}
};
struct Overlap
{
bool overlap = false;
Volume volume;
Overlap(bool overlap, const Volume& volume)
: overlap{overlap},
volume{volume}
{
}
operator bool()
{
return overlap;
}
};
Overlap Volume::GetOverlap(const Volume& other) const
{
if (min.x > other.max.x || min.y > other.max.y || min.z > other.max.z || max.x < other.min.x ||
max.y < other.min.y || max.z < other.min.z)
return Overlap{false, Volume{0, Index3D{}, Index3D{}}};
return Overlap{
true,
Volume{-other.sign,
Index3D{std::max(min.x, other.min.x), std::max(min.y, other.min.y), std::max(min.z, other.min.z)},
Index3D{std::min(max.x, other.max.x), std::min(max.y, other.max.y), std::min(max.z, other.max.z)}}};
}
REGISTER_DAY(2021, Day22, std::vector<Volume>, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day22, ExampleInput, 1, 474140);
REGISTER_TEST(2021, Day22, Input, 1, 596598);
REGISTER_TEST_EXAMPLE(2021, Day22, ExampleInput, 2, 2758514936282235);
REGISTER_TEST(2021, Day22, Input, 2, 1199121349148621);
READ_INPUT(input)
{
std::vector<Volume> volumes;
std::string str;
while (getline(input, str))
{
Volume volume;
std::stringstream ss{str};
std::string s;
ss >> s >> "x=" >> volume.min.x >> ".." >> volume.max.x >> "," >> "y=" >> volume.min.y >> ".." >> volume.max.y >>
"," >> "z=" >> volume.min.z >> ".." >> volume.max.z;
volume.sign = s == "on" ? 1 : -1;
volumes.emplace_back(volume);
}
return volumes;
}
OUTPUT1(input)
{
Array3D<char> values{101, 101, 101};
values.Fill('.');
for (auto& region : input)
{
for (int z = std::max(region.min.z, -50); z <= std::min(region.max.z, 50); z++)
{
for (int y = std::max(region.min.y, -50); y <= std::min(region.max.y, 50); y++)
{
for (int x = std::max(region.min.x, -50); x <= std::min(region.max.x, 50); x++)
{
if (values.IsInside(Index3D{x + 50, y + 50, z + 50}))
{
values.Set(x + 50, y + 50, z + 50, region.sign > 0 ? '#' : '.');
}
}
}
}
}
return values.Count('#');
}
OUTPUT2(input)
{
std::vector<Volume> volumes;
for (auto& volume : input)
{
size_t size = volumes.size();
for (size_t i = 0; i < size; i++)
{
Overlap overlap = volume.GetOverlap(volumes[i]);
if (overlap)
{
volumes.emplace_back(overlap.volume);
}
}
if (volume.sign > 0)
{
volumes.emplace_back(volume);
}
}
return Helper::Sum<int64_t>(volumes,
[](int64_t sum, const Volume& vol) { return sum + vol.GetCubes() * vol.sign; });
}
}
+243
View File
@@ -0,0 +1,243 @@
#include "common/aoc.h"
namespace y2021::day23
{
using State = std::map<Index2D, char>;
bool Find(const State& state, const Index2D& pos, char c)
{
auto it = state.find(pos);
if (it != state.end())
return it->second == c;
return false;
}
bool ValidateState(int height, const State& state)
{
return Find(state, {2, 1}, 'A') && Find(state, {2, 2}, 'A') && Find(state, {4, 1}, 'B') &&
Find(state, {4, 2}, 'B') && Find(state, {6, 1}, 'C') && Find(state, {6, 2}, 'C') &&
Find(state, {8, 1}, 'D') && Find(state, {8, 2}, 'D');
}
int Heuristic(int height, const State& state)
{
int h = 0;
for (auto& piece : state)
{
// Cost to move piece to the top of the room
if (piece.second == 'A' && piece.first.x != 2)
h += std::abs(piece.first.x - 2) + std::abs(piece.first.y - 0) + 1;
if (piece.second == 'B' && piece.first.x != 4)
h += (std::abs(piece.first.x - 4) + std::abs(piece.first.y - 0) + 1) * 10;
if (piece.second == 'C' && piece.first.x != 6)
h += (std::abs(piece.first.x - 6) + std::abs(piece.first.y - 0) + 1) * 100;
if (piece.second == 'D' && piece.first.x != 8)
h += (std::abs(piece.first.x - 8) + std::abs(piece.first.y - 0) + 1) * 1000;
}
return h;
}
int GetCost(char c)
{
switch (c)
{
case 'A':
return 1;
case 'B':
return 10;
case 'C':
return 100;
case 'D':
return 1000;
}
std::cout << "Invalid char: " << c << std::endl;
return 0;
}
std::vector<std::pair<int, State>> ValidStates(int height, const State& state)
{
std::vector<std::pair<int, State>> newStates;
for (auto& piece : state)
{
if (piece.first.y > 0)
{ // Piece is in the room, move to hallway
// Check if already at correct position
bool canMove = false;
if (piece.first.x == (piece.second - 'A') * 2 + 2)
{
for (int i = piece.first.y + 1; i < 1 + height; i++)
{
if (state.find({piece.first.x, i})->second != piece.second)
{
canMove = true;
break;
}
}
}
else
canMove = true;
// Check if piece is obstructed by others in the room
for (int i = piece.first.y - 1; i > 0; i--)
{
if (state.count({piece.first.x, i}) != 0)
{
canMove = false;
break;
}
}
if (canMove)
{
// Check hallways to the left
for (int i = piece.first.x - 1; i >= 0; i--)
{
// Is valid position in hallway
if (i == 0 || i % 2 == 1 || i == 10)
{
if (state.count({i, 0}) == 0)
{
State newState = state;
newState[{i, 0}] = piece.second;
newState.erase(piece.first);
newStates.emplace_back(std::pair<int, State>{
(piece.first.y + std::abs(piece.first.x - i)) * GetCost(piece.second), newState});
}
else
break;
}
}
// Check hallways to the right
for (int i = piece.first.x + 1; i < 11; i++)
{
// Is valid position in hallway
if (i == 0 || i % 2 == 1 || i == 10)
{
if (state.count({i, 0}) == 0)
{
State newState = state;
newState[{i, 0}] = piece.second;
newState.erase(piece.first);
newStates.emplace_back(std::pair<int, State>{
(piece.first.y + std::abs(piece.first.x - i)) * GetCost(piece.second), newState});
}
else
break;
}
}
}
}
else
{ // Piece is in the hallway, move to room
int x = (piece.second - 'A') * 2 + 2;
int dir = Helper::Sign(x - piece.first.x);
bool canMove = true;
// Check if hallway is clear to correct position
for (int i = piece.first.x + dir; (dir < 0 && i > x) || (dir > 0 && i < x); i += dir)
{
if (state.count({i, 0}) != 0)
{
canMove = false;
break;
}
}
if (canMove)
{
// Check if room is filled with same piece or no pieces
int pos = height;
for (int i = 1; i < 1 + height; i++)
{
if (state.count({x, i}) != 0)
{
if (state.find({x, i})->second == piece.second)
{
if (pos == height)
pos = i - 1;
}
else
{
pos = 0;
break;
}
}
}
if (pos != 0)
{
State newState = state;
newState[{x, pos}] = piece.second;
newState.erase(piece.first);
newStates.emplace_back(
std::pair<int, State>{(pos + std::abs(piece.first.x - x)) * GetCost(piece.second), newState});
}
}
}
}
return newStates;
}
int Solve(const State& state, int h)
{
return Helper::AStar(h, state, Heuristic, ValidStates, ValidateState);
}
REGISTER_DAY(2021, Day23, State, int);
REGISTER_TEST_EXAMPLE(2021, Day23, ExampleInput, 1, 12521);
REGISTER_TEST(2021, Day23, Input, 1, 14350);
REGISTER_TEST_EXAMPLE(2021, Day23, ExampleInput, 2, 44169);
REGISTER_TEST(2021, Day23, Input, 2, 49742);
READ_INPUT(input)
{
std::string str;
getline(input, str);
getline(input, str);
getline(input, str);
std::map<Index2D, char> state;
state.emplace(Index2D{2, 1}, str[3]);
state.emplace(Index2D{4, 1}, str[5]);
state.emplace(Index2D{6, 1}, str[7]);
state.emplace(Index2D{8, 1}, str[9]);
getline(input, str);
state.emplace(Index2D{2, 2}, str[3]);
state.emplace(Index2D{4, 2}, str[5]);
state.emplace(Index2D{6, 2}, str[7]);
state.emplace(Index2D{8, 2}, str[9]);
return state;
}
OUTPUT1(input)
{
return Solve(input, 2);
}
OUTPUT2(input)
{
State state;
for (auto& piece : input)
{
if (piece.first.y == 2)
state.emplace(Index2D{piece.first.x, 4}, piece.second);
else
state.emplace(piece.first, piece.second);
}
state.emplace(Index2D{2, 2}, 'D');
state.emplace(Index2D{2, 3}, 'D');
state.emplace(Index2D{4, 2}, 'C');
state.emplace(Index2D{4, 3}, 'B');
state.emplace(Index2D{6, 2}, 'B');
state.emplace(Index2D{6, 3}, 'A');
state.emplace(Index2D{8, 2}, 'A');
state.emplace(Index2D{8, 3}, 'C');
return Solve(state, 4);
}
}
+126
View File
@@ -0,0 +1,126 @@
#include "common/aoc.h"
namespace y2021::day24
{
enum class Operation
{
Inp,
Add,
Mul,
Div,
Mod,
Eql
};
struct Instruction
{
Operation operation;
char dst;
std::string src;
};
int64_t Read(const std::string& str, const std::map<char, int64_t>& data)
{
if (str[0] >= 'a' && str[0] <= 'z')
{
auto it = data.find(str[0]);
if (it != data.end())
return it->second;
return 0;
}
return atoll(str.c_str());
};
int64_t Read(char c, const std::map<char, int64_t>& data)
{
auto it = data.find(c);
if (it != data.end())
return it->second;
return 0;
}
bool ValidateInput(const std::vector<Instruction>& instructions, const std::string& str)
{
int inputOffset = 0;
std::map<char, int64_t> data;
for (int i = 0; i < instructions.size(); i++)
{
switch (instructions[i].operation)
{
case Operation::Inp:
data[instructions[i].dst] = str[inputOffset++] - '0';
break;
case Operation::Add:
data[instructions[i].dst] = Read(instructions[i].dst, data) + Read(instructions[i].src, data);
break;
case Operation::Mul:
data[instructions[i].dst] = Read(instructions[i].dst, data) * Read(instructions[i].src, data);
break;
case Operation::Div:
data[instructions[i].dst] = Read(instructions[i].dst, data) / Read(instructions[i].src, data);
break;
case Operation::Mod:
data[instructions[i].dst] = Read(instructions[i].dst, data) % Read(instructions[i].src, data);
break;
case Operation::Eql:
data[instructions[i].dst] = Read(instructions[i].dst, data) == Read(instructions[i].src, data) ? 1 : 0;
break;
default:
std::cout << "Invalid operation" << std::endl;
}
}
return data['z'] == 0;
}
REGISTER_DAY(2021, Day24, std::vector<Instruction>, int64_t);
REGISTER_TEST(2021, Day24, Input, 1, 99919765949498);
REGISTER_TEST(2021, Day24, Input, 2, 24913111616151);
READ_INPUT(input)
{
std::vector<Instruction> instructions;
std::string str;
while (getline(input, str))
{
Instruction instruction;
std::string_view sv(str.c_str(), 3);
if (sv == "inp")
instruction.operation = Operation::Inp;
else if (sv == "add")
instruction.operation = Operation::Add;
else if (sv == "mul")
instruction.operation = Operation::Mul;
else if (sv == "div")
instruction.operation = Operation::Div;
else if (sv == "mod")
instruction.operation = Operation::Mod;
else if (sv == "eql")
instruction.operation = Operation::Eql;
else
std::cout << "Invalid operation: " << sv << std::endl;
instruction.dst = str[4];
if (instruction.operation != Operation::Inp)
instruction.src = str.substr(6);
instructions.emplace_back(instruction);
}
return instructions;
}
OUTPUT1(input)
{
std::string str = "99919765949498";
if (ValidateInput(input, str))
return atoll(str.c_str());
return 0;
}
OUTPUT2(input)
{
std::string str = "24913111616151";
if (ValidateInput(input, str))
return atoll(str.c_str());
return 0;
}
}
+66
View File
@@ -0,0 +1,66 @@
#include "common/aoc.h"
namespace y2021::day25
{
REGISTER_DAY(2021, Day25, Array2D<char>, int);
REGISTER_TEST_EXAMPLE(2021, Day25, ExampleInput, 1, 58);
REGISTER_TEST(2021, Day25, Input, 1, 419);
READ_INPUT(input)
{
return Input::ReadArray2D(input);
}
OUTPUT1(inputConst)
{
Array2D<char> input = inputConst;
bool hasMoved = true;
int i = 0;
while (hasMoved)
{
hasMoved = false;
Array2D<char> cpy = input;
Index2D index{0, 0};
for (auto& c : cpy)
{
if (c == '>')
{
Index2D newIndex = index;
newIndex.x = (newIndex.x + 1) % cpy.width;
if (cpy[newIndex] == '.')
{
input[newIndex] = '>';
input[index] = '.';
hasMoved = true;
}
}
cpy.Increment(index);
}
cpy = input;
index = {0, 0};
for (auto& c : cpy)
{
if (c == 'v')
{
Index2D newIndex = index;
newIndex.y = (newIndex.y + 1) % cpy.height;
if (cpy[newIndex] == '.')
{
input[newIndex] = 'v';
input[index] = '.';
hasMoved = true;
}
}
cpy.Increment(index);
}
i++;
}
return i;
}
OUTPUT2(input)
{
return 0;
}
}