|
|
@@ -1,109 +1,87 @@
|
|
|
-using System.Drawing;
|
|
|
-
|
|
|
-using Day17;
|
|
|
-
|
|
|
-namespace Day18;
|
|
|
+namespace Day18;
|
|
|
|
|
|
public class Field
|
|
|
{
|
|
|
- private int _minX, _maxX = 0;
|
|
|
- private int _minY, _maxY = 0;
|
|
|
- private Vec _pos = new Vec(0, 0);
|
|
|
- private readonly Dictionary<Vec, CellData> _grid = new Dictionary<Vec, CellData>();
|
|
|
+ private CellData[,]? _grid;
|
|
|
+ private long _perimeter = 0L;
|
|
|
|
|
|
- public Field()
|
|
|
+ public void Apply(List<Instruction> instructions)
|
|
|
{
|
|
|
- _grid[_pos] = new CellData(Color.White);
|
|
|
- }
|
|
|
+ var pos = new Vec(0, 0);
|
|
|
+ var lines = new List<Line>();
|
|
|
+ _perimeter = 0L;
|
|
|
+ foreach (var inst in instructions)
|
|
|
+ {
|
|
|
+ var line = new Line(pos, Vec.Direction(inst.Dir), inst.Num);
|
|
|
+ lines.Add(line);
|
|
|
+ pos = pos.Add(line.Dir.Multiply(line.Length));
|
|
|
+ _perimeter += line.Length;
|
|
|
+ }
|
|
|
|
|
|
- public void Apply(Instruction inst)
|
|
|
- {
|
|
|
- var v = Vec.Direction(inst.Dir);
|
|
|
- for (var i = 0; i < inst.Num; i++)
|
|
|
+ var xNodes = lines.Select(l => l.Start.X).Order().Distinct().ToArray();
|
|
|
+ var yNodes = lines.Select(l => l.Start.Y).Order().Distinct().ToArray();
|
|
|
+
|
|
|
+ _grid = new CellData[xNodes.Length - 1, yNodes.Length - 1];
|
|
|
+ for (var y = 0; y < yNodes.Length - 1; y++)
|
|
|
{
|
|
|
- _grid[_pos].Outgoing = v;
|
|
|
-
|
|
|
- _pos = _pos.Add(v);
|
|
|
- _grid.TryAdd(_pos, new CellData(inst.Color));
|
|
|
- _grid[_pos].Incoming = v;
|
|
|
-
|
|
|
- _minX = Math.Min(_minX, _pos.X);
|
|
|
- _maxX = Math.Max(_maxX, _pos.X);
|
|
|
- _minY = Math.Min(_minY, _pos.Y);
|
|
|
- _maxY = Math.Max(_maxY, _pos.Y);
|
|
|
+ for (var x = 0; x < xNodes.Length - 1; x++)
|
|
|
+ {
|
|
|
+ var topLeft = new Vec(xNodes[x], yNodes[y]);
|
|
|
+ var bottomRight = new Vec(xNodes[x + 1], yNodes[y + 1]);
|
|
|
+ var cell = new CellData(topLeft, bottomRight);
|
|
|
+ _grid[x, y] = cell;
|
|
|
+
|
|
|
+ cell.Lines = lines
|
|
|
+ .Where(l => l.Dir.IsVertical && l.Start.X == topLeft.X)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ cell.Calculate();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public int Fill()
|
|
|
+ public long GetArea()
|
|
|
{
|
|
|
- var count = 0;
|
|
|
- for (var y = _minY; y < _maxY + 1; y++)
|
|
|
+ if (_grid == null)
|
|
|
+ {
|
|
|
+ throw new NullReferenceException("_grid");
|
|
|
+ }
|
|
|
+
|
|
|
+ var count = 0L;
|
|
|
+ for (var y = 0; y < _grid.GetLength(1); y++)
|
|
|
{
|
|
|
- var lastCorner = 0;
|
|
|
- var transitions = 0;
|
|
|
- for (var x = _minX; x < _maxX + 1; x++)
|
|
|
+ var crossings = 0;
|
|
|
+ for (var x = 0; x < _grid.GetLength(0); x++)
|
|
|
{
|
|
|
- var v = new Vec(x, y);
|
|
|
- if (_grid.TryGetValue(v, out CellData? d))
|
|
|
+ var cell = _grid[x, y];
|
|
|
+ crossings += cell.HasCrossing ? 1 : 0;
|
|
|
+ if (crossings % 2 == 1)
|
|
|
{
|
|
|
- var data = d!;
|
|
|
- count++;
|
|
|
- var cornerNum = data.CornerNum();
|
|
|
- if (cornerNum == 0)
|
|
|
- {
|
|
|
- if (data.Incoming!.Value.IsVertical)
|
|
|
- {
|
|
|
- transitions++;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (lastCorner == 0)
|
|
|
- {
|
|
|
- lastCorner = cornerNum;
|
|
|
- }
|
|
|
- else if (lastCorner == -cornerNum)
|
|
|
- {
|
|
|
- transitions++;
|
|
|
- lastCorner = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- lastCorner = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (transitions % 2 == 1)
|
|
|
- {
|
|
|
- count++;
|
|
|
- }
|
|
|
+ count += cell.Size();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return count;
|
|
|
- }
|
|
|
+ count += _perimeter / 2 + 1;
|
|
|
|
|
|
- private int CornerNum(Vec vec)
|
|
|
- {
|
|
|
- var above = _grid.ContainsKey(vec.Add(new Vec(0, -1)));
|
|
|
- var below = _grid.ContainsKey(vec.Add(new Vec(0, 1)));
|
|
|
- return above == below
|
|
|
- ? 0
|
|
|
- : above
|
|
|
- ? -1
|
|
|
- : 1;
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
public void Print()
|
|
|
{
|
|
|
- for (var y = _minY; y < _maxY + 1; y++)
|
|
|
+ if (_grid == null)
|
|
|
+ {
|
|
|
+ throw new NullReferenceException("_grid");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (var y = 0; y < _grid.GetLength(1); y++)
|
|
|
{
|
|
|
- for (var x = _minX; x < _maxX + 1; x++)
|
|
|
+ var crossings = 0;
|
|
|
+ for (var x = 0; x < _grid.GetLength(0); x++)
|
|
|
{
|
|
|
- if (_grid.ContainsKey(new Vec(x, y)))
|
|
|
+ var cell = _grid[x, y];
|
|
|
+ crossings += cell.HasCrossing ? 1 : 0;
|
|
|
+ if (crossings % 2 == 1)
|
|
|
{
|
|
|
Console.Write('#');
|
|
|
}
|
|
|
@@ -118,26 +96,4 @@ public class Field
|
|
|
|
|
|
Console.WriteLine();
|
|
|
}
|
|
|
-
|
|
|
- private class CellData
|
|
|
- {
|
|
|
- public Color Color { get; }
|
|
|
- public Vec? Outgoing { get; set; }
|
|
|
- public Vec? Incoming { get; set; }
|
|
|
-
|
|
|
- public CellData(Color color)
|
|
|
- {
|
|
|
- Color = color;
|
|
|
- }
|
|
|
-
|
|
|
- public int CornerNum()
|
|
|
- {
|
|
|
- if (Incoming != null && Outgoing != null)
|
|
|
- {
|
|
|
- var n = Incoming.Value.Cross(Outgoing.Value);
|
|
|
- return Math.Abs(n) == 1 ? n : 0;
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
}
|