-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay09.cs
84 lines (70 loc) · 4.09 KB
/
Day09.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
using System.Reflection;
using WinstonPuckett.PipeExtensions;
public static class Day09
{
static IEnumerable<long> Concat(this IEnumerable<long> list, long value) => list.Concat(new[] { value });
private static async Task<long[][]> GetInput() =>
await Inputs
.Read(MethodBase.GetCurrentMethod()?.DeclaringType?.FullName?.Split("+").First() ?? "")
.Select(text => text.Select(i => long.Parse(i.ToString())).ToArray())
.ToArrayAsync();
record Location((long X, long Y) Position, long Value, long[] Adjacents, bool IsLowerPoint);
private static IEnumerable<Location> GetLocations(long[][] input) =>
Enumerable.Range(0, input.Length).SelectMany(i =>
Enumerable.Range(0, input[i].Length).Select(j =>
{
var position = (x: (long)i, y: (long)j);
var value = input[i][j];
var adjacents =
(HasTop(i) ? new long[]{GetTop(input, i, j)} : Array.Empty<long>()).Pipe(adj =>
HasBottom(input, i) ? adj.Concat(GetBelow(input, i, j)) : adj).Pipe(adj =>
HasLeft(j) ? adj.Concat(GetLeft(input, i, j)) : adj).Pipe(adj =>
HasRight(input, i, j) ? adj.Concat(GetRight(input, i, j)) : adj)
.ToArray();
var isLowerPointer = adjacents.All(adj => adj > value);
return new Location(position, value, adjacents, isLowerPointer);
}));
private static bool HasTop(long i) => i > 0;
private static bool HasRight(long[][] input, long i, long j) => j < (input[i].Length - 1);
private static bool HasBottom(long[][] input, long i) => i < (input.Length - 1);
private static bool HasLeft(long j) => j > 0;
private static long GetTop(long[][] input, long i, long j) => input[i - 1][j];
private static long GetRight(long[][] input, long i, long j) => input[i][j + 1];
private static long GetBelow(long[][] input, long i, long j) => input[i + 1][j];
private static long GetLeft(long[][] input, long i, long j) => input[i][j - 1];
private static bool TopIsHigherLocation(long[][] input, long i, long j, long value) => GetTop(input, i, j) > value;
private static bool RightIsHigherLocation(long[][] input, long i, long j, long value) => GetRight(input, i, j) > value;
private static bool BelowIsHigherLocation(long[][] input, long i, long j, long value) => GetBelow(input, i, j) > value;
private static bool LeftIsHigherLocation(long[][] input, long i, long j, long value) => GetLeft(input, i, j) > value;
public static async Task<object> One() =>
(await GetInput())
.Pipe(GetLocations)
.Pipe(locations => locations.Where(x => x.IsLowerPoint))
.Sum(x => (x.Value + 1));
static IEnumerable<(long i, long j)> GetBasin(long[][] input, long i, long j, IEnumerable<(long i, long j)> sizes)
{
if (sizes.Contains((i, j)) && sizes.Count() > 1) return sizes;
sizes = sizes.ToList().Concat(new[] { (i, j) });
var value = input[i][j];
var GoUp = HasTop(i) && TopIsHigherLocation(input, i, j, value) && GetTop(input, i, j) != 9;
if (GoUp) sizes = GetBasin(input, i - 1, j, sizes);
var GoDown = HasBottom(input, i) && BelowIsHigherLocation(input, i, j, value) && GetBelow(input, i, j) != 9;
if (GoDown) sizes = GetBasin(input, i + 1, j, sizes);
var GoLeft = HasLeft(j) && LeftIsHigherLocation(input, i, j, value) && GetLeft(input, i, j) != 9;
if (GoLeft) sizes = GetBasin(input, i, j - 1, sizes);
var GoRight = HasRight(input, i, j) && RightIsHigherLocation(input, i, j, value) && GetRight(input, i, j) != 9;
if (GoRight) sizes = GetBasin(input, i, j + 1, sizes);
return sizes;
}
public static async Task<object> Two() =>
(await GetInput())
.Pipe(input =>
GetLocations(input)
.Where(x => x.IsLowerPoint)
.Select(l =>
GetBasin(input, l.Position.X, l.Position.Y, new (long, long)[] { (l.Position.X, l.Position.Y) })
.Distinct()))
.OrderByDescending(y => y.Count())
.Take(3)
.Aggregate(1, (x, y) => x * y.Count());
}