static void Main(string[] args) { string[] tokens = Console.ReadLine().Split(' '); int w = int.Parse(tokens[0]); int d = int.Parse(tokens[1]); int h = int.Parse(tokens[2]); var initColors = tokens[3]; // arrays of angle and edge parts var angleParts = new int[8]; int angleLen = 0; var edgeParts = new int[1000]; int edgeLen = 0; int xCount = 0; int yCount = 0; int zCount = 0; int n = int.Parse(Console.ReadLine()); var parts = new List<Part>(); for (int i = 0; i < n; ++i) { tokens = Console.ReadLine().Split(' '); var part = new Part(); part.W = int.Parse(tokens[0]); part.D = int.Parse(tokens[1]); part.H = int.Parse(tokens[2]); part.Colors = tokens[3]; part.DefineType(); part.CurState = new[] { 'F', 'B', 'D', 'U', 'L', 'R' }; part.Orient(initColors); parts.Add(part); if (part.Type == "angle" || part.Type == "edge") { if (part.Type == "angle") angleParts[angleLen++] = i; else edgeParts[edgeLen++] = i; UpdateXYZCounts(part.Colors, initColors, ref xCount, ref yCount, ref zCount); } } var cube = new int[xCount, yCount, zCount]; for (int i = 0; i < xCount; i++) { for (int j = 0; j < yCount; j++) { for (int k = 0; k < zCount; k++) { cube[i, j, k] = -1; } } } for (int i = 0; i < angleLen; i++) DefineAngleLocation(parts[angleParts[i]], angleParts[i], cube, initColors); for (int i = 0; i < edgeLen; i++) DefineEdgeLocation(parts[edgeParts[i]], edgeParts[i], cube, initColors); SortEdgeParts(parts, cube); var sortedW = new int[Math.Max(xCount-2, 0)]; for (int i = 0; i < sortedW.Length; i++) sortedW[i] = parts[cube[i + 1, 0, 0]].W; var sortedD = new int[Math.Max(yCount - 2, 0)]; for (int j = 0; j < sortedD.Length; j++) sortedD[j] = parts[cube[0, j + 1, 0]].D; var sortedH = new int[Math.Max(zCount - 2, 0)]; for (int k = 0; k < sortedH.Length; k++) sortedH[k] = parts[cube[0, 0, k + 1]].H; // Finally, central and inner types of part for (int i = 0; i < n; i++) { Part part = parts[i]; if (part.Type == "angle" || part.Type == "edge") continue; if (part.Type == "central") FindPlaceForCentralInCube(part, i, initColors, cube, sortedW, sortedD, sortedH); } // SetCoords to all of parts in cube parts[cube[0, 0, 0]].SetCoords(0, 0, 0); for (int i = 1; i < xCount; i++) { Part prev = parts[cube[i - 1, 0, 0]]; parts[cube[i, 0, 0]].SetCoords(prev.X + prev.W, prev.Y, prev.Z); } for (int i = 0; i < xCount; i++) { for (int j = 1; j < yCount; j++) { Part prev = parts[cube[i, j - 1, 0]]; parts[cube[i, j, 0]].SetCoords(prev.X, prev.Y + prev.D, prev.Z); } } for (int i = 0; i < xCount; i++) { for (int j = 0; j < yCount; j++) { for (int k = 1; k < zCount; k++) { Part prev = parts[cube[i, j, k - 1]]; parts[cube[i, j, k]].SetCoords(prev.X, prev.Y, prev.Z + prev.H); } } } foreach (var part in parts) Console.WriteLine(String.Format("{0} {1} {2} {3} {4}", part.FrontFace, part.DownFace, part.X, part.Y, part.Z)); }
private static void DefineEdgeLocation(Part part, int partNum, int[, ,] cube, string initColors) { int cubeX = -1, cubeY = -1, cubeZ = -1; // coords in cube if (part.Colors.Contains(initColors[5])) cubeZ = cube.GetLength(2) - 1; if (part.Colors.Contains(initColors[3])) cubeY = cube.GetLength(1) - 1; if (part.Colors.Contains(initColors[1])) cubeX = cube.GetLength(0) - 1; if (part.Colors.Contains(initColors[4])) cubeZ = 0; if (part.Colors.Contains(initColors[2])) cubeY = 0; if (part.Colors.Contains(initColors[0])) cubeX = 0; if (cubeX == -1) { cubeX = 0; while (cube[cubeX, cubeY, cubeZ] != -1) cubeX++; } else { if (cubeY == -1) { cubeY = 0; while (cube[cubeX, cubeY, cubeZ] != -1) cubeY++; } else { cubeZ = 0; while (cube[cubeX, cubeY, cubeZ] != -1) cubeZ++; } } cube[cubeX, cubeY, cubeZ] = partNum; }
private static void FindPlaceForCentralInCube(Part part, int i, string initColors, int[, ,] cube, int[] sortedW, int[] sortedD, int[] sortedH) { var xCount = cube.GetLength(0); var yCount = cube.GetLength(1); var zCount = cube.GetLength(2); var colPos = 0; while (part.Colors[colPos] == '.') colPos++; var colorFaceNum = initColors.IndexOf(part.Colors[colPos]); // front or back if (colorFaceNum == 0 || colorFaceNum == 1) { var startCubeX = colorFaceNum == 0 ? 0 : xCount - 1; var startCubeY = BinarySearch(part.D, sortedD) + 1; var startCubeZ = BinarySearch(part.H, sortedH) + 1; if (startCubeY == 0 || startCubeZ == 0 || !CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.D, part.H, sortedD, sortedH)) { part.RotateX(); var tmp = part.D; part.D = part.H; part.H = tmp; startCubeY = BinarySearch(part.D, sortedD) + 1; startCubeZ = BinarySearch(part.H, sortedH) + 1; CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.D, part.H, sortedD, sortedH); } } if (colorFaceNum == 2 || colorFaceNum == 3) { var startCubeX = BinarySearch(part.W, sortedW) + 1; var startCubeY = colorFaceNum == 0 ? 0 : yCount - 1; var startCubeZ = BinarySearch(part.H, sortedH) + 1; if (startCubeX == 0 || startCubeZ == 0 || !CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.W, part.H, sortedW, sortedH)) { part.RotateY(); var tmp = part.W; part.W = part.H; part.H = tmp; startCubeX = BinarySearch(part.W, sortedW) + 1; startCubeZ = BinarySearch(part.H, sortedH) + 1; CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.W, part.H, sortedW, sortedH); } } if (colorFaceNum == 4 || colorFaceNum == 5) { var startCubeX = BinarySearch(part.W, sortedW) + 1; var startCubeY = BinarySearch(part.D, sortedD) + 1; var startCubeZ = colorFaceNum == 0 ? 0 : zCount - 1; if (startCubeX == 0 || startCubeY == 0 || !CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.W, part.D, sortedW, sortedD)) { part.RotateZ(); var tmp = part.W; part.W = part.D; part.D = tmp; startCubeX = BinarySearch(part.W, sortedW) + 1; startCubeY = BinarySearch(part.D, sortedD) + 1; CanFindPlaceForCentralInCube(cube, startCubeX, startCubeY, startCubeZ, i, part.W, part.D, sortedW, sortedD); } } }
private static void DefineAngleLocation(Part part, int partNum, int[,,] cube, string initColors) { int cubeX, cubeY, cubeZ; // coords in cube if (part.Colors.Contains(initColors[0])) cubeX = 0; else cubeX = cube.GetLength(0) - 1; if (part.Colors.Contains(initColors[2])) cubeY = 0; else cubeY = cube.GetLength(1) - 1; if (part.Colors.Contains(initColors[4])) cubeZ = 0; else cubeZ = cube.GetLength(2) - 1; cube[cubeX, cubeY, cubeZ] = partNum; }