Add 2021 solutions
This commit is contained in:
@@ -8,13 +8,9 @@ fi
|
|||||||
list=$(find -name "Day*.cpp" | awk -F '/' '{print $3 "/" $4}' | awk -F '.' '{print $1}' | sed 's/Day//g' | sort)
|
list=$(find -name "Day*.cpp" | awk -F '/' '{print $3 "/" $4}' | awk -F '.' '{print $1}' | sed 's/Day//g' | sort)
|
||||||
|
|
||||||
for item in $list; do
|
for item in $list; do
|
||||||
echo $item
|
|
||||||
year=$(echo $item | awk -F '/' '{print $1}')
|
year=$(echo $item | awk -F '/' '{print $1}')
|
||||||
day=$(echo $item | awk -F '/' '{print $2}')
|
day=$(echo $item | awk -F '/' '{print $2}')
|
||||||
echo "year: $year"
|
|
||||||
echo "day: $day"
|
|
||||||
dir="res/$year/day$day/input.txt"
|
dir="res/$year/day$day/input.txt"
|
||||||
echo $dir
|
|
||||||
if [ ! -e $dir ]; then
|
if [ ! -e $dir ]; then
|
||||||
webitem=$(echo $day | sed 's/^0//g')
|
webitem=$(echo $day | sed 's/^0//g')
|
||||||
echo "Fetching $dir"
|
echo "Fetching $dir"
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
199
|
||||||
|
200
|
||||||
|
208
|
||||||
|
210
|
||||||
|
200
|
||||||
|
207
|
||||||
|
240
|
||||||
|
269
|
||||||
|
260
|
||||||
|
263
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
forward 5
|
||||||
|
down 5
|
||||||
|
forward 8
|
||||||
|
up 3
|
||||||
|
down 8
|
||||||
|
forward 2
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
00100
|
||||||
|
11110
|
||||||
|
10110
|
||||||
|
10111
|
||||||
|
10101
|
||||||
|
01111
|
||||||
|
00111
|
||||||
|
11100
|
||||||
|
10000
|
||||||
|
11001
|
||||||
|
00010
|
||||||
|
01010
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
3,4,3,1,2
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
16,1,2,0,4,2,7,1,2,14
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
2199943210
|
||||||
|
3987894921
|
||||||
|
9856789892
|
||||||
|
8767896789
|
||||||
|
9899965678
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[({(<(())[]>[[{[]{<()<>>
|
||||||
|
[(()[<>])]({[<{<<[]>>(
|
||||||
|
{([(<{}[<>[]}>{[]{[(<()>
|
||||||
|
(((({<>}<{<{<>}{[]{[]{}
|
||||||
|
[[<[([]))<([[{}[[()]]]
|
||||||
|
[{[{({}]{}}([{[{{{}}([]
|
||||||
|
{<[[]]>}<{[{[{[]{()[[[]
|
||||||
|
[<(<(<(<{}))><([]([]()
|
||||||
|
<{([([[(<>()){}]>(<<{{
|
||||||
|
<{([{{}}[<[[[<>{}]]]>[]]
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
5483143223
|
||||||
|
2745854711
|
||||||
|
5264556173
|
||||||
|
6141336146
|
||||||
|
6357385478
|
||||||
|
4167524645
|
||||||
|
2176841721
|
||||||
|
6882881134
|
||||||
|
4846848554
|
||||||
|
5283751526
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
start-A
|
||||||
|
start-b
|
||||||
|
A-c
|
||||||
|
A-b
|
||||||
|
b-d
|
||||||
|
A-end
|
||||||
|
b-end
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
1163751742
|
||||||
|
1381373672
|
||||||
|
2136511328
|
||||||
|
3694931569
|
||||||
|
7463417111
|
||||||
|
1319128137
|
||||||
|
1359912421
|
||||||
|
3125421639
|
||||||
|
1293138521
|
||||||
|
2311944581
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
9C0141080250320F1802104A08
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
target area: x=20..30, y=-10..-5
|
||||||
@@ -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]]]
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
|
||||||
|
|
||||||
|
#..#.
|
||||||
|
#....
|
||||||
|
##..#
|
||||||
|
..#..
|
||||||
|
..###
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Player 1 starting position: 4
|
||||||
|
Player 2 starting position: 8
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#############
|
||||||
|
#...........#
|
||||||
|
###B#C#B#D###
|
||||||
|
#A#D#C#A#
|
||||||
|
#########
|
||||||
@@ -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.>
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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; });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user