l3lab/ntp-mathlib huggingface dataset:
theorem coeff_prod_of_natDegree_le (f : ι → R[X]) (n : ℕ) (h : ∀ p ∈ s, natDegree (f p) ≤ n) :
    coeff (∏ i in s, f i) (s.card * n) = ∏ i in s, coeff (f i) n := by
  cases' s with l hl
  convert coeff_multiset_prod_of_natDegree_le (l.map f) n ?_
  · simp
  · 

Proof state:
case h.e'_3
R : Type u
ι : Type w
inst✝ : CommSemiring R
f✝ : ι → R[X]
t : Multiset R[X]
f : ι → R[X]
n : ℕ
l : Multiset ι
hl : Nodup l
h : ∀ p ∈ { val := l, nodup := hl }, natDegree (f p) ≤ n
⊢ ∏ i in { val := l, nodup := hl }, coeff (f i) n = prod (Multiset.map (fun p => coeff p n) (Multiset.map f l))

Next tactic:
simp
theorem coeff_prod_of_natDegree_le (f : ι → R[X]) (n : ℕ) (h : ∀ p ∈ s, natDegree (f p) ≤ n) :
    coeff (∏ i in s, f i) (s.card * n) = ∏ i in s, coeff (f i) n := by
  cases' s with l hl
  convert coeff_multiset_prod_of_natDegree_le (l.map f) n ?_
  · simp
  · simp
  · 

Proof state:
case mk
R : Type u
ι : Type w
inst✝ : CommSemiring R
f✝ : ι → R[X]
t : Multiset R[X]
f : ι → R[X]
n : ℕ
l : Multiset ι
hl : Nodup l
h : ∀ p ∈ { val := l, nodup := hl }, natDegree (f p) ≤ n
⊢ ∀ p ∈ Multiset.map f l, natDegree p ≤ n

Next tactic:
simpa using h
theorem coeff_zero_multiset_prod : t.prod.coeff 0 = (t.map fun f => coeff f 0).prod := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommSemiring R
f : ι → R[X]
t : Multiset R[X]
⊢ coeff (prod t) 0 = prod (Multiset.map (fun f => coeff f 0) t)

Next tactic:
refine' Multiset.induction_on t _ fun a t ht => _
theorem coeff_zero_multiset_prod : t.prod.coeff 0 = (t.map fun f => coeff f 0).prod := by
  refine' Multiset.induction_on t _ fun a t ht => _; · 

Proof state:
case refine'_1
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommSemiring R
f : ι → R[X]
t : Multiset R[X]
⊢ coeff (prod 0) 0 = prod (Multiset.map (fun f => coeff f 0) 0)

Next tactic:
simp
theorem coeff_zero_multiset_prod : t.prod.coeff 0 = (t.map fun f => coeff f 0).prod := by
  refine' Multiset.induction_on t _ fun a t ht => _; · simp
  

Proof state:
case refine'_2
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommSemiring R
f : ι → R[X]
t✝ : Multiset R[X]
a : R[X]
t : Multiset R[X]
ht : coeff (prod t) 0 = prod (Multiset.map (fun f => coeff f 0) t)
⊢ coeff (prod (a ::ₘ t)) 0 = prod (Multiset.map (fun f => coeff f 0) (a ::ₘ t))

Next tactic:
rw [Multiset.prod_cons, Multiset.map_cons, Multiset.prod_cons, Polynomial.mul_coeff_zero, ht]
theorem coeff_zero_prod : (∏ i in s, f i).coeff 0 = ∏ i in s, (f i).coeff 0 := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommSemiring R
f : ι → R[X]
t : Multiset R[X]
⊢ coeff (∏ i in s, f i) 0 = ∏ i in s, coeff (f i) 0

Next tactic:
simpa using coeff_zero_multiset_prod (s.1.map f)
theorem multiset_prod_X_sub_C_nextCoeff (t : Multiset R) :
    nextCoeff (t.map fun x => X - C x).prod = -t.sum := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
⊢ nextCoeff (prod (Multiset.map (fun x => X - C x) t)) = -Multiset.sum t

Next tactic:
rw [nextCoeff_multiset_prod]
theorem multiset_prod_X_sub_C_nextCoeff (t : Multiset R) :
    nextCoeff (t.map fun x => X - C x).prod = -t.sum := by
  rw [nextCoeff_multiset_prod]
  · 

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
⊢ Multiset.sum (Multiset.map (fun i => nextCoeff (X - C i)) t) = -Multiset.sum t

