public IList <PuzzleTile> ReadTiles(string filePath, int tileSize)
        {
            var result      = new List <PuzzleTile>();
            var lines       = Readlines(filePath).ToList();
            var currentLine = 0;

            for (int t = 0; t < (lines.Count + 1) / (tileSize + 2); t++)
            {
                var tileId   = System.Convert.ToInt32(lines[currentLine++].Substring(5, 4));
                var tileData = new TileElement[tileSize, tileSize];
                for (int i = 0; i < tileSize; i++)
                {
                    for (int j = 0; j < tileSize; j++)
                    {
                        tileData[i, j] = Convert(lines[currentLine][j]);
                    }
                    currentLine++;
                }
                currentLine++;
                var tile = new PuzzleTile()
                {
                    TileId = tileId, TileData = tileData
                };
                result.Add(tile);
            }
            return(result);
        }
예제 #2
0
        private static void FillTile(PuzzleTile[,] puzzled, List <PuzzleTile> nonBorderTiles, int posx, int posy)
        {
            short?needTop    = posy > 0 && puzzled[posy - 1, posx] != null ? puzzled[posy - 1, posx].Bottom : new short?();
            short?needLeft   = posx > 0 && puzzled[posy, posx - 1] != null ? puzzled[posy, posx - 1].Right : new short?();
            short?needBottom = posy < puzzled.GetLength(1) - 1 && puzzled[posy + 1, posx] != null ? puzzled[posy + 1, posx].Top : new short?();
            short?needRight  = posx < puzzled.GetLength(0) - 1 && puzzled[posy, posx + 1] != null ? puzzled[posy, posx + 1].Left : new short?();

            PuzzleTile foundTile = null;

            foreach (var tile in nonBorderTiles)
            {
                for (int i = 0; i < 8; i++)
                {
                    var item  = tile.TilePositions[i];
                    var match = (needTop.HasValue && item[0] == needTop.Value || !needTop.HasValue) &&
                                (needRight.HasValue && item[1] == needRight.Value || !needRight.HasValue) &&
                                (needBottom.HasValue && item[2] == needBottom.Value || !needBottom.HasValue) &&
                                (needLeft.HasValue && item[3] == needLeft.Value || !needLeft.HasValue);
                    if (match)
                    {
                        tile.Orientation    = (TileOrientation)i;
                        puzzled[posy, posx] = tile;
                        foundTile           = tile;
                        break;
                    }
                }
                if (foundTile != null)
                {
                    break;
                }
            }
            if (foundTile != null)
            {
                nonBorderTiles.Remove(foundTile);
            }
            else
            {
                throw new InvalidOperationException("No tile found");
            }
        }
