l3lab/ntp-mathlib huggingface dataset:
instance : OrderRingHomClass (α →+*o β) α β
    where
  coe f := f.toFun
  coe_injective' f g h := by
    obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; 

Proof state:
case mk.mk.mk.mk
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝⁷ : NonAssocSemiring α
inst✝⁶ : Preorder α
inst✝⁵ : NonAssocSemiring β
inst✝⁴ : Preorder β
inst✝³ : NonAssocSemiring γ
inst✝² : Preorder γ
inst✝¹ : NonAssocSemiring δ
inst✝ : Preorder δ
toMonoidHom✝¹ : α →* β
map_zero'✝¹ : OneHom.toFun (↑toMonoidHom✝¹) 0 = 0
map_add'✝¹ :
  ∀ (x y : α), OneHom.toFun (↑toMonoidHom✝¹) (x + y) = OneHom.toFun (↑toMonoidHom✝¹) x + OneHom.toFun (↑toMonoidHom✝¹) y
monotone'✝¹ : Monotone (↑↑{ toMonoidHom := toMonoidHom✝¹, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }).toFun
toMonoidHom✝ : α →* β
map_zero'✝ : OneHom.toFun (↑toMonoidHom✝) 0 = 0
map_add'✝ :
  ∀ (x y : α), OneHom.toFun (↑toMonoidHom✝) (x + y) = OneHom.toFun (↑toMonoidHom✝) x + OneHom.toFun (↑toMonoidHom✝) y
monotone'✝ : Monotone (↑↑{ toMonoidHom := toMonoidHom✝, map_zero' := map_zero'✝, map_add' := map_add'✝ }).toFun
h :
  (fun f => f.toFun)
      { toRingHom := { toMonoidHom := toMonoidHom✝¹, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ },
        monotone' := monotone'✝¹ } =
    (fun f => f.toFun)
      { toRingHom := { toMonoidHom := toMonoidHom✝, map_zero' := map_zero'✝, map_add' := map_add'✝ },
        monotone' := monotone'✝ }
⊢ { toRingHom := { toMonoidHom := toMonoidHom✝¹, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ },
      monotone' := monotone'✝¹ } =
    { toRingHom := { toMonoidHom := toMonoidHom✝, map_zero' := map_zero'✝, map_add' := map_add'✝ },
      monotone' := monotone'✝ }

Next tactic:
congr
instance : OrderRingHomClass (α →+*o β) α β
    where
  coe f := f.toFun
  coe_injective' f g h := by
    obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; congr
    -- porting note: needed to add the following line
    

Proof state:
case mk.mk.mk.mk.e_toRingHom.e_toMonoidHom
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝⁷ : NonAssocSemiring α
inst✝⁶ : Preorder α
inst✝⁵ : NonAssocSemiring β
inst✝⁴ : Preorder β
inst✝³ : NonAssocSemiring γ
inst✝² : Preorder γ
inst✝¹ : NonAssocSemiring δ
inst✝ : Preorder δ
toMonoidHom✝¹ : α →* β
map_zero'✝¹ : OneHom.toFun (↑toMonoidHom✝¹) 0 = 0
map_add'✝¹ :
  ∀ (x y : α), OneHom.toFun (↑toMonoidHom✝¹) (x + y) = OneHom.toFun (↑toMonoidHom✝¹) x + OneHom.toFun (↑toMonoidHom✝¹) y
monotone'✝¹ : Monotone (↑↑{ toMonoidHom := toMonoidHom✝¹, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ }).toFun
toMonoidHom✝ : α →* β
map_zero'✝ : OneHom.toFun (↑toMonoidHom✝) 0 = 0
map_add'✝ :
  ∀ (x y : α), OneHom.toFun (↑toMonoidHom✝) (x + y) = OneHom.toFun (↑toMonoidHom✝) x + OneHom.toFun (↑toMonoidHom✝) y
