static int Solve4D(string[] initialState) { int width = 21; int height = 21; int depth = 21; int wdim = 21; var current = new Matrix4D <char>(width, height, depth, wdim, Enumerable.Repeat('.', width * height * depth * wdim).ToArray()); int cx = 6; int cy = 6; int cz = 10; int cw = 10; for (int y = 0; y < initialState.Length; y++) { for (int x = 0; x < initialState[0].Length; x++) { current[cx + x, cy + y, cz, cw] = initialState[y][x]; } } var next = current.Clone(); for (int i = 1; i <= 6; i++) { for (int w = 0; w < wdim; w++) { for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { var state = current[x, y, z, w]; int activeNeighbors = CountNeighbors(current, x, y, z, w); if (state == '#') { next[x, y, z, w] = (activeNeighbors == 2 || activeNeighbors == 3) ? '#' : '.'; } else { next[x, y, z, w] = activeNeighbors == 3 ? '#' : '.'; } } } } } var tmp = current; current = next; next = tmp; } return(current.Array.Count(c => c == '#')); }
/// <summary> /// This calculates the 4 vertices of a general (but finite) Goursat Tetrahedron. Result is in the ball model. /// /// The method comes from the dissertation "Hyperbolic polyhedra: volume and scissors congruence", /// by Yana Zilberberg Mohanty, section 2.4, steps 1-5. /// /// A,B,C are the three dihedral angles surrounding a vertex. /// A_,B_,C_ are the three oppoite dihedral angles. /// </summary> public static Vector3D[] GoursatTetrahedron(double A, double B, double C, double A_, double B_, double C_) { // Step 1: Construct Gram matrix with reversed rows/columns. // NOTE: The sign of the diagonal in the paper was incorrect. double pi = Math.PI; double[,] gramMatrixData = new double[, ] { { -1, Math.Cos(pi / A_), Math.Cos(pi / B_), Math.Cos(pi / C) }, { Math.Cos(pi / A_), -1, Math.Cos(pi / C_), Math.Cos(pi / B) }, { Math.Cos(pi / B_), Math.Cos(pi / C_), -1, Math.Cos(pi / A) }, { Math.Cos(pi / C), Math.Cos(pi / B), Math.Cos(pi / A), -1 }, }; Matrix4D gramMatrix = new Matrix4D(gramMatrixData); gramMatrix *= -1; Matrix4D identity = Matrix4D.Identity(); // Step 2: Gram-Schmidt. Matrix4D W = GramSchmidt(identity, gramMatrix); // Step 3: Divide 4th row by i (already effectively done in our Gram-Schmidt routine below), and reverse order of rows. Matrix4D W_ = ReverseRows(W); // Step 4 Matrix4D D = identity.Clone(); D[0, 0] = -1; Matrix4D U = Matrix4D.Transpose(D * W_); // Step 5 Matrix4D U_ = ReverseRows(U); for (int i = 0; i < 4; i++) { MinkowskiNormalize(U_[i]); } // Now move from the hyperboloid model to the ball. List <Vector3D> result = new List <Vector3D>(); for (int i = 0; i < 4; i++) { result.Add(HyperboloidToBall(U_[i])); } return(result.ToArray()); }
public static Matrix4D GramSchmidt(Matrix4D input, Matrix4D innerProductValues) { Matrix4D result = input.Clone(); for (int i = 0; i < 4; i++) { for (int j = 0; j < i; j++) { Vector3D iVec = result[i]; Vector3D jVec = result[j]; double inner = innerProductValues[i].Dot(jVec); iVec -= inner * jVec; result[i] = iVec; } // Normalize. We don't use Vector3D normalize because we might have timelike vectors. double mag2 = innerProductValues[i].Dot(result[i]); double abs = mag2 < 0 ? -Math.Sqrt(-mag2) : Math.Sqrt(mag2); result[i].Divide(abs); } return(result); }