예제 #3
0
        static int Second(string inputFile)
        {
            var tileData   = PuzzleTileMapParser.Instance.ReadTiles(inputFile, 10);
            var gridSize   = Convert.ToInt32(Math.Sqrt(tileData.Count));
            var puzzleData = PuzzleTile(tileData, gridSize);

            //for (int i = 0; i < gridSize; i++)
            //{
            //    for (int j = 0; j < gridSize; j++)
            //    {
            //        Console.Write(puzzleData[i, j].TileId + " ");
            //    }
            //    Console.WriteLine();
            //}
            //Console.WriteLine();

            for (int j = 0; j < 12; j++)
            {
                PuzzleTile lastTile = puzzleData[j, 0];
                for (int i = 1; i < 12; i++)
                {
                    var nextTile = puzzleData[j, i];
                    Debug.Assert(nextTile.Left == lastTile.Right);
                    lastTile = nextTile;
                }
            }
            for (int i = 0; i < 12; i++)
            {
                PuzzleTile lastTile = puzzleData[0, i];
                for (int j = 1; j < 12; j++)
                {
                    var nextTile = puzzleData[j, i];
                    Debug.Assert(nextTile.Top == lastTile.Bottom);
                    lastTile = nextTile;
                }
            }

            //using (System.IO.StreamWriter file =
            //new System.IO.StreamWriter(@"..\..\..\tile.txt"))
            //{
            //    for (int j = 0; j < gridSize; j++)
            //    {
            //        for (int i = 0; i < gridSize; i++)
            //        {
            //            file.Write(puzzleData[j, i].TileId + " ");
            //        }
            //        file.WriteLine();
            //    }
            //    file.Close();
            //}

            //using (System.IO.StreamWriter file =
            //new System.IO.StreamWriter(@"..\..\..\orientation.txt"))
            //{
            //    for (int j = 0; j < gridSize; j++)
            //    {
            //        for (int i = 0; i < gridSize; i++)
            //        {
            //            file.Write(puzzleData[j, i].Orientation + " ");
            //        }
            //        file.WriteLine();
            //    }
            //    file.Close();
            //}

            TileElement[,] combinedImage = CreateImage(gridSize, puzzleData);

            //using (System.IO.StreamWriter file =
            //new System.IO.StreamWriter(@"..\..\..\output.txt"))
            //{
            //    for (int j = 0; j< gridSize * 8; j++)
            //    {
            //        for (int i = gridSize*8-1; i>=0; i--)
            //        {
            //            file.Write(combinedImage[i, j] == TileElement.Hash ? '#' : '.');
            //            Console.Write(combinedImage[i, j] == TileElement.Hash ? '#' : '.');
            //        }
            //        Console.WriteLine();
            //        file.WriteLine();
            //    }
            //    Console.WriteLine();
            //    file.WriteLine();
            //    file.Close();
            //}

            var monsterHashCount = FindMonsters(combinedImage) * 15;
            var hashCount        = FindHash(combinedImage);

            return(hashCount - monsterHashCount);
        }
