l3lab/ntp-mathlib huggingface dataset:
/-- `MulSemiringAction.toAlgHom` is bijective. -/
theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite G]
    [MulSemiringAction G F] [FaithfulSMul G F] :
    Function.Bijective (MulSemiringAction.toAlgHom _ _ : G → F →ₐ[subfield G F] F) := by
  cases nonempty_fintype G
  rw [Fintype.bijective_iff_injective_and_card]
  constructor
  · 

Proof state:
case intro.left
M : Type u
inst✝⁹ : Monoid M
G✝ : Type u
inst✝⁸ : Group G✝
F✝ : Type v
inst✝⁷ : Field F✝
inst✝⁶ : MulSemiringAction M F✝
inst✝⁵ : MulSemiringAction G✝ F✝
m : M
G : Type u
F : Type v
inst✝⁴ : Group G
inst✝³ : Field F
inst✝² : Finite G
inst✝¹ : MulSemiringAction G F
inst✝ : FaithfulSMul G F
val✝ : Fintype G
⊢ Function.Injective (MulSemiringAction.toAlgHom (↥(subfield G F)) F)

Next tactic:
exact MulSemiringAction.toAlgHom_injective _ F
/-- `MulSemiringAction.toAlgHom` is bijective. -/
theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite G]
    [MulSemiringAction G F] [FaithfulSMul G F] :
    Function.Bijective (MulSemiringAction.toAlgHom _ _ : G → F →ₐ[subfield G F] F) := by
  cases nonempty_fintype G
  rw [Fintype.bijective_iff_injective_and_card]
  constructor
  · exact MulSemiringAction.toAlgHom_injective _ F
  · 

Proof state:
case intro.right
M : Type u
inst✝⁹ : Monoid M
G✝ : Type u
inst✝⁸ : Group G✝
F✝ : Type v
inst✝⁷ : Field F✝
inst✝⁶ : MulSemiringAction M F✝
inst✝⁵ : MulSemiringAction G✝ F✝
m : M
G : Type u
F : Type v
inst✝⁴ : Group G
inst✝³ : Field F
inst✝² : Finite G
inst✝¹ : MulSemiringAction G F
inst✝ : FaithfulSMul G F
val✝ : Fintype G
⊢ Fintype.card G = Fintype.card (F →ₐ[↥(subfield G F)] F)

Next tactic:
apply le_antisymm
/-- `MulSemiringAction.toAlgHom` is bijective. -/
theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite G]
    [MulSemiringAction G F] [FaithfulSMul G F] :
    Function.Bijective (MulSemiringAction.toAlgHom _ _ : G → F →ₐ[subfield G F] F) := by
  cases nonempty_fintype G
  rw [Fintype.bijective_iff_injective_and_card]
  constructor
  · exact MulSemiringAction.toAlgHom_injective _ F
  · apply le_antisymm
    · 

Proof state:
case intro.right.a
M : Type u
inst✝⁹ : Monoid M
G✝ : Type u
inst✝⁸ : Group G✝
F✝ : Type v
inst✝⁷ : Field F✝
inst✝⁶ : MulSemiringAction M F✝
inst✝⁵ : MulSemiringAction G✝ F✝
m : M
G : Type u
F : Type v
inst✝⁴ : Group G
inst✝³ : Field F
inst✝² : Finite G
inst✝¹ : MulSemiringAction G F
inst✝ : FaithfulSMul G F
val✝ : Fintype G
⊢ Fintype.card G ≤ Fintype.card (F →ₐ[↥(subfield G F)] F)

Next tactic:
exact Fintype.card_le_of_injective _ (MulSemiringAction.toAlgHom_injective _ F)
/-- `MulSemiringAction.toAlgHom` is bijective. -/
theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite G]
    [MulSemiringAction G F] [FaithfulSMul G F] :
    Function.Bijective (MulSemiringAction.toAlgHom _ _ : G → F →ₐ[subfield G F] F) := by
  cases nonempty_fintype G
  rw [Fintype.bijective_iff_injective_and_card]
  constructor
  · exact MulSemiringAction.toAlgHom_injective _ F
  · apply le_antisymm
    · exact Fintype.card_le_of_injective _ (MulSemiringAction.toAlgHom_injective _ F)
    · 

