diff --git a/AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs b/AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs index 3e93bd5..fa4c455 100644 --- a/AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs +++ b/AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; + namespace AdventOfCode.Problems.AOC2024.Day12; [ProblemInfo(2024, 12, "Garden Groups")] @@ -13,7 +15,7 @@ internal class GardenGroups : Problem { private char[][] _data = []; - public readonly static Vec2[] DIRS = [ + public static readonly Vec2[] DIRS = [ new(0,1), new(1,0), new(0,-1), @@ -28,28 +30,138 @@ internal class GardenGroups : Problem public override void CalculatePart2() { - var r = FindPlots(_data).Select(plot => (plot.plant, plot.area.Count, CountSides(plot.outline))); + var plots = FindPlots(_data); + var r = plots.Select(plot => (plot.plant, area: plot.area.Count, sides: CountSides(GroupSides(plot.outline), plot.area))); + foreach (var item in plots) + { + Console.WriteLine($"{item.plant}: {CountSides(GroupSides(item.outline), item.area)}"); + var groups = GroupSides(item.outline); + DrawPlot(item.area, groups, item.plant); + } + Part2 = r.Sum(v => v.area * v.sides); } - private static int CountSides(List> perimeter) + public static List>> GroupSides(List> outline) { - if (perimeter.Count <= 2) - return 4; - var sides = 1; + var result = new List>>(); + var visited = new HashSet>(); + var open = new HashSet>(outline); - var lastDir = new Vec2(0,0); - //var startDir = lastDir; - for (int i = 0; i < perimeter.Count; i++) - { - var p = perimeter[i]; - var p2 = perimeter[(i + 1) % perimeter.Count]; - var dir = p - p2; - if(dir != lastDir) - sides++; - lastDir = dir; + while (open.Count > 0) + { + var p = open.First(); + open.Remove(p); + var group = new List>() { p }; + GetGroup(p, group); + result.Add(group); } - return sides < 4 ? 4 : sides; + void GetGroup(Vec2 point, List> group) + { + throw new NotImplementedException(); + } + + return result; + + } + + public static void DrawPlot(List> area, List>> outline, char plant) + { + var (min, max) = GetBounds(outline.SelectMany(v => v).ToList()); + + ConsoleColor[] colors = [ + ConsoleColor.Red, + ConsoleColor.Green, + ConsoleColor.Blue, + ConsoleColor.Yellow, + ConsoleColor.Magenta, + ConsoleColor.Cyan, + ]; + + for (int y = min.Y; y <= max.Y; y++) + { + for (int x = min.X; x <= max.X; x++) + { + Console.ResetColor(); + var p = new Vec2(x,y); + if (area.Contains(p)) + { + Console.BackgroundColor = ConsoleColor.DarkGreen; + Console.Write(plant); + } + else + { + var match = outline.FirstOrDefault(v => v.Contains(p)); + if (match != null) + { + var idx = outline.IndexOf(match); + Console.BackgroundColor = colors[idx % colors.Length]; + Console.Write(' '); + }else + Console.Write(' '); + } + Console.ResetColor(); + } + Console.WriteLine(); + } + Console.ResetColor(); + } + + public static void DrawPoints(List> data, char display) + { + var (min, max) = GetBounds(data); + + var output = new StringBuilder(); + for (int y = min.Y; y <= max.Y; y++) + { + for (int x = min.X; x <= max.X; x++) + { + var p = new Vec2(x,y); + if (data.Contains(p)) + output.Append(display); + else + output.Append(' '); + + } + output.AppendLine(); + } + Console.WriteLine(output); + } + + public static (Vec2 min, Vec2 max) GetBounds(List> points) + { + var min = Vec2.Splat(int.MaxValue); + var max = Vec2.Splat(int.MinValue); + foreach (var pos in points) + { + if (pos.X < min.X) + min.X = pos.X; + if (pos.Y < min.Y) + min.Y = pos.Y; + + if (pos.X > max.X) + max.X = pos.X; + if (pos.Y > max.Y) + max.Y = pos.Y; + } + return (min, max); + } + + public static int CountSides(List>> groups, List> area) + { + int Sides(Vec2 point) + { + var s = 0; + foreach (var dir in DIRS) + { + var n = point + dir; + if(area.Contains(n)) + s++; + } + return s; + } + + return groups.Sum(s => s.Select(Sides).Max()); } private static List<(char plant, List> area, int perimeter, List> outline)> FindPlots(char[][] data) @@ -60,7 +172,7 @@ internal class GardenGroups : Problem for (int y = 0; y < data.Length; y++) { - var row = data[y]; + var row = data[y]; for (int x = 0; x < row.Length; x++) { var p = new Vec2(x, y); @@ -70,7 +182,7 @@ internal class GardenGroups : Problem var plant = data[y][x]; var perimeter = 0; var outline = new List>(); - GetMembers(data, plant, p,visited, members, ref perimeter, outline); + GetMembers(data, plant, p, visited, members, ref perimeter, outline); results.Add((plant, members, perimeter, outline)); } } @@ -101,7 +213,6 @@ internal class GardenGroups : Problem } GetMembers(data, plant, n, visited, members, ref perimeter, outline); } - } public static bool IsInBounds(Vec2 pos, char[][] data) @@ -113,10 +224,8 @@ internal class GardenGroups : Problem return true; } - - public override void LoadInput() { - _data = ReadInputLines("sample.txt").Select(ln => ln.ToCharArray()).ToArray(); + _data = ReadInputLines("sample3.txt").Select(ln => ln.ToCharArray()).ToArray(); } -} +} \ No newline at end of file diff --git a/AdventOfCode/Runner/ExtraMath.cs b/AdventOfCode/Runner/ExtraMath.cs index 1c0cc38..3ec3b2c 100644 --- a/AdventOfCode/Runner/ExtraMath.cs +++ b/AdventOfCode/Runner/ExtraMath.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; namespace AdventOfCode.Runner; + public static class ExtraMath { public static T GCF(this T a, T b) where T : INumber @@ -19,8 +20,18 @@ public static class ExtraMath return a; } - public static T LCM(this T a, T b) where T: INumber + public static T LCM(this T a, T b) where T : INumber { return (a / GCF(a, b)) * b; } -} + + public static T Max(this T a, T b) where T : INumber + { + return T.Max(a, b); + } + + public static T Min(this T a, T b) where T : INumber + { + return T.Min(a, b); + } +} \ No newline at end of file diff --git a/AdventOfCode/Utils/Models/Common.cs b/AdventOfCode/Utils/Models/Common.cs index 53490e3..6ec5e27 100644 --- a/AdventOfCode/Utils/Models/Common.cs +++ b/AdventOfCode/Utils/Models/Common.cs @@ -4,6 +4,9 @@ namespace AdventOfCode.Utils.Models; public record struct Vec2(T X, T Y) where T : INumber { + public static Vec2 Zero => new (T.Zero, T.Zero); + public static Vec2 One => new (T.One, T.One); + public static Vec2 Splat(T v) => new(v, v); public static Vec2 operator +(Vec2 left, Vec2 right) => new Vec2(left.X + right.X, left.Y + right.Y); public static Vec2 operator -(Vec2 left, Vec2 right) => new Vec2(left.X - right.X, left.Y - right.Y); public static Vec2 operator -(Vec2 vec) => new Vec2(-vec.X, -vec.Y); @@ -21,6 +24,9 @@ public record struct Vec2(T X, T Y) where T : INumber public record struct Vec3(T X, T Y, T Z) where T : INumber { + public static Vec3 Zero => new(T.Zero, T.Zero, T.Zero); + public static Vec3 One => new(T.One, T.One, T.One); + public static Vec3 Splat(T v) => new(v, v, v); public static Vec3 operator +(Vec3 left, Vec3 right) => new Vec3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); public static Vec3 operator -(Vec3 left, Vec3 right) => new Vec3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); public static Vec3 operator -(Vec3 vec) => new Vec3(-vec.X, -vec.Y, -vec.Z);