예제 #4
0
        private static PuzzleTile[,] PuzzleTile(IList <PuzzleTile> tileData, int gridSize)
        {
            var puzzled = new PuzzleTile[gridSize, gridSize];

            foreach (var tile in tileData)
            {
                tile.CalculateBorderData(true);
            }
            var tileBorderData = tileData.SelectMany(x => x.TilePositions.SelectMany(p => p)).GroupBy(t => t).Select(s => new { Border = s.Key, Count = s.Count() }).Where(s => s.Count == 1).Select(s => s.Border).ToList();

            var cornerTiles = FindCorners(tileData, tileBorderData);

            //take first corner tile, and lay it down with the right orientation
            var firstCornerTile = cornerTiles.First().Item1;

            firstCornerTile.CalculateBorderData(false);
            var firstCornerOrientationVector = cornerTiles.First().Item2;
            var firstCornerOrientation       = TileOrientation.Original;

            if (firstCornerOrientationVector[0] && firstCornerOrientationVector[1])
            {
                firstCornerOrientation = TileOrientation.Rotate270;
            }
            else if (firstCornerOrientationVector[1] && firstCornerOrientationVector[2])
            {
                firstCornerOrientation = TileOrientation.Rotate180;
            }
            else if (firstCornerOrientationVector[2] && firstCornerOrientationVector[3])
            {
                firstCornerOrientation = TileOrientation.Rotate90;
            }
            firstCornerTile.Orientation = firstCornerOrientation;
            var n = gridSize - 1;

            puzzled[0, 0] = firstCornerTile;
            var lastTile = firstCornerTile;

            var borderTiles    = FindBorders(tileData, tileBorderData);
            var nonBorderTiles = tileData.Where(t => !borderTiles.Any(b => b.Item1.TileId == t.TileId) && !cornerTiles.Any(b => b.Item1.TileId == t.TileId)).ToList();

            foreach (var tile in borderTiles)
            {
                tile.Item1.CalculateBorderData(false);
            }
            foreach (var tile in nonBorderTiles)
            {
                tile.CalculateBorderData(false);
            }
            PuzzleTile nextTile = null;

            //Top borders with the correct numbers
            for (int i = 1; i < n; i++)
            {
                nextTile      = FindBorderTile(borderTiles, lastTile.Right, 0);
                puzzled[0, i] = nextTile;
                lastTile      = nextTile;
                borderTiles.Remove(borderTiles.First(b => b.Item1.TileId == nextTile.TileId));
            }
            //find next corner
            nextTile      = FindCornerTile(cornerTiles.Skip(1).Take(3), 1, lastTile.Right);
            puzzled[0, n] = nextTile;
            lastTile      = nextTile;

            //find Right borders with the correct numbers
            for (int i = 1; i < n; i++)
            {
                nextTile      = FindBorderTile(borderTiles, lastTile.Bottom, 1);
                puzzled[i, n] = nextTile;
                lastTile      = nextTile;
                borderTiles.Remove(borderTiles.First(b => b.Item1.TileId == nextTile.TileId));
            }

            //find next corner
            nextTile      = FindCornerTile(cornerTiles.Skip(1).Take(3), 2, lastTile.Bottom);
            puzzled[n, n] = nextTile;
            lastTile      = nextTile;
            //find Bottom borders with the correct numbers
            for (int i = n - 1; i >= 1; i--)
            {
                nextTile      = FindBorderTile(borderTiles, lastTile.Left, 2);
                puzzled[n, i] = nextTile;
                lastTile      = nextTile;
                borderTiles.Remove(borderTiles.First(b => b.Item1.TileId == nextTile.TileId));
            }

            //find next corner
            nextTile      = FindCornerTile(cornerTiles.Skip(1).Take(3), 3, lastTile.Left);
            puzzled[n, 0] = nextTile;
            lastTile      = nextTile;
            //find Left borders with the correct numbers
            for (int i = n - 1; i >= 1; i--)
            {
                nextTile      = FindBorderTile(borderTiles, lastTile.Top, 3);
                puzzled[i, 0] = nextTile;
                lastTile      = nextTile;
                borderTiles.Remove(borderTiles.First(b => b.Item1.TileId == nextTile.TileId));
            }
            //check last piece for borders with the correct numbers
            if (lastTile.Top != firstCornerTile.Bottom)
            {
                throw new InvalidOperationException("last border tile mismatch with corner");
            }

            var fillSteps = (gridSize - 2) / 2 + (gridSize - 2) % 2;        //5

            for (int s = 1; s <= fillSteps; s++)                            //[1 ..5]
            {
                for (int i = s; i < gridSize - s; i++)                      //[1..10] [2..9] [3..8] [4..7] [5..6]
                {
                    FillTile(puzzled, nonBorderTiles, i, s);                //[1,1][2,1][3,1][4,1][5,1][6,1][7,1][8,1][9,1][10,1] / [2,2][3,2]..[9,2] / [3,3][4,3]..[8,3] / [4,4]..[7,4] / [5,5][6,5]  //10+8+6+4+2
                }
                for (int i = s + 1; i < gridSize - s; i++)                  //[2..10] [3..9] [4..8] [5..7] [6]
                {
                    FillTile(puzzled, nonBorderTiles, gridSize - s - 1, i); //[10,2][10,3][10,4][10,5][10,6][10,7][10,8][10,9][10,10] / [9,3][9,4]..[9,8][9,9] / [8,4]..[8,8] / [7,5]..[7,7] / [6,6] //9+7+5+3+1
                }
                for (int i = gridSize - s - 2; i > s; i--)                  //[9..2] [8..3][7..4][6..5]
                {
                    FillTile(puzzled, nonBorderTiles, i, gridSize - s - 1); //[9,10][8,10][7,10][6,10][5,10][4,10][3,10][2,10] / [8,9][7,9]..[3,9] / [7,8]..[4,8] / [6,7][5,7] //8+6+4+2
                }
                for (int i = gridSize - s - 1; i > s; i--)                  //[10..2][9..3][8..4][7..5][6]
                {
                    FillTile(puzzled, nonBorderTiles, s, i);                //[1,10][1,9][1,8][1,7][1,6][1,5][1,4][1,3][1,2] / [2,9][2,8]..[2,3] / [3,8][3,7]..[3,4] / [4,7][4,6][4,5] / [5,6] //9+7+5+3+1
                }
            }
            return(puzzled);
        }