l3lab/ntp-mathlib huggingface dataset:
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    

Proof state:
case mp
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : Exact S
⊢ ShortComplex.Exact (sc' S hS 0 1 2)

Next tactic:
exact h.exact 0 (by linarith)
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : Exact S
⊢ 0 + 2 ≤ 2

Next tactic:
linarith
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by linarith)
  · 

Proof state:
case mpr
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
⊢ ShortComplex.Exact (sc' S hS 0 1 2) → Exact S

Next tactic:
intro h
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by linarith)
  · intro h
    

Proof state:
case mpr
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : ShortComplex.Exact (sc' S hS 0 1 2)
⊢ Exact S

Next tactic:
refine' Exact.mk hS (fun i hi => _)
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by linarith)
  · intro h
    refine' Exact.mk hS (fun i hi => _)
    

Proof state:
case mpr
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : ShortComplex.Exact (sc' S hS 0 1 2)
i : ℕ
hi : autoParam (i + 2 ≤ 2) _auto✝
⊢ ShortComplex.Exact (sc S hS i)

Next tactic:
obtain rfl : i = 0 := by linarith
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by linarith)
  · intro h
    refine' Exact.mk hS (fun i hi => _)
    obtain rfl : i = 0 := by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : ShortComplex.Exact (sc' S hS 0 1 2)
i : ℕ
hi : autoParam (i + 2 ≤ 2) _auto✝
⊢ i = 0

Next tactic:
linarith
lemma exact₂_iff (S : ComposableArrows C 2) (hS : S.IsComplex) :
    S.Exact ↔ (S.sc' hS 0 1 2).Exact := by
  constructor
  · intro h
    exact h.exact 0 (by linarith)
  · intro h
    refine' Exact.mk hS (fun i hi => _)
    obtain rfl : i = 0 := by linarith
    

Proof state:
case mpr
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C 2
hS : IsComplex S
h : ShortComplex.Exact (sc' S hS 0 1 2)
hi : autoParam (0 + 2 ≤ 2) _auto✝
⊢ ShortComplex.Exact (sc S hS 0)

Next tactic:
exact h
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
⊢ Exact S ↔ Exact (mk₂ (map' S 0 1) (map' S 1 2)) ∧ Exact (δ₀ S)

Next tactic:
constructor
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · 

Proof state:
case mp
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
⊢ Exact S → Exact (mk₂ (map' S 0 1) (map' S 1 2)) ∧ Exact (δ₀ S)

Next tactic:
intro h
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    

Proof state:
case mp
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (mk₂ (map' S 0 1) (map' S 1 2)) ∧ Exact (δ₀ S)

Next tactic:
constructor
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · 

Proof state:
case mp.left
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (mk₂ (map' S 0 1) (map' S 1 2))

Next tactic:
rw [exact₂_iff]
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; 

Proof state:
case mp.left
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ ShortComplex.Exact (sc' (mk₂ (map' S 0 1) (map' S 1 2)) ?mp.left.hS 0 1 2)
case mp.left.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ IsComplex (mk₂ (map' S 0 1) (map' S 1 2))

Next tactic:
swap
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · 

Proof state:
case mp.left.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ IsComplex (mk₂ (map' S 0 1) (map' S 1 2))

Next tactic:
rw [isComplex₂_iff]
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        

Proof state:
case mp.left.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ map' (mk₂ (map' S 0 1) (map' S 1 2)) 0 1 ≫ map' (mk₂ (map' S 0 1) (map' S 1 2)) 1 2 = 0

Next tactic:
exact h.toIsComplex.zero 0
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      

Proof state:
case mp.left
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ ShortComplex.Exact (sc' (mk₂ (map' S 0 1) (map' S 1 2)) (_ : IsComplex (mk₂ (map' S 0 1) (map' S 1 2))) 0 1 2)

Next tactic:
exact h.exact 0 (by linarith)
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ 0 + 2 ≤ n + 2

Next tactic:
linarith
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · 

Proof state:
case mp.right
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (δ₀ S)

Next tactic:
exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · 

Proof state:
case mpr
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
⊢ Exact (mk₂ (map' S 0 1) (map' S 1 2)) ∧ Exact (δ₀ S) → Exact S

Next tactic:
rintro ⟨h, h₀⟩
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    

Proof state:
case mpr.intro
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
⊢ Exact S

Next tactic:
refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · 

Proof state:
case mpr.intro.refine'_1
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
i : ℕ
hi : autoParam (i + 2 ≤ n + 2) _auto✝
⊢ map' S i (i + 1) ≫ map' S (i + 1) (i + 2) = 0

Next tactic:
obtain _ | i := i
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · obtain _ | i := i
      · 

Proof state:
case mpr.intro.refine'_1.zero
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
hi : autoParam (Nat.zero + 2 ≤ n + 2) _auto✝
⊢ map' S Nat.zero (Nat.zero + 1) ≫ map' S (Nat.zero + 1) (Nat.zero + 2) = 0

Next tactic:
exact h.toIsComplex.zero 0
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · obtain _ | i := i
      · exact h.toIsComplex.zero 0
      · 

Proof state:
case mpr.intro.refine'_1.succ
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
i : ℕ
hi : autoParam (Nat.succ i + 2 ≤ n + 2) _auto✝
⊢ map' S (Nat.succ i) (Nat.succ i + 1) ≫ map' S (Nat.succ i + 1) (Nat.succ i + 2) = 0

Next tactic:
exact h₀.toIsComplex.zero i
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · obtain _ | i := i
      · exact h.toIsComplex.zero 0
      · exact h₀.toIsComplex.zero i
    · 

Proof state:
case mpr.intro.refine'_2
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
i : ℕ
hi : autoParam (i + 2 ≤ n + 2) _auto✝
⊢ ShortComplex.Exact (sc S (_ : IsComplex S) i)

Next tactic:
obtain _ | i := i
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · obtain _ | i := i
      · exact h.toIsComplex.zero 0
      · exact h₀.toIsComplex.zero i
    · obtain _ | i := i
      · 

Proof state:
case mpr.intro.refine'_2.zero
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
hi : autoParam (Nat.zero + 2 ≤ n + 2) _auto✝
⊢ ShortComplex.Exact (sc S (_ : IsComplex S) Nat.zero)

Next tactic:
exact h.exact 0
lemma exact_iff_δ₀ (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact ∧ S.δ₀.Exact := by
  constructor
  · intro h
    constructor
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero 0
      exact h.exact 0 (by linarith)
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero (i + 1)))
        (fun i hi => h.exact (i + 1))
  · rintro ⟨h, h₀⟩
    refine' Exact.mk (IsComplex.mk (fun i hi => _)) (fun i hi => _)
    · obtain _ | i := i
      · exact h.toIsComplex.zero 0
      · exact h₀.toIsComplex.zero i
    · obtain _ | i := i
      · exact h.exact 0
      · 

Proof state:
case mpr.intro.refine'_2.succ
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
i : ℕ
hi : autoParam (Nat.succ i + 2 ≤ n + 2) _auto✝
⊢ ShortComplex.Exact (sc S (_ : IsComplex S) (Nat.succ i))

Next tactic:
exact h₀.exact i
/-- If `S : ComposableArrows C (n + 2)` is such that the first two arrows form
an exact sequence and that the tail `S.δ₀` is exact, then `S` is also exact.
See `ShortComplex.SnakeInput.snake_lemma` in `Algebra.Homology.ShortComplex.SnakeLemma`
for a use of this lemma. -/
lemma exact_of_δ₀ {S : ComposableArrows C (n + 2)}
    (h : (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact) (h₀ : S.δ₀.Exact) : S.Exact := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
⊢ Exact S

Next tactic:
rw [exact_iff_δ₀]
/-- If `S : ComposableArrows C (n + 2)` is such that the first two arrows form
an exact sequence and that the tail `S.δ₀` is exact, then `S` is also exact.
See `ShortComplex.SnakeInput.snake_lemma` in `Algebra.Homology.ShortComplex.SnakeLemma`
for a use of this lemma. -/
lemma exact_of_δ₀ {S : ComposableArrows C (n + 2)}
    (h : (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact) (h₀ : S.δ₀.Exact) : S.Exact := by
  rw [exact_iff_δ₀]
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
⊢ Exact (mk₂ (map' S 0 1) (map' S 1 2)) ∧ Exact (δ₀ S)

Next tactic:
constructor
/-- If `S : ComposableArrows C (n + 2)` is such that the first two arrows form
an exact sequence and that the tail `S.δ₀` is exact, then `S` is also exact.
See `ShortComplex.SnakeInput.snake_lemma` in `Algebra.Homology.ShortComplex.SnakeLemma`
for a use of this lemma. -/
lemma exact_of_δ₀ {S : ComposableArrows C (n + 2)}
    (h : (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact) (h₀ : S.δ₀.Exact) : S.Exact := by
  rw [exact_iff_δ₀]
  constructor <;> 

Proof state:
case left
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
⊢ Exact (mk₂ (map' S 0 1) (map' S 1 2))

Next tactic:
assumption
/-- If `S : ComposableArrows C (n + 2)` is such that the first two arrows form
an exact sequence and that the tail `S.δ₀` is exact, then `S` is also exact.
See `ShortComplex.SnakeInput.snake_lemma` in `Algebra.Homology.ShortComplex.SnakeLemma`
for a use of this lemma. -/
lemma exact_of_δ₀ {S : ComposableArrows C (n + 2)}
    (h : (mk₂ (S.map' 0 1) (S.map' 1 2)).Exact) (h₀ : S.δ₀.Exact) : S.Exact := by
  rw [exact_iff_δ₀]
  constructor <;> 

Proof state:
case right
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n : ℕ
S✝ : ComposableArrows C n
S : ComposableArrows C (n + 2)
h : Exact (mk₂ (map' S 0 1) (map' S 1 2))
h₀ : Exact (δ₀ S)
⊢ Exact (δ₀ S)

Next tactic:
assumption
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
⊢ Exact S ↔ Exact (δlast S) ∧ Exact (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
constructor
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · 

Proof state:
case mp
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
⊢ Exact S → Exact (δlast S) ∧ Exact (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
intro h
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    

Proof state:
case mp
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (δlast S) ∧ Exact (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
constructor
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · 

Proof state:
case mp.left
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (δlast S)

Next tactic:
exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · 

Proof state:
case mp.right
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ Exact (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
rw [exact₂_iff]
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · rw [exact₂_iff]; 

Proof state:
case mp.right
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ ShortComplex.Exact (sc' (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2))) ?mp.right.hS 0 1 2)
case mp.right.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ IsComplex (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
swap
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · rw [exact₂_iff]; swap
      · 

Proof state:
case mp.right.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ IsComplex (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))

Next tactic:
rw [isComplex₂_iff]
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        

Proof state:
case mp.right.hS
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ map' (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2))) 0 1 ≫
      map' (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2))) 1 2 =
    0

Next tactic:
exact h.toIsComplex.zero n
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero n
      

Proof state:
case mp.right
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ ShortComplex.Exact
    (sc' (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))
      (_ : IsComplex (mk₂ (map' S n (n + 1)) (map' S (n + 1) (n + 2)))) 0 1 2)

Next tactic:
exact h.exact n (by linarith)
lemma exact_iff_δlast {n : ℕ} (S : ComposableArrows C (n + 2)) :
    S.Exact ↔ S.δlast.Exact ∧ (mk₂ (S.map' n (n + 1)) (S.map' (n + 1) (n + 2))).Exact := by
  constructor
  · intro h
    constructor
    · exact Exact.mk (IsComplex.mk (fun i hi => h.toIsComplex.zero i))
        (fun i hi => h.exact i)
    · rw [exact₂_iff]; swap
      · rw [isComplex₂_iff]
        exact h.toIsComplex.zero n
      exact h.exact n (by 

Proof state:
C : Type u_1
inst✝¹ : Category.{u_2, u_1} C
inst✝ : HasZeroMorphisms C
n✝ : ℕ
S✝ : ComposableArrows C n✝
n : ℕ
S : ComposableArrows C (n + 2)
h : Exact S
⊢ n + 2 ≤ n + 2

Next tactic:
linarith