-
Notifications
You must be signed in to change notification settings - Fork 0
/
2017_03.cs
105 lines (89 loc) · 3.22 KB
/
2017_03.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
namespace AOC.CSharp;
public static class AOC2017_03
{
private static readonly Dictionary<Directions, DirectionInfo> DirectionLookup =
new()
{
{
Directions.Right,
new DirectionInfo(Directions.Up, 0, xy => xy with { X = xy.X + 1 })
},
{
Directions.Up,
new DirectionInfo(Directions.Left, 1, xy => xy with { Y = xy.Y - 1 })
},
{
Directions.Left,
new DirectionInfo(Directions.Down, 0, xy => xy with { X = xy.X - 1 })
},
{
Directions.Down,
new DirectionInfo(Directions.Right, 1, xy => xy with { Y = xy.Y + 1 })
},
};
public static long Solve1(string[] lines)
{
return SolveBoth(int.Parse(lines[0])).Item1;
}
public static long Solve2(string[] lines)
{
return SolveBoth(int.Parse(lines[0])).Item2;
}
private static (int, int) SolveBoth(int target)
{
int dimensions = (int)Math.Sqrt(target) + 10;
int[,] a = new int[dimensions, dimensions];
XY start = new(dimensions / 2, dimensions / 2);
XY curr = start;
int nextDirectionTravelAmount = 1;
int remainingTravelAmount = 1;
Directions direction = Directions.Right;
int? part2Result = null;
for (int i = 1; i < target; i++)
{
int neighborSum = Math.Max(1, SumNeighbors(a, curr));
a[curr.X, curr.Y] = neighborSum;
if (!part2Result.HasValue && neighborSum > target)
{
part2Result = neighborSum;
}
var initialInfo = DirectionLookup[direction];
if (remainingTravelAmount == 0)
{
// Not going any further in this direction. Time to turn and reset the
// steps we need to head in the next direction. This step count grows when
// we make certain turns
direction = initialInfo.Next;
nextDirectionTravelAmount += initialInfo.StartAdjust;
remainingTravelAmount = nextDirectionTravelAmount;
}
// Advance one in the proper direction and adjust our coordinates
var revisedInfo = DirectionLookup[direction];
curr = revisedInfo.PosAdjust(curr);
remainingTravelAmount--;
}
return (Math.Abs(curr.X - start.X) + Math.Abs(curr.Y - start.Y), part2Result.Value);
}
private static int SumNeighbors(int[,] grid, XY curr)
{
int sum = 0;
sum += grid[curr.X - 1, curr.Y - 1]; // NW
sum += grid[curr.X, curr.Y - 1]; // N
sum += grid[curr.X + 1, curr.Y - 1]; // NE
sum += grid[curr.X + 1, curr.Y]; // E
sum += grid[curr.X + 1, curr.Y + 1]; // SE
sum += grid[curr.X, curr.Y + 1]; // S
sum += grid[curr.X - 1, curr.Y + 1]; // SW
sum += grid[curr.X - 1, curr.Y]; // W
return sum;
}
private enum Directions
{
Right,
Up,
Left,
Down,
}
private record DirectionInfo(Directions Next, int StartAdjust, Func<XY, XY> PosAdjust);
private record XY(int X, int Y);
}