wip day 12 part 2
This commit is contained in:
@@ -6,6 +6,8 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day12;
|
namespace AdventOfCode.Problems.AOC2024.Day12;
|
||||||
|
|
||||||
[ProblemInfo(2024, 12, "Garden Groups")]
|
[ProblemInfo(2024, 12, "Garden Groups")]
|
||||||
@@ -13,7 +15,7 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
{
|
{
|
||||||
private char[][] _data = [];
|
private char[][] _data = [];
|
||||||
|
|
||||||
public readonly static Vec2<int>[] DIRS = [
|
public static readonly Vec2<int>[] DIRS = [
|
||||||
new(0,1),
|
new(0,1),
|
||||||
new(1,0),
|
new(1,0),
|
||||||
new(0,-1),
|
new(0,-1),
|
||||||
@@ -28,28 +30,138 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
|
|
||||||
public override void CalculatePart2()
|
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<Vec2<int>> perimeter)
|
public static List<List<Vec2<int>>> GroupSides(List<Vec2<int>> outline)
|
||||||
{
|
{
|
||||||
if (perimeter.Count <= 2)
|
var result = new List<List<Vec2<int>>>();
|
||||||
return 4;
|
var visited = new HashSet<Vec2<int>>();
|
||||||
var sides = 1;
|
var open = new HashSet<Vec2<int>>(outline);
|
||||||
|
|
||||||
var lastDir = new Vec2<int>(0,0);
|
while (open.Count > 0)
|
||||||
//var startDir = lastDir;
|
{
|
||||||
for (int i = 0; i < perimeter.Count; i++)
|
var p = open.First();
|
||||||
{
|
open.Remove(p);
|
||||||
var p = perimeter[i];
|
var group = new List<Vec2<int>>() { p };
|
||||||
var p2 = perimeter[(i + 1) % perimeter.Count];
|
GetGroup(p, group);
|
||||||
var dir = p - p2;
|
result.Add(group);
|
||||||
if(dir != lastDir)
|
|
||||||
sides++;
|
|
||||||
lastDir = dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sides < 4 ? 4 : sides;
|
void GetGroup(Vec2<int> point, List<Vec2<int>> group)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawPlot(List<Vec2<int>> area, List<List<Vec2<int>>> 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<int>(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<Vec2<int>> 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<int>(x,y);
|
||||||
|
if (data.Contains(p))
|
||||||
|
output.Append(display);
|
||||||
|
else
|
||||||
|
output.Append(' ');
|
||||||
|
|
||||||
|
}
|
||||||
|
output.AppendLine();
|
||||||
|
}
|
||||||
|
Console.WriteLine(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (Vec2<int> min, Vec2<int> max) GetBounds(List<Vec2<int>> points)
|
||||||
|
{
|
||||||
|
var min = Vec2<int>.Splat(int.MaxValue);
|
||||||
|
var max = Vec2<int>.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<List<Vec2<int>>> groups, List<Vec2<int>> area)
|
||||||
|
{
|
||||||
|
int Sides(Vec2<int> 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<Vec2<int>> area, int perimeter, List<Vec2<int>> outline)> FindPlots(char[][] data)
|
private static List<(char plant, List<Vec2<int>> area, int perimeter, List<Vec2<int>> outline)> FindPlots(char[][] data)
|
||||||
@@ -60,7 +172,7 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
|
|
||||||
for (int y = 0; y < data.Length; y++)
|
for (int y = 0; y < data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = data[y];
|
var row = data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
var p = new Vec2<int>(x, y);
|
var p = new Vec2<int>(x, y);
|
||||||
@@ -70,7 +182,7 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
var plant = data[y][x];
|
var plant = data[y][x];
|
||||||
var perimeter = 0;
|
var perimeter = 0;
|
||||||
var outline = new List<Vec2<int>>();
|
var outline = new List<Vec2<int>>();
|
||||||
GetMembers(data, plant, p,visited, members, ref perimeter, outline);
|
GetMembers(data, plant, p, visited, members, ref perimeter, outline);
|
||||||
results.Add((plant, members, perimeter, outline));
|
results.Add((plant, members, perimeter, outline));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +213,6 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
}
|
}
|
||||||
GetMembers(data, plant, n, visited, members, ref perimeter, outline);
|
GetMembers(data, plant, n, visited, members, ref perimeter, outline);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsInBounds(Vec2<int> pos, char[][] data)
|
public static bool IsInBounds(Vec2<int> pos, char[][] data)
|
||||||
@@ -113,10 +224,8 @@ internal class GardenGroups : Problem<int, int>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("sample.txt").Select(ln => ln.ToCharArray()).ToArray();
|
_data = ReadInputLines("sample3.txt").Select(ln => ln.ToCharArray()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
|
|
||||||
public static class ExtraMath
|
public static class ExtraMath
|
||||||
{
|
{
|
||||||
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
||||||
@@ -19,8 +20,18 @@ public static class ExtraMath
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T LCM<T>(this T a, T b) where T: INumber<T>
|
public static T LCM<T>(this T a, T b) where T : INumber<T>
|
||||||
{
|
{
|
||||||
return (a / GCF(a, b)) * b;
|
return (a / GCF(a, b)) * b;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static T Max<T>(this T a, T b) where T : INumber<T>
|
||||||
|
{
|
||||||
|
return T.Max(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T Min<T>(this T a, T b) where T : INumber<T>
|
||||||
|
{
|
||||||
|
return T.Min(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@ namespace AdventOfCode.Utils.Models;
|
|||||||
|
|
||||||
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
||||||
{
|
{
|
||||||
|
public static Vec2<T> Zero => new (T.Zero, T.Zero);
|
||||||
|
public static Vec2<T> One => new (T.One, T.One);
|
||||||
|
public static Vec2<T> Splat(T v) => new(v, v);
|
||||||
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
||||||
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
||||||
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
|
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
|
||||||
@@ -21,6 +24,9 @@ public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
|||||||
|
|
||||||
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
||||||
{
|
{
|
||||||
|
public static Vec3<T> Zero => new(T.Zero, T.Zero, T.Zero);
|
||||||
|
public static Vec3<T> One => new(T.One, T.One, T.One);
|
||||||
|
public static Vec3<T> Splat(T v) => new(v, v, v);
|
||||||
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||||
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||||
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
||||||
|
|||||||
Reference in New Issue
Block a user