static void Main(string[] args) { Console.WriteLine("Day 17 - Conway Cubes"); Console.WriteLine("Star 1"); Console.WriteLine(); char[,] grid = File.ReadAllLines(inputFile).ToArrayGrid(); { HashSet <Point3D> activeStates = new HashSet <Point3D>(); HashSet <Point3D> tempActiveStates = new HashSet <Point3D>(); for (int x = 0; x < grid.GetLength(0); x++) { for (int y = 0; y < grid.GetLength(1); y++) { if (grid[x, y] == '#') { activeStates.Add((x, y, 0)); } } } int cycleCount = 0; while (cycleCount < 6) { //Perform a cycle tempActiveStates.Clear(); Point3D min = new Point3D(int.MaxValue, int.MaxValue, int.MaxValue); Point3D max = new Point3D(int.MinValue, int.MinValue, int.MinValue); foreach (Point3D point in activeStates) { min = AoCMath.Min(min, point); max = AoCMath.Max(max, point); } for (int x = min.x - 1; x <= max.x + 1; x++) { for (int y = min.y - 1; y <= max.y + 1; y++) { for (int z = min.z - 1; z <= max.z + 1; z++) { if (CheckState(activeStates, x, y, z)) { tempActiveStates.Add(new Point3D(x, y, z)); } } } } cycleCount++; (activeStates, tempActiveStates) = (tempActiveStates, activeStates); } int output1 = activeStates.Count(); Console.WriteLine($"The answer is: {output1}"); } Console.WriteLine(); Console.WriteLine("Star 2"); Console.WriteLine(); { HashSet <Point4D> activeStates = new HashSet <Point4D>(); HashSet <Point4D> tempActiveStates = new HashSet <Point4D>(); for (int x = 0; x < grid.GetLength(0); x++) { for (int y = 0; y < grid.GetLength(1); y++) { if (grid[x, y] == '#') { activeStates.Add((x, y, 0, 0)); } } } int cycleCount = 0; while (cycleCount < 6) { //Perform a cycle tempActiveStates.Clear(); Point4D min = new Point4D(int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue); Point4D max = new Point4D(int.MinValue, int.MinValue, int.MinValue, int.MinValue);; foreach (Point4D point in activeStates) { min = AoCMath.Min(min, point); max = AoCMath.Max(max, point); } for (int x = min.x - 1; x <= max.x + 1; x++) { for (int y = min.y - 1; y <= max.y + 1; y++) { for (int z = min.z - 1; z <= max.z + 1; z++) { for (int w = min.w - 1; w <= max.w + 1; w++) { if (CheckState(activeStates, x, y, z, w)) { tempActiveStates.Add(new Point4D(x, y, z, w)); } } } } } cycleCount++; (activeStates, tempActiveStates) = (tempActiveStates, activeStates); } int output2 = activeStates.Count(); Console.WriteLine($"The answer is: {output2}"); } Console.WriteLine(); Console.ReadKey(); }
static void Main(string[] args) { Console.WriteLine("Day 20 - Jurassic Jigsaw"); Console.WriteLine("Star 1"); Console.WriteLine(); string[] lines = File.ReadAllLines(inputFile); List <Tile> tiles = GetTiles(lines).ToList(); Dictionary <int, List <Tile> > edgeTrackingDict = new Dictionary <int, List <Tile> >(); foreach (Tile tile in tiles) { tile.AddToDict(edgeTrackingDict); } List <Tile> edgeTiles = new List <Tile>(edgeTrackingDict.Values .Where(x => x.Count == 1) .Select(x => x.First())); HashSet <Tile> uniqueEdgeTiles = new HashSet <Tile>(edgeTiles); HashSet <Tile> cornerTiles = new HashSet <Tile>( uniqueEdgeTiles .Where(y => edgeTiles.Count(x => x == y) == 4)); long output1 = cornerTiles .Select(x => x.Id).Aggregate(1L, (x, y) => x * y); Console.WriteLine($"The answer is: {output1}"); Console.WriteLine(); Console.WriteLine("Star 2"); Console.WriteLine(); Tile[,] assembledImage = new Tile[12, 12]; Tile protoCorner = cornerTiles.First(); List <int> matchlessCorners = new List <int>(); for (int i = 0; i < 4; i++) { if (edgeTrackingDict[protoCorner.edgeValues[i]].Count == 1) { matchlessCorners.Add(i); } } //0,3 -> UL //0,1 -> UR //1,2 -> LR //2,3 -> LL int protoX; int protoY; if (matchlessCorners.Contains(0)) { protoY = 0; } else { protoY = 11; } if (matchlessCorners.Contains(1)) { protoX = 11; } else { protoX = 0; } assembledImage[protoX, protoY] = protoCorner; protoCorner.Coordinate = (protoX, protoY); Queue <Tile> tilesToProcess = new Queue <Tile>(); tilesToProcess.Enqueue(protoCorner); while (tilesToProcess.Count > 0) { Tile tileToProcess = tilesToProcess.Dequeue(); Point2D coordinate = tileToProcess.Coordinate; var(top, right, bottom, left) = tileToProcess.GetEdges(tileToProcess.Orientation); //Check Up if (coordinate.y > 0 && assembledImage[coordinate.x, coordinate.y - 1] == null) { //Find Upper Match Tile correspondingTile = edgeTrackingDict[top].First(x => x != tileToProcess); correspondingTile.Coordinate = (coordinate.x, coordinate.y - 1); assembledImage[coordinate.x, coordinate.y - 1] = correspondingTile; for (int orientation = 0; orientation < 8; orientation++) { var correspondingEdges = correspondingTile.GetEdges(orientation); if (correspondingEdges.bottom == top) { correspondingTile.Orientation = orientation; break; } } tilesToProcess.Enqueue(correspondingTile); } //Check Down if (coordinate.y < 11 && assembledImage[coordinate.x, coordinate.y + 1] == null) { //Find Lower Match Tile correspondingTile = edgeTrackingDict[bottom].First(x => x != tileToProcess); correspondingTile.Coordinate = (coordinate.x, coordinate.y + 1); assembledImage[coordinate.x, coordinate.y + 1] = correspondingTile; for (int orientation = 0; orientation < 8; orientation++) { var correspondingEdges = correspondingTile.GetEdges(orientation); if (correspondingEdges.top == bottom) { correspondingTile.Orientation = orientation; break; } } tilesToProcess.Enqueue(correspondingTile); } //Check Right if (coordinate.x < 11 && assembledImage[coordinate.x + 1, coordinate.y] == null) { //Find Lower Match Tile correspondingTile = edgeTrackingDict[right].First(x => x != tileToProcess); correspondingTile.Coordinate = (coordinate.x + 1, coordinate.y); assembledImage[coordinate.x + 1, coordinate.y] = correspondingTile; for (int orientation = 0; orientation < 8; orientation++) { var correspondingEdges = correspondingTile.GetEdges(orientation); if (correspondingEdges.left == right) { correspondingTile.Orientation = orientation; break; } } tilesToProcess.Enqueue(correspondingTile); } //Check Left if (coordinate.x > 0 && assembledImage[coordinate.x - 1, coordinate.y] == null) { //Find Lower Match Tile correspondingTile = edgeTrackingDict[left].First(x => x != tileToProcess); correspondingTile.Coordinate = (coordinate.x - 1, coordinate.y); assembledImage[coordinate.x - 1, coordinate.y] = correspondingTile; for (int orientation = 0; orientation < 8; orientation++) { var correspondingEdges = correspondingTile.GetEdges(orientation); if (correspondingEdges.right == left) { correspondingTile.Orientation = orientation; break; } } tilesToProcess.Enqueue(correspondingTile); } } HashSet <Point2D> activeCoordinates = new HashSet <Point2D>(); for (int tileX = 0; tileX < 12; tileX++) { for (int tileY = 0; tileY < 12; tileY++) { Point2D corner = (8 * tileX, 8 * tileY); Tile currentTile = assembledImage[tileX, tileY]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (currentTile.GetOrientedValue(x, y)) { activeCoordinates.Add(corner + (x, y)); } } } } } List <Point2D> originalMonstarCoordinates = new List <Point2D>(); for (int y = 0; y < SEE_MONSTAR.Length; y++) { for (int x = 0; x < SEE_MONSTAR[y].Length; x++) { if (SEE_MONSTAR[y][x] == '#') { originalMonstarCoordinates.Add((x, y)); } } } int monsterCount = 0; List <Point2D> seaMonsterPositions = new List <Point2D>(); List <Point2D> monstarCoordinates = null; for (int rotation = 0; rotation < 8; rotation++) { monstarCoordinates = originalMonstarCoordinates .Select(x => GetRotatedValue(x, rotation)).ToList(); //Start First Pass Logic Point2D maxDisplacement = (0, 0); foreach (Point2D point in monstarCoordinates) { maxDisplacement = AoCMath.Max(point, maxDisplacement); } for (int x0 = 0; x0 < (12 * 8 - maxDisplacement.x); x0++) { for (int y0 = 0; y0 < (12 * 8 - maxDisplacement.y); y0++) { if (SearchCoordinate((x0, y0), monstarCoordinates, activeCoordinates)) { monsterCount++; seaMonsterPositions.Add((x0, y0)); } } } if (monsterCount > 0) { break; } } foreach (Point2D monstarPosition in seaMonsterPositions) { foreach (Point2D monstarCoordinate in monstarCoordinates) { activeCoordinates.Remove(monstarPosition + monstarCoordinate); } } Console.WriteLine($"The answer is: {activeCoordinates.Count}"); Console.WriteLine(); Console.ReadKey(); }