Proof state:
case intro.right.a
M : Type u
inst✝⁹ : Monoid M
G✝ : Type u
inst✝⁸ : Group G✝
F✝ : Type v
inst✝⁷ : Field F✝
inst✝⁶ : MulSemiringAction M F✝
inst✝⁵ : MulSemiringAction G✝ F✝
m : M
G : Type u
F : Type v
inst✝⁴ : Group G
inst✝³ : Field F
inst✝² : Finite G
inst✝¹ : MulSemiringAction G F
inst✝ : FaithfulSMul G F
val✝ : Fintype G
⊢ Fintype.card (F →ₐ[↥(subfield G F)] F) ≤ Fintype.card G

Next tactic:
rw [← finrank_eq_card G F]
/-- `MulSemiringAction.toAlgHom` is bijective. -/
theorem toAlgHom_bijective (G : Type u) (F : Type v) [Group G] [Field F] [Finite G]
    [MulSemiringAction G F] [FaithfulSMul G F] :
    Function.Bijective (MulSemiringAction.toAlgHom _ _ : G → F →ₐ[subfield G F] F) := by
  cases nonempty_fintype G
  rw [Fintype.bijective_iff_injective_and_card]
  constructor
  · exact MulSemiringAction.toAlgHom_injective _ F
  · apply le_antisymm
    · exact Fintype.card_le_of_injective _ (MulSemiringAction.toAlgHom_injective _ F)
    · rw [← finrank_eq_card G F]
      

Proof state:
case intro.right.a
M : Type u
inst✝⁹ : Monoid M
G✝ : Type u
inst✝⁸ : Group G✝
F✝ : Type v
inst✝⁷ : Field F✝
inst✝⁶ : MulSemiringAction M F✝
inst✝⁵ : MulSemiringAction G✝ F✝
m : M
G : Type u
F : Type v
inst✝⁴ : Group G
inst✝³ : Field F
inst✝² : Finite G
inst✝¹ : MulSemiringAction G F
inst✝ : FaithfulSMul G F
val✝ : Fintype G
⊢ Fintype.card (F →ₐ[↥(subfield G F)] F) ≤ finrank (↥(subfield G F)) F

Next tactic:
exact LE.le.trans_eq (finrank_algHom _ F) (finrank_linear_map' _ _ _)
/-- The preadditive Co-Yoneda functor on `P` preserves finite colimits if `P` is projective. -/
noncomputable def preservesFiniteColimitsPreadditiveCoyonedaObjOfProjective
    (P : C) [hP : Projective P] :
    PreservesFiniteColimits (preadditiveCoyonedaObj (op P)) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : Projective P
⊢ PreservesFiniteColimits (preadditiveCoyonedaObj (op P))

Next tactic:
haveI := (projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj' P).mp hP
/-- The preadditive Co-Yoneda functor on `P` preserves finite colimits if `P` is projective. -/
noncomputable def preservesFiniteColimitsPreadditiveCoyonedaObjOfProjective
    (P : C) [hP : Projective P] :
    PreservesFiniteColimits (preadditiveCoyonedaObj (op P)) := by
  haveI := (projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj' P).mp hP
  -- porting note: this next instance wasn't necessary in Lean 3
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : Projective P
this : Functor.PreservesEpimorphisms (preadditiveCoyoneda.obj (op P))
⊢ PreservesFiniteColimits (preadditiveCoyonedaObj (op P))

Next tactic:
haveI := @Functor.preservesEpimorphisms_of_preserves_of_reflects _ _ _ _ _ _ _ _ this _
/-- The preadditive Co-Yoneda functor on `P` preserves finite colimits if `P` is projective. -/
noncomputable def preservesFiniteColimitsPreadditiveCoyonedaObjOfProjective
    (P : C) [hP : Projective P] :
    PreservesFiniteColimits (preadditiveCoyonedaObj (op P)) := by
  haveI := (projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj' P).mp hP
  -- porting note: this next instance wasn't necessary in Lean 3
  haveI := @Functor.preservesEpimorphisms_of_preserves_of_reflects _ _ _ _ _ _ _ _ this _
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : Projective P
this✝ : Functor.PreservesEpimorphisms (preadditiveCoyoneda.obj (op P))
this : Functor.PreservesEpimorphisms (preadditiveCoyonedaObj (op P))
⊢ PreservesFiniteColimits (preadditiveCoyonedaObj (op P))

Next tactic:
apply Functor.preservesFiniteColimitsOfPreservesEpisAndKernels
/-- An object is projective if its preadditive Co-Yoneda functor preserves finite colimits. -/
theorem projective_of_preservesFiniteColimits_preadditiveCoyonedaObj (P : C)
    [hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))] : Projective P := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))
