Esempio n. 1
0
        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();
        }
Esempio n. 2
0
        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();
        }