monotone'✝ : Monotone (↑↑{ toMonoidHom := toMonoidHom✝, map_zero' := map_zero'✝, map_add' := map_add'✝ }).toFun
h :
  (fun f => f.toFun)
      { toRingHom := { toMonoidHom := toMonoidHom✝¹, map_zero' := map_zero'✝¹, map_add' := map_add'✝¹ },
        monotone' := monotone'✝¹ } =
    (fun f => f.toFun)
      { toRingHom := { toMonoidHom := toMonoidHom✝, map_zero' := map_zero'✝, map_add' := map_add'✝ },
        monotone' := monotone'✝ }
⊢ toMonoidHom✝¹ = toMonoidHom✝

Next tactic:
exact MonoidHom.monoidHomClass.coe_injective' h
@[simp]
theorem cancel_right {f₁ f₂ : β →+*o γ} {g : α →+*o β} (hg : Surjective g) :
    f₁.comp g = f₂.comp g ↔ f₁ = f₂ :=
  ⟨fun h => ext <| hg.forall.2 <| FunLike.ext_iff.1 h, fun h => by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝⁷ : NonAssocSemiring α
inst✝⁶ : Preorder α
inst✝⁵ : NonAssocSemiring β
inst✝⁴ : Preorder β
inst✝³ : NonAssocSemiring γ
inst✝² : Preorder γ
inst✝¹ : NonAssocSemiring δ
inst✝ : Preorder δ
f₁ f₂ : β →+*o γ
g : α →+*o β
hg : Surjective ⇑g
h : f₁ = f₂
⊢ OrderRingHom.comp f₁ g = OrderRingHom.comp f₂ g

Next tactic:
rw [h]
@[simp]
theorem cancel_left {f : β →+*o γ} {g₁ g₂ : α →+*o β} (hf : Injective f) :
    f.comp g₁ = f.comp g₂ ↔ g₁ = g₂ :=
  ⟨fun h => ext fun a => hf <| by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝⁷ : NonAssocSemiring α
inst✝⁶ : Preorder α
inst✝⁵ : NonAssocSemiring β
inst✝⁴ : Preorder β
inst✝³ : NonAssocSemiring γ
inst✝² : Preorder γ
inst✝¹ : NonAssocSemiring δ
inst✝ : Preorder δ
f : β →+*o γ
g₁ g₂ : α →+*o β
hf : Injective ⇑f
h : OrderRingHom.comp f g₁ = OrderRingHom.comp f g₂
a : α
⊢ f (g₁ a) = f (g₂ a)

Next tactic:
rw [← comp_apply, h, comp_apply]
instance : OrderRingIsoClass (α ≃+*o β) α β
    where
  coe f := f.toFun
  inv f := f.invFun
  coe_injective' f g h₁ h₂ := by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝¹¹ : Mul α
inst✝¹⁰ : Add α
inst✝⁹ : LE α
inst✝⁸ : Mul β
inst✝⁷ : Add β
inst✝⁶ : LE β
inst✝⁵ : Mul γ
inst✝⁴ : Add γ
inst✝³ : LE γ
inst✝² : Mul δ
inst✝¹ : Add δ
inst✝ : LE δ
f g : α ≃+*o β
h₁ : (fun f => f.toFun) f = (fun f => f.toFun) g
h₂ : (fun f => f.invFun) f = (fun f => f.invFun) g
⊢ f = g

Next tactic:
obtain ⟨⟨⟨_, _⟩, _⟩, _⟩ := f
instance : OrderRingIsoClass (α ≃+*o β) α β
    where
  coe f := f.toFun
  inv f := f.invFun
  coe_injective' f g h₁ h₂ := by
    obtain ⟨⟨⟨_, _⟩, _⟩, _⟩ := f
    