⊢ Projective P

Next tactic:
rw [projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj']
/-- An object is projective if its preadditive Co-Yoneda functor preserves finite colimits. -/
theorem projective_of_preservesFiniteColimits_preadditiveCoyonedaObj (P : C)
    [hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))] : Projective P := by
  rw [projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj']
  -- porting note: this next line wasn't necessary in Lean 3
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))
⊢ Functor.PreservesEpimorphisms (preadditiveCoyoneda.obj (op P))

Next tactic:
dsimp only [preadditiveCoyoneda]
/-- An object is projective if its preadditive Co-Yoneda functor preserves finite colimits. -/
theorem projective_of_preservesFiniteColimits_preadditiveCoyonedaObj (P : C)
    [hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))] : Projective P := by
  rw [projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj']
  -- porting note: this next line wasn't necessary in Lean 3
  dsimp only [preadditiveCoyoneda]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Abelian C
P : C
hP : PreservesFiniteColimits (preadditiveCoyonedaObj (op P))
⊢ Functor.PreservesEpimorphisms (preadditiveCoyonedaObj (op P) ⋙ forget₂ (ModuleCat (End (op P))) AddCommGroupCat)

Next tactic:
infer_instance
@[simp]
theorem inv_neg' (a : α) : (-a)⁻¹ = -a⁻¹ := by
  

Proof state:
α : Type u_1
inst✝¹ : Group α
inst✝ : HasDistribNeg α
a : α
⊢ (-a)⁻¹ = -a⁻¹

Next tactic:
rw [eq_comm, eq_inv_iff_mul_eq_one, neg_mul, mul_neg, neg_neg, mul_left_inv]
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
⊢ ∃ y, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c

Next tactic:
have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by simp [mul_sub, mul_comm])
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by 

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
⊢ -(x * x - b * x) = x * (b - x)

Next tactic:
simp [mul_sub, mul_comm]
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by simp [mul_sub, mul_comm])
  

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
this : c = x * (b - x)
⊢ ∃ y, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c

Next tactic:
refine' ⟨b - x, _, by simp, by rw [this]⟩
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by simp [mul_sub, mul_comm])
  refine' ⟨b - x, _, by 

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
this : c = x * (b - x)
⊢ x + (b - x) = b

Next tactic:
simp
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by simp [mul_sub, mul_comm])
  refine' ⟨b - x, _, by simp, by 

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
this : c = x * (b - x)
⊢ x * (b - x) = c

Next tactic:
rw [this]
/-- Vieta's formula for a quadratic equation, relating the coefficients of the polynomial with
  its roots. This particular version states that if we have a root `x` of a monic quadratic
  polynomial, then there is another root `y` such that `x + y` is negative the `a_1` coefficient
  and `x * y` is the `a_0` coefficient. -/
theorem vieta_formula_quadratic {b c x : α} (h : x * x - b * x + c = 0) :
    ∃ y : α, y * y - b * y + c = 0 ∧ x + y = b ∧ x * y = c := by
  have : c = x * (b - x) := (eq_neg_of_add_eq_zero_right h).trans (by simp [mul_sub, mul_comm])
  refine' ⟨b - x, _, by simp, by rw [this]⟩
  

Proof state:
α : Type u_1
inst✝ : NonUnitalCommRing α
a b✝ c✝ b c x : α
h : x * x - b * x + c = 0
this : c = x * (b - x)
⊢ (b - x) * (b - x) - b * (b - x) + c = 0

