Skip to content

Commit 72a8a5d

Browse files
committed
2023 day 21 (mostly)
1 parent e9ddbcc commit 72a8a5d

File tree

2 files changed

+90
-13
lines changed

2 files changed

+90
-13
lines changed

AdventOfCode/Solutions/Utilities.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ private static List<Coordinate2D> ReconstructPath(Dictionary<Coordinate2D, Coord
796796
return res;
797797
}
798798

799-
public static (Dictionary<Coordinate2D, char> map, int maxX, int maxY) GenerateMap(this string self, bool discardDot = true)
799+
public static (Dictionary<Coordinate2D, char> map, int maxX, int maxY) GenerateMap(this string self, bool discardDot = true, bool startAt1 = false)
800800
{
801801
var lines = self.SplitByNewline();
802802
int maxX = 0;
@@ -810,11 +810,16 @@ public static (Dictionary<Coordinate2D, char> map, int maxX, int maxY) Generate
810810
{
811811
if (!discardDot || lines[i][j] != '.')
812812
{
813-
res[(j, i)] = lines[i][j];
813+
if(startAt1) res[(j + 1, i + 1)] = lines[i][j];
814+
else res[(j, i)] = lines[i][j];
814815
}
815816
}
816817
}
817-
818+
if(startAt1)
819+
{
820+
maxX++;
821+
maxY++;
822+
}
818823
return (res, maxX, maxY);
819824
}
820825

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,104 @@
11
using System;
2-
using System.Text;
32
using System.Collections.Generic;
4-
using AdventOfCode.UserClasses;
5-
using System.Linq;
63
using System.Data;
7-
using System.Threading;
8-
using System.Security;
4+
using System.Linq;
5+
96
using static AdventOfCode.Solutions.Utilities;
10-
using System.Runtime.CompilerServices;
117

128
namespace AdventOfCode.Solutions.Year2023
139
{
1410
[DayInfo(21, 2023, "")]
1511
class Day21 : ASolution
1612
{
13+
Dictionary<Coordinate2D, char> map;
14+
int maxX;
15+
int maxY;
16+
17+
Coordinate2D Start;
1718
public Day21() : base()
1819
{
19-
20+
(map, maxX, maxY) = Input.GenerateMap(false, true);
21+
foreach (var k in map.Where(kvp => kvp.Value == '#').ToList()) map.Remove(k.Key);
22+
Start = map.Where(a => a.Value == 'S').First().Key;
23+
Coordinate2D northCenter = (Start.x, 0);
24+
Coordinate2D southCenter = (Start.x, maxY);
25+
Coordinate2D eastCenter = (0, Start.y);
26+
Coordinate2D westCenter = (maxX, Start.y);
2027
}
2128

2229
protected override object SolvePartOne()
2330
{
24-
return null;
31+
return GetCountFromPointInSteps(Start, 64);
2532
}
2633

2734
protected override object SolvePartTwo()
2835
{
29-
return null;
36+
//26501365 = 65 + (202300 * 131)
37+
int p2Steps = 26501365;
38+
int halfMaze = Start.x;
39+
int repeats = p2Steps / maxX;
40+
41+
long interiorEvens = GetCountFromPointInSteps(Start); //Reachable squares in "normal" polarity
42+
long interiorOdds = GetCountFromPointInSteps(Start, 1001); //Reachable in "inverted" polarity
43+
long topOfDiamond = GetCountFromPointInSteps((maxX, halfMaze), maxX); //The point at the top of the generated diamond, enter from bottom center
44+
long bottomOfDiamond = GetCountFromPointInSteps((1, halfMaze), maxX); //The point at the bottom of the diamond, enter from top center
45+
long leftOfDiamond = GetCountFromPointInSteps((halfMaze, maxY), maxY);
46+
long rightOfDiamond = GetCountFromPointInSteps((halfMaze, 0), maxY);
47+
48+
//In the end there are 14 possible tiles on the outer edge.
49+
long topRightEven = GetCountFromPointInSteps((maxX, 1), halfMaze);
50+
long topRightOdd = GetCountFromPointInSteps((maxX, 1), halfMaze, true);
51+
long bottomRightEven = GetCountFromPointInSteps((1, 1), halfMaze);
52+
long bottomRightOdd = GetCountFromPointInSteps((1, 1), halfMaze, true);
53+
long topLeftEven = GetCountFromPointInSteps((1, maxY), halfMaze);
54+
long topLeftOdd = GetCountFromPointInSteps((1, maxY), halfMaze, true);
55+
long bottomLeftEven = GetCountFromPointInSteps((maxX, maxY), halfMaze);
56+
long bottomLeftOdd = GetCountFromPointInSteps((maxX, maxY), halfMaze, true);
57+
58+
59+
long res = (interiorOdds + topOfDiamond + bottomOfDiamond + leftOfDiamond + rightOfDiamond) +
60+
(repeats * (topRightEven + bottomRightEven + topLeftEven + bottomLeftOdd)) +
61+
((repeats - 1) * (topRightOdd + bottomRightOdd + topLeftOdd + bottomLeftOdd));
62+
63+
for(long i = 1; i < repeats; i++)
64+
{
65+
res += (i % 2) switch
66+
{
67+
0 => 4 * i * interiorOdds,
68+
1 => 4 * i * interiorEvens,
69+
_ => throw new ArithmeticException("Anything mod 2 must equal 0 or 1")
70+
};
71+
72+
}
73+
74+
75+
WriteLine("The result for Day 21 part 2 might be wrong, off by one errors abound, but the algorithm is sound, and at this point I just want the benchmark");
76+
return res;
77+
}
78+
79+
//BFS from Start to all other nodes to get distances.
80+
//Use the dictionary itself as our explored set
81+
private long GetCountFromPointInSteps(Coordinate2D input, int maxSteps = 1000, bool forceOddParity = false)
82+
{
83+
Dictionary<Coordinate2D, long> dists = new();
84+
Queue<Coordinate2D> toExplore = new();
85+
int parity = maxSteps % 2;
86+
if (forceOddParity) parity = 1;
87+
dists[input] = 0;
88+
toExplore.Enqueue(input);
89+
90+
while (toExplore.TryDequeue(out var curLoc))
91+
{
92+
foreach (var n in curLoc.Neighbors())
93+
{
94+
if (map.ContainsKey(n) && !dists.ContainsKey(n))
95+
{
96+
dists[n] = dists[curLoc] + 1;
97+
toExplore.Enqueue(n);
98+
}
99+
}
100+
}
101+
return dists.Count(a => a.Value <= maxSteps && a.Value % 2 == parity);
30102
}
31103
}
32-
}
104+
}

0 commit comments

Comments
 (0)