Proof state:
case mk.mk.mk
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝¹¹ : Mul α
inst✝¹⁰ : Add α
inst✝⁹ : LE α
inst✝⁸ : Mul β
inst✝⁷ : Add β
inst✝⁶ : LE β
inst✝⁵ : Mul γ
inst✝⁴ : Add γ
inst✝³ : LE γ
inst✝² : Mul δ
inst✝¹ : Add δ
inst✝ : LE δ
g : α ≃+*o β
toFun✝ : α → β
invFun✝ : β → α
left_inv✝ : LeftInverse invFun✝ toFun✝
right_inv✝ : Function.RightInverse invFun✝ toFun✝
map_mul'✝ :
  ∀ (x y : α),
    Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } (x * y) =
      Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } x *
        Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } y
map_add'✝ :
  ∀ (x y : α),
    Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } (x + y) =
      Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } x +
        Equiv.toFun { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ } y
map_le_map_iff'✝ :
  ∀ {a b : α},
    Equiv.toFun
          { toEquiv := { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ },
              map_mul' := map_mul'✝, map_add' := map_add'✝ }.toEquiv
          a ≤
        Equiv.toFun
          { toEquiv := { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ },
              map_mul' := map_mul'✝, map_add' := map_add'✝ }.toEquiv
          b ↔
      a ≤ b
h₁ :
  (fun f => f.toFun)
      {
        toRingEquiv :=
          { toEquiv := { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ },
            map_mul' := map_mul'✝, map_add' := map_add'✝ },
        map_le_map_iff' := map_le_map_iff'✝ } =
    (fun f => f.toFun) g
h₂ :
  (fun f => f.invFun)
      {
        toRingEquiv :=
          { toEquiv := { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ },
            map_mul' := map_mul'✝, map_add' := map_add'✝ },
        map_le_map_iff' := map_le_map_iff'✝ } =
    (fun f => f.invFun) g
⊢ {
      toRingEquiv :=
        { toEquiv := { toFun := toFun✝, invFun := invFun✝, left_inv := left_inv✝, right_inv := right_inv✝ },
          map_mul' := map_mul'✝, map_add' := map_add'✝ },
      map_le_map_iff' := map_le_map_iff'✝ } =
    g

Next tactic:
obtain ⟨⟨⟨_, _⟩, _⟩, _⟩ := g
@[simp]
theorem refl_apply (x : α) : OrderRingIso.refl α x = x := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝¹¹ : Mul α
inst✝¹⁰ : Add α
inst✝⁹ : LE α
inst✝⁸ : Mul β
inst✝⁷ : Add β
inst✝⁶ : LE β
inst✝⁵ : Mul γ
inst✝⁴ : Add γ
inst✝³ : LE γ
inst✝² : Mul δ
inst✝¹ : Add δ
inst✝ : LE δ
x : α
⊢ (OrderRingIso.refl α) x = x

Next tactic:
rfl
/-- The inverse of an ordered ring isomorphism as an ordered ring isomorphism. -/
@[symm]
protected def symm (e : α ≃+*o β) : β ≃+*o α :=
  ⟨e.toRingEquiv.symm, by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝¹¹ : Mul α
inst✝¹⁰ : Add α
inst✝⁹ : LE α
inst✝⁸ : Mul β
inst✝⁷ : Add β
inst✝⁶ : LE β
inst✝⁵ : Mul γ
inst✝⁴ : Add γ
inst✝³ : LE γ
inst✝² : Mul δ
inst✝¹ : Add δ
inst✝ : LE δ
e : α ≃+*o β
⊢ ∀ {a b : β},
    Equiv.toFun (RingEquiv.symm e.toRingEquiv).toEquiv a ≤ Equiv.toFun (RingEquiv.symm e.toRingEquiv).toEquiv b ↔ a ≤ b

