 
 typealias G = Int
 let Z = 1
+
+extension G {
+    func repeating(_ n: Int) -> [Int] {
+        return Array(repeating: self, count: n)
+    }
+}
+
+extension Optional where Wrapped == G {
+    var isZero: Bool {
+        return self != nil && self! == 0
+    }
+    var symbol: String {
+        return self.flatMap{ $0 == 1 ? "Z" : "0"} ?? "?"
+    }
+}
 
 extension Array where Element == String {
     func join(_ separator: String = "") -> String {
         return self.joined(separator: separator)
-    }
-}
-
-extension Optional where Wrapped == G {
-    var isZero: Bool {
-        return self != nil && self! == 0
-    }
-    var symbol: String {
-        return self.flatMap{ $0 == 1 ? "Z" : "0"} ?? "?"
     }
 }
 

    }

    func cascadeZeros() {
        let E = self
        let N = maxDegree
        if N == 2 {
            return

            }
        }
    }
    
    func updateAll() {
        let E2 = self[2]
        for (p, q, _) in E2 {
            update(2, p, q)
        }
    }
    
    func update(_ r: Int, _ p: Int, _ q: Int) {
        let Er = self[r]
        let infty = maxDegree
        
        guard (0 ..< width).contains(p) && (0 ..< height).contains(q) && (2 ... infty).contains(r) else {
            return
        }
        
        guard r < infty else {
            return
        }
        
        let Er1 = self[r + 1]
        
        if Er.isZeroMap(p, q) && Er.isZeroMap(Er.cotarget(p, q)) { // => E_r[p, q] = E_{r+1}[p, q]
            if Er[p, q] == nil {
                
                if Er1[p, q] == nil {
                    update(r + 1, p, q)
                }
                
                if Er1[p, q] != nil {
                    Er[p, q] = Er1[p, q]!
                    // update?
                    
                    // if r == 2 && ...
                }
            } else {
                if Er1[p, q] == nil {
                    Er1[p, q] = Er[p, q]!
                    update(r + 1, p, q)
                } else if Er[p, q] != Er1[p, q] {
                    fatalError()
                }
            }
        }
        
        else if Er1[p, q].isZero {
            
        }
    }
}

let n = 2
var E = SpectralSequence(size: (2 * n + 1, 2))

E.name = "S^1 -> S^{2n + 1} -> CP^n"
E.fiber = [Z, Z]
E.total = [Z] + 0.repeating(2 * n) + [Z]

E.solve()