Next tactic:
rw [this, sub_add, ← sub_mul, sub_self]
theorem succ_ne_self [NonAssocRing α] [Nontrivial α] (a : α) : a + 1 ≠ a := fun h =>
  one_ne_zero ((add_right_inj a).mp (by 

Proof state:
α : Type u_1
inst✝¹ : NonAssocRing α
inst✝ : Nontrivial α
a : α
h : a + 1 = a
⊢ a + 1 = a + 0

Next tactic:
simp [h]
theorem pred_ne_self [NonAssocRing α] [Nontrivial α] (a : α) : a - 1 ≠ a := fun h ↦
  one_ne_zero (neg_injective ((add_right_inj a).mp (by 

Proof state:
α : Type u_1
inst✝¹ : NonAssocRing α
inst✝ : Nontrivial α
a : α
h : a - 1 = a
⊢ a + -1 = a + -0

Next tactic:
simp [← sub_eq_add_neg, h]
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
⊢ x = 0 ∨ y = 0

Next tactic:
by_cases hx : x = 0
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      

Proof state:
case pos
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : x = 0
⊢ x = 0 ∨ y = 0
case neg α : Type u_1 inst✝¹ : Ring α inst✝ : IsLeftCancelMulZero α x y : α h : x * y = 0 hx : ¬x = 0 ⊢ x = 0 ∨ y = 0

Next tactic:
{ left
        exact hx }
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { 

Proof state:
case pos
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : x = 0
⊢ x = 0 ∨ y = 0

Next tactic:
left
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        

Proof state:
case pos.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : x = 0
⊢ x = 0

Next tactic:
exact hx
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        exact hx }
      

Proof state:
case neg
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : ¬x = 0
⊢ x = 0 ∨ y = 0

Next tactic:
{ right
        rw [← sub_zero (x * y), ← mul_zero x, ← mul_sub] at h
        have := (IsLeftCancelMulZero.mul_left_cancel_of_ne_zero) hx h
        rwa [sub_zero] at this }
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        exact hx }
      { 

Proof state:
case neg
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : ¬x = 0
⊢ x = 0 ∨ y = 0

Next tactic:
right
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        exact hx }
      { right
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * y = 0
hx : ¬x = 0
⊢ y = 0

Next tactic:
rw [← sub_zero (x * y), ← mul_zero x, ← mul_sub] at h
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        exact hx }
      { right
        rw [← sub_zero (x * y), ← mul_zero x, ← mul_sub] at h
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * (y - 0) = x * 0
hx : ¬x = 0
⊢ y = 0

Next tactic:
have := (IsLeftCancelMulZero.mul_left_cancel_of_ne_zero) hx h
lemma IsLeftCancelMulZero.to_noZeroDivisors [Ring α] [IsLeftCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hx : x = 0
      { left
        exact hx }
      { right
        rw [← sub_zero (x * y), ← mul_zero x, ← mul_sub] at h
        have := (IsLeftCancelMulZero.mul_left_cancel_of_ne_zero) hx h
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsLeftCancelMulZero α
x y : α
h : x * (y - 0) = x * 0
hx : ¬x = 0
this : y - 0 = 0
⊢ y = 0

Next tactic:
rwa [sub_zero] at this
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
⊢ x = 0 ∨ y = 0

Next tactic:
by_cases hy : y = 0
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      

Proof state:
case pos
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : y = 0
⊢ x = 0 ∨ y = 0
case neg α : Type u_1 inst✝¹ : Ring α inst✝ : IsRightCancelMulZero α x y : α h : x * y = 0 hy : ¬y = 0 ⊢ x = 0 ∨ y = 0

Next tactic:
{ right
        exact hy }
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { 

Proof state:
case pos
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : y = 0
⊢ x = 0 ∨ y = 0

Next tactic:
right
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        

Proof state:
case pos.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : y = 0
⊢ y = 0

Next tactic:
exact hy
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        exact hy }
      

Proof state:
case neg
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : ¬y = 0
⊢ x = 0 ∨ y = 0

Next tactic:
{ left
        rw [← sub_zero (x * y), ← zero_mul y, ← sub_mul] at h
        have := (IsRightCancelMulZero.mul_right_cancel_of_ne_zero) hy h
        rwa [sub_zero] at this }
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        exact hy }
      { 

Proof state:
case neg
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : ¬y = 0
⊢ x = 0 ∨ y = 0

Next tactic:
left
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        exact hy }
      { left
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : x * y = 0
hy : ¬y = 0
⊢ x = 0

Next tactic:
rw [← sub_zero (x * y), ← zero_mul y, ← sub_mul] at h
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        exact hy }
      { left
        rw [← sub_zero (x * y), ← zero_mul y, ← sub_mul] at h
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : (x - 0) * y = 0 * y
hy : ¬y = 0
⊢ x = 0

Next tactic:
have := (IsRightCancelMulZero.mul_right_cancel_of_ne_zero) hy h
lemma IsRightCancelMulZero.to_noZeroDivisors [Ring α] [IsRightCancelMulZero α] :
    NoZeroDivisors α :=
  { eq_zero_or_eq_zero_of_mul_eq_zero := fun {x y} h ↦ by
      by_cases hy : y = 0
      { right
        exact hy }
      { left
        rw [← sub_zero (x * y), ← zero_mul y, ← sub_mul] at h
        have := (IsRightCancelMulZero.mul_right_cancel_of_ne_zero) hy h
        

Proof state:
case neg.h
α : Type u_1
inst✝¹ : Ring α
inst✝ : IsRightCancelMulZero α
x y : α
h : (x - 0) * y = 0 * y
hy : ¬y = 0
this : x - 0 = 0
⊢ x = 0

Next tactic:
rwa [sub_zero] at this
instance (priority := 100) NoZeroDivisors.to_isCancelMulZero [Ring α] [NoZeroDivisors α] :
    IsCancelMulZero α :=
  { mul_left_cancel_of_ne_zero := fun ha h ↦ by
      

Proof state:
α : Type ?u.22112
inst✝¹ : Ring α
inst✝ : NoZeroDivisors α
a✝ b✝ c✝ : α
ha : a✝ ≠ 0
h : a✝ * b✝ = a✝ * c✝
⊢ b✝ = c✝

Next tactic:
rw [← sub_eq_zero, ← mul_sub] at h
instance (priority := 100) NoZeroDivisors.to_isCancelMulZero [Ring α] [NoZeroDivisors α] :
    IsCancelMulZero α :=
  { mul_left_cancel_of_ne_zero := fun ha h ↦ by
      rw [← sub_eq_zero, ← mul_sub] at h
      

Proof state:
α : Type ?u.22112
inst✝¹ : Ring α
inst✝ : NoZeroDivisors α
a✝ b✝ c✝ : α
ha : a✝ ≠ 0
h : a✝ * (b✝ - c✝) = 0
⊢ b✝ = c✝

Next tactic:
exact sub_eq_zero.1 ((eq_zero_or_eq_zero_of_mul_eq_zero h).resolve_left ha)
instance (priority := 100) NoZeroDivisors.to_isCancelMulZero [Ring α] [NoZeroDivisors α] :
    IsCancelMulZero α :=
  { mul_left_cancel_of_ne_zero := fun ha h ↦ by
      rw [← sub_eq_zero, ← mul_sub] at h
      exact sub_eq_zero.1 ((eq_zero_or_eq_zero_of_mul_eq_zero h).resolve_left ha)
    mul_right_cancel_of_ne_zero := fun hb h ↦ by
      

Proof state:
α : Type ?u.22112
inst✝¹ : Ring α
inst✝ : NoZeroDivisors α
a✝ b✝ c✝ : α
hb : b✝ ≠ 0
h : a✝ * b✝ = c✝ * b✝
⊢ a✝ = c✝

Next tactic:
rw [← sub_eq_zero, ← sub_mul] at h
instance (priority := 100) NoZeroDivisors.to_isCancelMulZero [Ring α] [NoZeroDivisors α] :
    IsCancelMulZero α :=
  { mul_left_cancel_of_ne_zero := fun ha h ↦ by
      rw [← sub_eq_zero, ← mul_sub] at h
      exact sub_eq_zero.1 ((eq_zero_or_eq_zero_of_mul_eq_zero h).resolve_left ha)
    mul_right_cancel_of_ne_zero := fun hb h ↦ by
      rw [← sub_eq_zero, ← sub_mul] at h
      

Proof state:
α : Type ?u.22112
inst✝¹ : Ring α
inst✝ : NoZeroDivisors α
a✝ b✝ c✝ : α
hb : b✝ ≠ 0
h : (a✝ - c✝) * b✝ = 0
⊢ a✝ = c✝

Next tactic:
exact sub_eq_zero.1 ((eq_zero_or_eq_zero_of_mul_eq_zero h).resolve_right hb)