Next tactic:
intro a b
/-- The inverse of an ordered ring isomorphism as an ordered ring isomorphism. -/
@[symm]
protected def symm (e : α ≃+*o β) : β ≃+*o α :=
  ⟨e.toRingEquiv.symm, by
    intro a b
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝¹¹ : Mul α
inst✝¹⁰ : Add α
inst✝⁹ : LE α
inst✝⁸ : Mul β
inst✝⁷ : Add β
inst✝⁶ : LE β
inst✝⁵ : Mul γ
inst✝⁴ : Add γ
inst✝³ : LE γ
inst✝² : Mul δ
inst✝¹ : Add δ
inst✝ : LE δ
e : α ≃+*o β
a b : β
⊢ Equiv.toFun (RingEquiv.symm e.toRingEquiv).toEquiv a ≤ Equiv.toFun (RingEquiv.symm e.toRingEquiv).toEquiv b ↔ a ≤ b

Next tactic:
erw [← map_le_map_iff e, e.1.apply_symm_apply, e.1.apply_symm_apply]
theorem toOrderRingHom_injective : Injective (toOrderRingHom : α ≃+*o β → α →+*o β) :=
  fun f g h => FunLike.coe_injective <| by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝⁵ : NonAssocSemiring α
inst✝⁴ : Preorder α
inst✝³ : NonAssocSemiring β
inst✝² : Preorder β
inst✝¹ : NonAssocSemiring γ
inst✝ : Preorder γ
f g : α ≃+*o β
h : toOrderRingHom f = toOrderRingHom g
⊢ (fun f => ⇑f) f = (fun f => ⇑f) g

Next tactic:
convert FunLike.ext'_iff.1 h using 0
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
⊢ f = g

Next tactic:
ext x
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
⊢ f x = g x

Next tactic:
by_contra! h' : f x ≠ g x
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
⊢ False

Next tactic:
wlog h : f x < g x generalizing α β with h₂
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    wlog h : f x < g x generalizing α β with h₂
    -- porting note: had to add the `generalizing` as there are random variables
    -- `F γ δ` flying around in context.
    · 

Proof state:
case h.inr
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
h₂ :
  ∀ {α : Type u_2} {β : Type u_3} [inst : LinearOrderedField α] [inst_1 : LinearOrderedField β] [inst_2 : Archimedean β]
    (f g : α →+*o β) (x : α), f x ≠ g x → f x < g x → False
h : ¬f x < g x
⊢ False

Next tactic:
exact h₂ g f x (Ne.symm h') (h'.lt_or_lt.resolve_left h)
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    wlog h : f x < g x generalizing α β with h₂
    -- porting note: had to add the `generalizing` as there are random variables
    -- `F γ δ` flying around in context.
    · exact h₂ g f x (Ne.symm h') (h'.lt_or_lt.resolve_left h)
    

Proof state:
F : Type u_1
α✝ : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
α : Type u_2
β : Type u_3
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
h : f x < g x
⊢ False

Next tactic:
obtain ⟨q, hf, hg⟩ := exists_rat_btwn h
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    wlog h : f x < g x generalizing α β with h₂
    -- porting note: had to add the `generalizing` as there are random variables
    -- `F γ δ` flying around in context.
    · exact h₂ g f x (Ne.symm h') (h'.lt_or_lt.resolve_left h)
    obtain ⟨q, hf, hg⟩ := exists_rat_btwn h
    

Proof state:
case intro.intro
F : Type u_1
α✝ : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
α : Type u_2
β : Type u_3
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
h : f x < g x
q : ℚ
hf : f x < ↑q
hg : ↑q < g x
⊢ False

Next tactic:
rw [← map_ratCast f] at hf
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    wlog h : f x < g x generalizing α β with h₂
    -- porting note: had to add the `generalizing` as there are random variables
    -- `F γ δ` flying around in context.
    · exact h₂ g f x (Ne.symm h') (h'.lt_or_lt.resolve_left h)
    obtain ⟨q, hf, hg⟩ := exists_rat_btwn h
    rw [← map_ratCast f] at hf
    

Proof state:
case intro.intro
F : Type u_1
α✝ : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
α : Type u_2
β : Type u_3
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
h : f x < g x
q : ℚ
hf : f x < f ↑q
hg : ↑q < g x
⊢ False

