Skip to content

Commit

Permalink
day 12 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaKateryna committed Dec 12, 2024
1 parent e5d8c7d commit ac172e1
Showing 1 changed file with 186 additions and 12 deletions.
198 changes: 186 additions & 12 deletions AdventOfCode/Day12.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System.Collections;
using System.Collections.Generic;

namespace AdventOfCode;
namespace AdventOfCode;

public class Day12 : BaseDay
{
Expand All @@ -13,6 +10,16 @@ public Day12()
}

public override ValueTask<string> Solve_1()
{
return new(Solve(false).ToString());
}

public override ValueTask<string> Solve_2()
{
return new(Solve(true).ToString());
}

private int Solve(bool updated)
{
bool[][] visited = new bool[_input.Length][];
for (int i = 0; i < visited.Length; ++i)
Expand All @@ -29,14 +36,11 @@ public override ValueTask<string> Solve_1()
nextStart = GetNextNotVisited(visited);
}

int price = areas.Sum(GetAreaPrice);

return new(price.ToString());
}

public override ValueTask<string> Solve_2()
{
return new("");
if (updated)
{
return areas.Sum(GetNewAreaPrice);
}
return areas.Sum(GetAreaPrice);
}

private List<Point> GetArea(Point start, bool[][] visited)
Expand Down Expand Up @@ -82,6 +86,166 @@ private int GetAreaPrice(List<Point> area)
return perimeter * areaSize;
}

private int GetNewAreaPrice(List<Point> area)
{
int areaSize = area.Count;

HashSet<PointSide> sides = new HashSet<PointSide>();

foreach (Point point in area)
{
// top
if (point.I == 0 || !area.Contains(new Point(point.I - 1, point.J)))
{
TryAddSide(point, Side.Top, sides, area);
}

// bottom
if (point.I == _input.Length - 1 || !area.Contains(new Point(point.I + 1, point.J)))
{
TryAddSide(point, Side.Bottom, sides, area);
}

// left
if (point.J == 0 || !area.Contains(new Point(point.I, point.J - 1)))
{
TryAddSide(point, Side.Left, sides, area);
}

// right
if (point.J == _input[0].Length || !area.Contains(new Point(point.I, point.J + 1)))
{
TryAddSide(point, Side.Right, sides, area);
}
}

return sides.Count * areaSize;
}

private void TryAddSide(Point point, Side side, HashSet<PointSide> pointSides, List<Point> area)
{
if (side == Side.Top || side == Side.Bottom)
{
var existingSides = pointSides.Where(ps => ps.Point.I == point.I && ps.Side == side);
foreach (var existing in existingSides)
{
if (CanReachHorizontally(point, existing, side))
{
return;
}
}
pointSides.Add(new PointSide(point, side));
}

if (side == Side.Left || side == Side.Right)
{
var existingSides = pointSides.Where(ps => ps.Point.J == point.J && ps.Side == side);
foreach (var existing in existingSides)
{
if (CanReachVertically(point, existing, side))
{
return;
}
}
pointSides.Add(new PointSide(point, side));
}
}

private bool CanReachHorizontally(Point point, PointSide existing, Side side)
{
char value = _input[point.I][point.J];
if (point.J < existing.Point.J)
{
for (int j= point.J + 1; j < existing.Point.J; ++j)
{
if (_input[point.I][j] != value)
{
return false;
}
if (side == Side.Top && point.I != 0 && _input[point.I - 1][j] == value)
{
return false;
}
if (side == Side.Bottom && point.I != _input.Length - 1 && _input[point.I + 1][j] == value)
{
return false;
}
}

return true;
}

if (point.J > existing.Point.J)
{
for (int j = point.J - 1; j > existing.Point.J; --j)
{
if (_input[point.I][j] != value)
{
return false;
}
if (side == Side.Top && point.I != 0 && _input[point.I - 1][j] == value)
{
return false;
}
if (side == Side.Bottom && point.I != _input.Length - 1 && _input[point.I + 1][j] == value)
{
return false;
}
}

return true;
}

throw new Exception();
}

private bool CanReachVertically(Point point, PointSide existing, Side side)
{
char value = _input[point.I][point.J];
if (point.I < existing.Point.I)
{
for (int i = point.I + 1; i < existing.Point.I; ++i)
{
if (_input[i][point.J] != value)
{
return false;
}
if (side == Side.Left && point.J != 0 && _input[i][point.J - 1] == value)
{
return false;
}
if (side == Side.Right && point.J != _input[i].Length - 1 && _input[i][point.J + 1] == value)
{
return false;
}
}

return true;
}

if (point.I > existing.Point.I)
{
for (int i = point.I - 1; i > existing.Point.I; --i)
{
if (_input[i][point.J] != value)
{
return false;
}
if (side == Side.Left && point.J != 0 && _input[i][point.J - 1] == value)
{
return false;
}
if (side == Side.Right && point.J != _input[i].Length - 1 && _input[i][point.J + 1] == value)
{
return false;
}
}

return true;
}

throw new Exception();
}

private Point? GetNextNotVisited(bool[][] visited)
{
Expand Down Expand Up @@ -126,4 +290,14 @@ private IEnumerable<Point> GetNeighbourPoints(Point current)
}

private record Point(int I, int J);

private enum Side
{
Top,
Bottom,
Left,
Right
}

private record PointSide(Point Point, Side Side);
}

0 comments on commit ac172e1

Please sign in to comment.