Next tactic:
simp only [nextCoeff_X_sub_C]
theorem multiset_prod_X_sub_C_nextCoeff (t : Multiset R) :
    nextCoeff (t.map fun x => X - C x).prod = -t.sum := by
  rw [nextCoeff_multiset_prod]
  · simp only [nextCoeff_X_sub_C]
    

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
⊢ Multiset.sum (Multiset.map (fun x => -x) t) = -Multiset.sum t

Next tactic:
exact t.sum_hom (-AddMonoidHom.id R)
theorem multiset_prod_X_sub_C_nextCoeff (t : Multiset R) :
    nextCoeff (t.map fun x => X - C x).prod = -t.sum := by
  rw [nextCoeff_multiset_prod]
  · simp only [nextCoeff_X_sub_C]
    exact t.sum_hom (-AddMonoidHom.id R)
  · 

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
⊢ ∀ i ∈ t, Monic (X - C i)

Next tactic:
intros
theorem multiset_prod_X_sub_C_nextCoeff (t : Multiset R) :
    nextCoeff (t.map fun x => X - C x).prod = -t.sum := by
  rw [nextCoeff_multiset_prod]
  · simp only [nextCoeff_X_sub_C]
    exact t.sum_hom (-AddMonoidHom.id R)
  · intros
    

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
i✝ : R
a✝ : i✝ ∈ t
⊢ Monic (X - C i✝)

Next tactic:
apply monic_X_sub_C
theorem prod_X_sub_C_nextCoeff {s : Finset ι} (f : ι → R) :
    nextCoeff (∏ i in s, (X - C (f i))) = -∑ i in s, f i := by
  

Proof state:
R : Type u
ι : Type w
s✝ : Finset ι
inst✝ : CommRing R
s : Finset ι
f : ι → R
⊢ nextCoeff (∏ i in s, (X - C (f i))) = -∑ i in s, f i

Next tactic:
simpa using multiset_prod_X_sub_C_nextCoeff (s.1.map f)
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = -Multiset.sum t

Next tactic:
nontriviality R
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = -Multiset.sum t

Next tactic:
convert multiset_prod_X_sub_C_nextCoeff (by assumption)
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by 

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
⊢ Multiset ?m.972330

Next tactic:
assumption
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  

Proof state:
case h.e'_2
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) =
    nextCoeff (prod (Multiset.map (fun x => X - C x) t))

Next tactic:
rw [nextCoeff]
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; 

Proof state:
case h.e'_2
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) =
    if natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0 then 0
    else coeff (prod (Multiset.map (fun x => X - C x) t)) (natDegree (prod (Multiset.map (fun x => X - C x) t)) - 1)

Next tactic:
split_ifs with h
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · 

Proof state:
case pos
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = 0

Next tactic:
rw [natDegree_multiset_prod_of_monic] at h
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    

Proof state:
case pos
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : Multiset.sum (Multiset.map natDegree (Multiset.map (fun x => X - C x) t)) = 0
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = 0
case pos.h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ ∀ f ∈ Multiset.map (fun x => X - C x) t, Monic f

Next tactic:
swap
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · 

Proof state:
case pos.h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ ∀ f ∈ Multiset.map (fun x => X - C x) t, Monic f

Next tactic:
simp only [Multiset.mem_map]
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      

Proof state:
case pos.h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ ∀ (f : R[X]), (∃ a ∈ t, X - C a = f) → Monic f

Next tactic:
rintro _ ⟨_, _, rfl⟩
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      

Proof state:
case pos.h.intro.intro
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
w✝ : R
left✝ : w✝ ∈ t
⊢ Monic (X - C w✝)

Next tactic:
apply monic_X_sub_C
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    

Proof state:
case pos
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : Multiset.sum (Multiset.map natDegree (Multiset.map (fun x => X - C x) t)) = 0
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = 0

Next tactic:
simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    

Proof state:
case pos
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : ∀ (x : ℕ), (∃ a, (∃ a_1 ∈ t, X - C a_1 = a) ∧ natDegree a = x) → x = 0
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) = 0

Next tactic:
contrapose! h
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    

Proof state:
case pos
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) ≠ 0
⊢ ∃ x, (∃ a, (∃ a_1 ∈ t, X - C a_1 = a) ∧ natDegree a = x) ∧ x ≠ 0

Next tactic:
obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
    

Proof state:
case pos.intro
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) ≠ 0
x : R
hx : x ∈ t
⊢ ∃ x, (∃ a, (∃ a_1 ∈ t, X - C a_1 = a) ∧ natDegree a = x) ∧ x ≠ 0