Next tactic:
rw [← map_ratCast g] at hg
/-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean
linear ordered field. -/
instance OrderRingHom.subsingleton [LinearOrderedField α] [LinearOrderedField β] [Archimedean β] :
    Subsingleton (α →+*o β) :=
  ⟨fun f g => by
    ext x
    by_contra! h' : f x ≠ g x
    wlog h : f x < g x generalizing α β with h₂
    -- porting note: had to add the `generalizing` as there are random variables
    -- `F γ δ` flying around in context.
    · exact h₂ g f x (Ne.symm h') (h'.lt_or_lt.resolve_left h)
    obtain ⟨q, hf, hg⟩ := exists_rat_btwn h
    rw [← map_ratCast f] at hf
    rw [← map_ratCast g] at hg
    

Proof state:
case intro.intro
F : Type u_1
α✝ : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
α : Type u_2
β : Type u_3
inst✝² : LinearOrderedField α
inst✝¹ : LinearOrderedField β
inst✝ : Archimedean β
f g : α →+*o β
x : α
h' : f x ≠ g x
h : f x < g x
q : ℚ
hf : f x < f ↑q
hg : g ↑q < g x
⊢ False

Next tactic:
exact
      (lt_asymm ((OrderHomClass.mono g).reflect_lt hg) <|
          (OrderHomClass.mono f).reflect_lt hf).elim
theorem cast_choose {a b : ℕ} (h : a ≤ b) : (b.choose a : K) = b ! / (a ! * (b - a)!) := by
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a b : ℕ
h : a ≤ b
⊢ ↑(choose b a) = ↑b ! / (↑a ! * ↑(b - a)!)

Next tactic:
have : ∀ {n : ℕ}, (n ! : K) ≠ 0 := Nat.cast_ne_zero.2 (factorial_ne_zero _)
theorem cast_choose {a b : ℕ} (h : a ≤ b) : (b.choose a : K) = b ! / (a ! * (b - a)!) := by
  have : ∀ {n : ℕ}, (n ! : K) ≠ 0 := Nat.cast_ne_zero.2 (factorial_ne_zero _)
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a b : ℕ
h : a ≤ b
this : ∀ {n : ℕ}, ↑n ! ≠ 0
⊢ ↑(choose b a) = ↑b ! / (↑a ! * ↑(b - a)!)

Next tactic:
rw [eq_div_iff_mul_eq (mul_ne_zero this this)]
theorem cast_choose {a b : ℕ} (h : a ≤ b) : (b.choose a : K) = b ! / (a ! * (b - a)!) := by
  have : ∀ {n : ℕ}, (n ! : K) ≠ 0 := Nat.cast_ne_zero.2 (factorial_ne_zero _)
  rw [eq_div_iff_mul_eq (mul_ne_zero this this)]
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a b : ℕ
h : a ≤ b
this : ∀ {n : ℕ}, ↑n ! ≠ 0
⊢ ↑(choose b a) * (↑a ! * ↑(b - a)!) = ↑b !

Next tactic:
rw_mod_cast [← mul_assoc, choose_mul_factorial_mul_factorial h]
theorem cast_add_choose {a b : ℕ} : ((a + b).choose a : K) = (a + b)! / (a ! * b !) := by
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a b : ℕ
⊢ ↑(choose (a + b) a) = ↑(a + b)! / (↑a ! * ↑b !)

Next tactic:
rw [cast_choose K (_root_.le_add_right le_rfl), add_tsub_cancel_left]
theorem cast_choose_eq_ascPochhammer_div (a b : ℕ) :
    (a.choose b : K) = (ascPochhammer K b).eval ↑(a - (b - 1)) / b ! := by
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a b : ℕ
⊢ ↑(choose a b) = Polynomial.eval (↑(a - (b - 1))) (ascPochhammer K b) / ↑b !

