Skip to content

Commit 70e9ec1

Browse files
committed
Merge branch 'master' of github.com:Bpendragon/AdventOfCodeCSharp
2 parents 19ad9b1 + dc65399 commit 70e9ec1

File tree

5 files changed

+320
-31
lines changed

5 files changed

+320
-31
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

AdventOfCode/Solutions/Year2023/Day20-Solution.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ protected override object SolvePartOne()
6464
long lowPulses = 0;
6565
long highPulses = 0;
6666

67-
for(int i = 0; i < 1000; i++)
67+
for(int i = 1; i <= 1000; i++)
6868
{
6969
modules["button"].incomingPulses.Enqueue(("finger", false));
7070
processOrder.Enqueue("button");
7171

7272
while(processOrder.TryDequeue(out string nextPulseTarget))
7373
{
7474
(long pulsesSent, bool pulseVal) = modules[nextPulseTarget].ProcessPulse();
75-
75+
if (rxConjunctions.ContainsKey(nextPulseTarget) && rxConjunctions[nextPulseTarget] == 0 && pulseVal) rxConjunctions[nextPulseTarget] = i;
7676
if (pulseVal) highPulses += pulsesSent;
7777
else lowPulses += pulsesSent;
7878
}
@@ -83,9 +83,7 @@ protected override object SolvePartOne()
8383

8484
protected override object SolvePartTwo()
8585
{
86-
foreach (var m in modules.Values) m.Reset();
87-
88-
for (int i = 1; ; i++)
86+
for (int i = 1001; ; i++)
8987
{
9088
modules["button"].incomingPulses.Enqueue(("finger", false));
9189
processOrder.Enqueue("button");
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+
}
Lines changed: 125 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,147 @@
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;
9-
using static AdventOfCode.Solutions.Utilities;
10-
using System.Runtime.CompilerServices;
4+
using System.Linq;
115

126
namespace AdventOfCode.Solutions.Year2023
137
{
148
[DayInfo(22, 2023, "")]
159
class Day22 : ASolution
1610
{
11+
List<Brick> AllBricks = new();
12+
Dictionary<char, int> BrickFallCounts = new();
1713
public Day22() : base()
1814
{
15+
char i = 'A';
16+
foreach (var l in Input.SplitByNewline())
17+
{
18+
var n = l.ExtractInts().ToList();
19+
Brick tmp = new(i, (n[0], n[1], n[2]), (n[3], n[4], n[5]));
20+
AllBricks.Add(tmp);
21+
i++;
22+
}
23+
24+
25+
//Shift bricks that can move down until everyone is settled
26+
int numBricksShifted;
27+
do
28+
{
29+
numBricksShifted = 0;
30+
31+
HashSet<Coordinate3D> AllBrickPoints = new();
32+
33+
foreach (var b in AllBricks) foreach (var p in b.Members()) AllBrickPoints.Add(p);
34+
35+
foreach (var b in AllBricks)
36+
{
37+
if (b.Members().Any(m => m.z == 1 || (AllBrickPoints.Contains(m - (0, 0, 1)) && !b.Members().Contains(m - (0, 0, 1))))) continue;
1938

39+
b.Start = b.Start - (0, 0, 1);
40+
b.End = b.End - (0, 0, 1);
41+
numBricksShifted++;
42+
}
43+
44+
45+
} while (numBricksShifted != 0);
46+
47+
AllBricks.Sort((a, b) => a.Start.z.CompareTo(b.Start.z));
48+
49+
//Get everyone's interactions with one another.
50+
foreach(var b in AllBricks)
51+
{
52+
foreach(var p in AllBricks.Where(a => a.Start.z == b.End.z + 1))
53+
{
54+
foreach(var m in b.Members())
55+
{
56+
if(p.Members().Any(a => a.x == m.x && a.y == m.y && a.z - 1 == m.z))
57+
{
58+
b.Supports.Add(p);
59+
p.SupportedBy.Add(b);
60+
break;
61+
}
62+
}
63+
}
64+
}
65+
66+
foreach (var b in AllBricks) BrickFallCount(b, new(), true);
2067
}
2168

2269
protected override object SolvePartOne()
2370
{
24-
return null;
71+
return BrickFallCounts.Count(kvp => kvp.Value == 0);
2572
}
2673

2774
protected override object SolvePartTwo()
2875
{
29-
return null;
76+
return BrickFallCounts.Sum(k => k.Value);
77+
}
78+
79+
private void BrickFallCount(Brick b, List<char> toIgnore, bool updateDict = false)
80+
{
81+
toIgnore.Add(b.id);
82+
if(b.Supports.Count == 0)
83+
{
84+
if(updateDict)BrickFallCounts[b.id] = 0;
85+
}
86+
87+
//Collect all that would fall with the removal of that support
88+
var bricksThatFall = b.Supports.Where(p => p.SupportedBy.Count(a => !toIgnore.Contains(a.id)) == 0).ToList();
89+
foreach (var p in bricksThatFall)
90+
{
91+
toIgnore.Add(p.id);
92+
}
93+
94+
foreach(var p in bricksThatFall)
95+
{
96+
BrickFallCount(p, toIgnore);
97+
}
98+
99+
if(updateDict) BrickFallCounts[b.id] = toIgnore.Distinct().Count() - 1;
100+
}
101+
102+
private class Brick
103+
{
104+
public char id;
105+
public Coordinate3D Start;
106+
public Coordinate3D End;
107+
108+
public List<Brick> Supports = new();
109+
public List<Brick> SupportedBy = new();
110+
111+
public int Length => Start.ManhattanDistance(End) + 1;
112+
113+
public IEnumerable<Coordinate3D> Members()
114+
{
115+
yield return Start;
116+
var curLoc = Start;
117+
while (curLoc != End)
118+
{
119+
if (Start.x == End.x && Start.y == End.y) curLoc = curLoc + (0, 0, 1); //Vertically Oriented Brick
120+
else if (Start.x == End.x && Start.z == End.z) curLoc = curLoc + (0, 1, 0); //Oriented Along Y- Axis
121+
else if (Start.y == End.y && Start.z == End.z) curLoc = curLoc + (1, 0, 0); //Oriented Along x- Axis
122+
yield return curLoc;
123+
}
124+
}
125+
126+
public Brick(char id, Coordinate3D p1, Coordinate3D p2)
127+
{
128+
this.id = id;
129+
if (p1.x < p2.x || p1.y < p2.y || p1.z < p2.z)
130+
{
131+
Start = p1;
132+
End = p2;
133+
}
134+
else
135+
{
136+
Start = p2;
137+
End = p2;
138+
}
139+
}
140+
141+
public override string ToString()
142+
{
143+
return id.ToString();
144+
}
30145
}
31146
}
32-
}
147+
}

0 commit comments

Comments
 (0)