Next tactic:
exact ⟨_, ⟨_, ⟨x, hx, rfl⟩, natDegree_X_sub_C _⟩, one_ne_zero⟩
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
    exact ⟨_, ⟨_, ⟨x, hx, rfl⟩, natDegree_X_sub_C _⟩, one_ne_zero⟩
  

Proof state:
case neg
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : ¬natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ coeff (prod (Multiset.map (fun x => X - C x) t)) (Multiset.card t - 1) =
    coeff (prod (Multiset.map (fun x => X - C x) t)) (natDegree (prod (Multiset.map (fun x => X - C x) t)) - 1)

Next tactic:
congr
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
    exact ⟨_, ⟨_, ⟨x, hx, rfl⟩, natDegree_X_sub_C _⟩, one_ne_zero⟩
  congr; 

Proof state:
case neg.e_a.e_a
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : ¬natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ Multiset.card t = natDegree (prod (Multiset.map (fun x => X - C x) t))

Next tactic:
rw [natDegree_multiset_prod_of_monic]
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
    exact ⟨_, ⟨_, ⟨x, hx, rfl⟩, natDegree_X_sub_C _⟩, one_ne_zero⟩
  congr; rw [natDegree_multiset_prod_of_monic] <;> · 

Proof state:
case neg.e_a.e_a
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : ¬natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ Multiset.card t = Multiset.sum (Multiset.map natDegree (Multiset.map (fun x => X - C x) t))

Next tactic:
simp [natDegree_X_sub_C, monic_X_sub_C]
theorem multiset_prod_X_sub_C_coeff_card_pred (t : Multiset R) (ht : 0 < Multiset.card t) :
    (t.map fun x => X - C x).prod.coeff ((Multiset.card t) - 1) = -t.sum := by
  nontriviality R
  convert multiset_prod_X_sub_C_nextCoeff (by assumption)
  rw [nextCoeff]; split_ifs with h
  · rw [natDegree_multiset_prod_of_monic] at h
    swap
    · simp only [Multiset.mem_map]
      rintro _ ⟨_, _, rfl⟩
      apply monic_X_sub_C
    simp_rw [Multiset.sum_eq_zero_iff, Multiset.mem_map] at h
    contrapose! h
    obtain ⟨x, hx⟩ := card_pos_iff_exists_mem.mp ht
    exact ⟨_, ⟨_, ⟨x, hx, rfl⟩, natDegree_X_sub_C _⟩, one_ne_zero⟩
  congr; rw [natDegree_multiset_prod_of_monic] <;> · 

Proof state:
case neg.e_a.e_a.h
R : Type u
ι : Type w
s : Finset ι
inst✝ : CommRing R
t : Multiset R
ht : 0 < Multiset.card t
✝ : Nontrivial R
h : ¬natDegree (prod (Multiset.map (fun x => X - C x) t)) = 0
⊢ ∀ f ∈ Multiset.map (fun x => X - C x) t, Monic f

Next tactic:
simp [natDegree_X_sub_C, monic_X_sub_C]
theorem prod_X_sub_C_coeff_card_pred (s : Finset ι) (f : ι → R) (hs : 0 < s.card) :
    (∏ i in s, (X - C (f i))).coeff (s.card - 1) = -∑ i in s, f i := by
  

Proof state:
R : Type u
ι : Type w
s✝ : Finset ι
inst✝ : CommRing R
s : Finset ι
f : ι → R
hs : 0 < Finset.card s
⊢ coeff (∏ i in s, (X - C (f i))) (Finset.card s - 1) = -∑ i in s, f i