Next tactic:
rw [eq_div_iff_mul_eq (cast_ne_zero.2 b.factorial_ne_zero : (b ! : K) ≠ 0), ← cast_mul,
    mul_comm, ← descFactorial_eq_factorial_mul_choose, ← cast_descFactorial]
theorem cast_choose_two (a : ℕ) : (a.choose 2 : K) = a * (a - 1) / 2 := by
  

Proof state:
K : Type u_1
inst✝¹ : DivisionRing K
inst✝ : CharZero K
a : ℕ
⊢ ↑(choose a 2) = ↑a * (↑a - 1) / 2

Next tactic:
rw [← cast_descFactorial_two, descFactorial_eq_factorial_mul_choose, factorial_two, mul_comm,
    cast_mul, cast_two, eq_div_iff_mul_eq (two_ne_zero : (2 : K) ≠ 0)]
@[simp]
theorem cardQuot_apply (S : Submodule R M) [h : Fintype (M ⧸ S)] :
    cardQuot S = Fintype.card (M ⧸ S) := by
  -- Porting note: original proof was AddSubgroup.index_eq_card _
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
S : Submodule R M
h : Fintype (M ⧸ S)
⊢ cardQuot S = Fintype.card (M ⧸ S)

Next tactic:
suffices Fintype (M ⧸ S.toAddSubgroup) by convert AddSubgroup.index_eq_card S.toAddSubgroup
@[simp]
theorem cardQuot_apply (S : Submodule R M) [h : Fintype (M ⧸ S)] :
    cardQuot S = Fintype.card (M ⧸ S) := by
  -- Porting note: original proof was AddSubgroup.index_eq_card _
  suffices Fintype (M ⧸ S.toAddSubgroup) by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
S : Submodule R M
h : Fintype (M ⧸ S)
this : Fintype (M ⧸ toAddSubgroup S)
⊢ cardQuot S = Fintype.card (M ⧸ S)

Next tactic:
convert AddSubgroup.index_eq_card S.toAddSubgroup
@[simp]
theorem cardQuot_apply (S : Submodule R M) [h : Fintype (M ⧸ S)] :
    cardQuot S = Fintype.card (M ⧸ S) := by
  -- Porting note: original proof was AddSubgroup.index_eq_card _
  suffices Fintype (M ⧸ S.toAddSubgroup) by convert AddSubgroup.index_eq_card S.toAddSubgroup
  

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
S : Submodule R M
h : Fintype (M ⧸ S)
⊢ Fintype (M ⧸ toAddSubgroup S)

