#pragma warning disable
using System.Collections;
var input = File.ReadAllLines("../../../../Input.in");
var enhancement = new BitArray(input.First().ToCharArray().Select(c => c == '#').ToArray());
var inputImage = new HashSet<(int, int)>();
var initFrame = new FrameState { minX = 0, minY = 0, maxX = input[2].Length, maxY = input.Length - 2 };
for (int row = 2; row < input.Length; row++)
{
var line = input[row];
for (int col = 0; col < line.Length; col++)
{
if (line[col] == '#')
{
inputImage.Add((col, row - 2));
}
}
}
var (img, frame) = (inputImage, initFrame);
for (int i = 0; i < 2; i++)
{
(img, frame) = Step(img, frame);
}
Console.WriteLine("After 2 enhancements " + img.Count + " pixels are lit");
(img, frame) = (inputImage, initFrame);
for (int i = 0; i < 50; i++)
{
(img, frame) = Step(img, frame);
}
Console.WriteLine("After 50 enhancements " + img.Count + " pixels are lit");
bool EnhancePix(HashSet<(int, int)> img, (int x, int y) coordinates, FrameState frame)
{
int key = 0;
for (int row = coordinates.y - 1; row <= coordinates.y + 1; row++)
{
for (int col = coordinates.x - 1; col <= coordinates.x + 1; col++)
{
key <<= 1;
bool litBecauseOutside = frame.LitOutside && (col < frame.minX || col > frame.maxX || row < frame.minY || row > frame.maxY);
if (litBecauseOutside || img.Contains((col, row)))
{
key += 1;
}
}
}
return enhancement[key];
}
(HashSet<(int, int)>, FrameState) Step(HashSet<(int, int)> inputImage, FrameState frame)
{
var outputImage = new HashSet<(int, int)>();
for (var x = frame.minX - 1; x <= frame.maxX + 1; x++)
{
for (var y = frame.minY - 1; y <= frame.maxY + 1; y++)
{
if (!outputImage.Contains((x, y)) && EnhancePix(inputImage, (x, y), frame))
{
outputImage.Add((x, y));
}
}
}
var newFrame = new FrameState
{
// enhancement[0] = do we turn on the frame, which is all off?
// enhancement[511] = do we turn off the frame, which is all on?
LitOutside = frame.LitOutside ? enhancement[511] : enhancement[0],
minX = frame.minX - 1,
minY = frame.minY - 1,
maxX = frame.maxX + 1,
maxY = frame.maxY + 1,
};
return (outputImage, newFrame);
}
struct FrameState
{
public bool LitOutside = false;
public int minX = int.MaxValue;
public int minY = int.MaxValue;
public int maxX = int.MinValue;
public int maxY = int.MinValue;
}