Next tactic:
simpa using multiset_prod_X_sub_C_coeff_card_pred (s.1.map f) (by simpa using hs)
theorem prod_X_sub_C_coeff_card_pred (s : Finset ι) (f : ι → R) (hs : 0 < s.card) :
    (∏ i in s, (X - C (f i))).coeff (s.card - 1) = -∑ i in s, f i := by
  simpa using multiset_prod_X_sub_C_coeff_card_pred (s.1.map f) (by 

Proof state:
R : Type u
ι : Type w
s✝ : Finset ι
inst✝ : CommRing R
s : Finset ι
f : ι → R
hs : 0 < Finset.card s
⊢ 0 < Multiset.card (Multiset.map f s.val)

Next tactic:
simpa using hs
/-- The degree of a product of polynomials is equal to
the sum of the degrees.

See `Polynomial.natDegree_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem natDegree_prod (h : ∀ i ∈ s, f i ≠ 0) :
    (∏ i in s, f i).natDegree = ∑ i in s, (f i).natDegree := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : ∀ i ∈ s, f i ≠ 0
⊢ natDegree (∏ i in s, f i) = ∑ i in s, natDegree (f i)

Next tactic:
nontriviality R
/-- The degree of a product of polynomials is equal to
the sum of the degrees.

See `Polynomial.natDegree_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem natDegree_prod (h : ∀ i ∈ s, f i ≠ 0) :
    (∏ i in s, f i).natDegree = ∑ i in s, (f i).natDegree := by
  nontriviality R
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : ∀ i ∈ s, f i ≠ 0
✝ : Nontrivial R
⊢ natDegree (∏ i in s, f i) = ∑ i in s, natDegree (f i)

Next tactic:
apply natDegree_prod'
/-- The degree of a product of polynomials is equal to
the sum of the degrees.

See `Polynomial.natDegree_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem natDegree_prod (h : ∀ i ∈ s, f i ≠ 0) :
    (∏ i in s, f i).natDegree = ∑ i in s, (f i).natDegree := by
  nontriviality R
  apply natDegree_prod'
  

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : ∀ i ∈ s, f i ≠ 0
✝ : Nontrivial R
⊢ ∏ i in s, leadingCoeff (f i) ≠ 0

Next tactic:
rw [prod_ne_zero_iff]
/-- The degree of a product of polynomials is equal to
the sum of the degrees.

See `Polynomial.natDegree_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem natDegree_prod (h : ∀ i ∈ s, f i ≠ 0) :
    (∏ i in s, f i).natDegree = ∑ i in s, (f i).natDegree := by
  nontriviality R
  apply natDegree_prod'
  rw [prod_ne_zero_iff]
  

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : ∀ i ∈ s, f i ≠ 0
✝ : Nontrivial R
⊢ ∀ a ∈ s, leadingCoeff (f a) ≠ 0

Next tactic:
intro x hx
/-- The degree of a product of polynomials is equal to
the sum of the degrees.

See `Polynomial.natDegree_prod'` (with a `'`) for a version for commutative semirings,
where additionally, the product of the leading coefficients must be nonzero.
-/
theorem natDegree_prod (h : ∀ i ∈ s, f i ≠ 0) :
    (∏ i in s, f i).natDegree = ∑ i in s, (f i).natDegree := by
  nontriviality R
  apply natDegree_prod'
  rw [prod_ne_zero_iff]
  intro x hx; 

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : ∀ i ∈ s, f i ≠ 0
✝ : Nontrivial R
x : ι
hx : x ∈ s
⊢ leadingCoeff (f x) ≠ 0

Next tactic:
simp [h x hx]
theorem natDegree_multiset_prod (h : (0 : R[X]) ∉ t) :
    natDegree t.prod = (t.map natDegree).sum := by
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : 0 ∉ t
⊢ natDegree (prod t) = Multiset.sum (Multiset.map natDegree t)

Next tactic:
nontriviality R
theorem natDegree_multiset_prod (h : (0 : R[X]) ∉ t) :
    natDegree t.prod = (t.map natDegree).sum := by
  nontriviality R
  

Proof state:
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : 0 ∉ t
✝ : Nontrivial R
⊢ natDegree (prod t) = Multiset.sum (Multiset.map natDegree t)

Next tactic:
rw [natDegree_multiset_prod']
theorem natDegree_multiset_prod (h : (0 : R[X]) ∉ t) :
    natDegree t.prod = (t.map natDegree).sum := by
  nontriviality R
  rw [natDegree_multiset_prod']
  

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : 0 ∉ t
✝ : Nontrivial R
⊢ prod (Multiset.map (fun f => leadingCoeff f) t) ≠ 0

Next tactic:
simp_rw [Ne.def, Multiset.prod_eq_zero_iff, Multiset.mem_map, leadingCoeff_eq_zero]
theorem natDegree_multiset_prod (h : (0 : R[X]) ∉ t) :
    natDegree t.prod = (t.map natDegree).sum := by
  nontriviality R
  rw [natDegree_multiset_prod']
  simp_rw [Ne.def, Multiset.prod_eq_zero_iff, Multiset.mem_map, leadingCoeff_eq_zero]
  

Proof state:
case h
R : Type u
ι : Type w
s : Finset ι
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
f : ι → R[X]
t : Multiset R[X]
h : 0 ∉ t
✝ : Nontrivial R
⊢ ¬∃ a ∈ t, a = 0

Next tactic:
rintro ⟨_, h, rfl⟩