Next tactic:
convert h
@[simp]
theorem cardQuot_eq_one_iff {P : Submodule R M} : cardQuot P = 1 ↔ P = ⊤ :=
  AddSubgroup.index_eq_one.trans (by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Ring R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
P : Submodule R M
⊢ toAddSubgroup P = ⊤ ↔ P = ⊤

Next tactic:
simp [SetLike.ext_iff]
/-- Multiplicity of the ideal norm, for coprime ideals.
This is essentially just a repackaging of the Chinese Remainder Theorem.
-/
theorem cardQuot_mul_of_coprime [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S]
    {I J : Ideal S} (coprime : IsCoprime I J) : cardQuot (I * J) = cardQuot I * cardQuot J := by
  

Proof state:
S : Type u_1
inst✝⁴ : CommRing S
inst✝³ : IsDomain S
inst✝² : IsDedekindDomain S
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I J : Ideal S
coprime : IsCoprime I J
⊢ cardQuot (I * J) = cardQuot I * cardQuot J

Next tactic:
let b := Module.Free.chooseBasis ℤ S
/-- Multiplicity of the ideal norm, for coprime ideals.
This is essentially just a repackaging of the Chinese Remainder Theorem.
-/
theorem cardQuot_mul_of_coprime [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S]
    {I J : Ideal S} (coprime : IsCoprime I J) : cardQuot (I * J) = cardQuot I * cardQuot J := by
  let b := Module.Free.chooseBasis ℤ S
  

Proof state:
S : Type u_1
inst✝⁴ : CommRing S
inst✝³ : IsDomain S
inst✝² : IsDedekindDomain S
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I J : Ideal S
coprime : IsCoprime I J
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
⊢ cardQuot (I * J) = cardQuot I * cardQuot J

Next tactic:
cases isEmpty_or_nonempty (Module.Free.ChooseBasisIndex ℤ S)
/-- Multiplicity of the ideal norm, for coprime ideals.
This is essentially just a repackaging of the Chinese Remainder Theorem.
-/
theorem cardQuot_mul_of_coprime [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S]
    {I J : Ideal S} (coprime : IsCoprime I J) : cardQuot (I * J) = cardQuot I * cardQuot J := by
  let b := Module.Free.chooseBasis ℤ S
  cases isEmpty_or_nonempty (Module.Free.ChooseBasisIndex ℤ S)
  · 

Proof state:
case inl
S : Type u_1
inst✝⁴ : CommRing S
inst✝³ : IsDomain S
inst✝² : IsDedekindDomain S
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I J : Ideal S
coprime : IsCoprime I J
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
h✝ : IsEmpty (Module.Free.ChooseBasisIndex ℤ S)
⊢ cardQuot (I * J) = cardQuot I * cardQuot J

Next tactic:
haveI : Subsingleton S := Function.Surjective.subsingleton b.repr.toEquiv.symm.surjective
/-- Multiplicity of the ideal norm, for coprime ideals.
This is essentially just a repackaging of the Chinese Remainder Theorem.
-/
theorem cardQuot_mul_of_coprime [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S]
    {I J : Ideal S} (coprime : IsCoprime I J) : cardQuot (I * J) = cardQuot I * cardQuot J := by
  let b := Module.Free.chooseBasis ℤ S
  cases isEmpty_or_nonempty (Module.Free.ChooseBasisIndex ℤ S)
  · haveI : Subsingleton S := Function.Surjective.subsingleton b.repr.toEquiv.symm.surjective
    

Proof state:
case inl
S : Type u_1
inst✝⁴ : CommRing S
inst✝³ : IsDomain S
inst✝² : IsDedekindDomain S
inst✝¹ : Module.Free ℤ S
inst✝ : Module.Finite ℤ S
I J : Ideal S
coprime : IsCoprime I J
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
h✝ : IsEmpty (Module.Free.ChooseBasisIndex ℤ S)
this : Subsingleton S
⊢ cardQuot (I * J) = cardQuot I * cardQuot J

Next tactic:
nontriviality S
/-- Multiplicity of the ideal norm, for coprime ideals.
This is essentially just a repackaging of the Chinese Remainder Theorem.
-/
theorem cardQuot_mul_of_coprime [IsDedekindDomain S] [Module.Free ℤ S] [Module.Finite ℤ S]
    {I J : Ideal S} (coprime : IsCoprime I J) : cardQuot (I * J) = cardQuot I * cardQuot J := by
  let b := Module.Free.chooseBasis ℤ S
  cases isEmpty_or_nonempty (Module.Free.ChooseBasisIndex ℤ S)
  · haveI : Subsingleton S := Function.Surjective.subsingleton b.repr.toEquiv.symm.surjective
    nontriviality S
    

Proof state:
case inl
S : Type u_1
inst✝⁵ : CommRing S
inst✝⁴ : IsDomain S
inst✝³ : IsDedekindDomain S
inst✝² : Module.Free ℤ S
inst✝¹ : Module.Finite ℤ S
I J : Ideal S
coprime : IsCoprime I J
b : Basis (Module.Free.ChooseBasisIndex ℤ S) ℤ S := Module.Free.chooseBasis ℤ S
h✝ : IsEmpty (Module.Free.ChooseBasisIndex ℤ S)
this : Subsingleton S
inst✝ : Nontrivial S
⊢ cardQuot (I * J) = cardQuot I * cardQuot J

Next tactic:
exfalso