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); }
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"); } }
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); }
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); }