l3lab/ntp-mathlib huggingface dataset:
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
| prod (map (fun t => X - C t) s)

Next tactic:
congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
| prod (map (fun t => X - C t) s)

Next tactic:
congr
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    

Proof state:
case a
R : Type u_1
inst✝ : CommRing R
s : Multiset R
| map (fun t => X - C t) s

Next tactic:
congr
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    

Proof state:
case a.f
R : Type u_1
inst✝ : CommRing R
s : Multiset R
| fun t => X - C t
case a.s R : Type u_1 inst✝ : CommRing R s : Multiset R | s

Next tactic:
ext x
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    

Proof state:
case a.f.h
R : Type u_1
inst✝ : CommRing R
s : Multiset R
x : R
| X - C x
case a.s R : Type u_1 inst✝ : CommRing R s : Multiset R | s

Next tactic:
rw [sub_eq_add_neg]
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    

Proof state:
case a.f.h
R : Type u_1
inst✝ : CommRing R
s : Multiset R
x : R
| X + -C x
case a.s R : Type u_1 inst✝ : CommRing R s : Multiset R | s

Next tactic:
rw [← map_neg C x]
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
⊢ prod (map (fun x => X + C (-x)) s) = ∑ j in Finset.range (card s + 1), (-1) ^ j * (C (esymm s j) * X ^ (card s - j))

Next tactic:
convert prod_X_add_C_eq_sum_esymm (map (fun t => -t) s) using 1
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_eq_sum_esymm (map (fun t => -t) s) using 1
  · 

Proof state:
case h.e'_2
R : Type u_1
inst✝ : CommRing R
s : Multiset R
⊢ prod (map (fun x => X + C (-x)) s) = prod (map (fun r => X + C r) (map (fun t => -t) s))

Next tactic:
rw [map_map]
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_eq_sum_esymm (map (fun t => -t) s) using 1
  · rw [map_map]; 

Proof state:
case h.e'_2
R : Type u_1
inst✝ : CommRing R
s : Multiset R
⊢ prod (map (fun x => X + C (-x)) s) = prod (map ((fun r => X + C r) ∘ fun t => -t) s)

Next tactic:
rfl
theorem prod_X_sub_X_eq_sum_esymm (s : Multiset R) :
    (s.map fun t => X - C t).prod =
      ∑ j in Finset.range (Multiset.card s + 1),
        (-1) ^ j * (C (s.esymm j) * X ^ (Multiset.card s - j)) := by
  conv_lhs =>
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_eq_sum_esymm (map (fun t => -t) s) using 1
  · rw [map_map]; rfl
  · 

Proof state:
case h.e'_3
R : Type u_1
inst✝ : CommRing R
s : Multiset R
⊢ ∑ j in Finset.range (card s + 1), (-1) ^ j * (C (esymm s j) * X ^ (card s - j)) =
    ∑ j in Finset.range (card (map (fun t => -t) s) + 1),
      C (esymm (map (fun t => -t) s) j) * X ^ (card (map (fun t => -t) s) - j)

Next tactic:
simp only [esymm_neg, card_map, mul_assoc, map_mul, map_pow, map_neg, map_one]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ coeff (prod (map (fun t => X - C t) s)) k = (-1) ^ (card s - k) * esymm s (card s - k)

Next tactic:
conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| coeff (prod (map (fun t => X - C t) s)) k

Next tactic:
congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| coeff (prod (map (fun t => X - C t) s)) k

Next tactic:
congr
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    

Proof state:
case a
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| prod (map (fun t => X - C t) s)
case a R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s | k

Next tactic:
congr
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    

Proof state:
case a.a
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| map (fun t => X - C t) s
case a R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s | k

Next tactic:
congr
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    

Proof state:
case a.a.f
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| fun t => X - C t
case a.a.s
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| s
case a R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s | k

Next tactic:
ext x
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    

Proof state:
case a.a.f.h
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
x : R
| X - C x
case a.a.s
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| s
case a R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s | k

Next tactic:
rw [sub_eq_add_neg]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    

Proof state:
case a.a.f.h
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
x : R
| X + -C x
case a.a.s
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
| s
case a R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s | k

Next tactic:
rw [← map_neg C x]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ coeff (prod (map (fun x => X + C (-x)) s)) k = (-1) ^ (card s - k) * esymm s (card s - k)

Next tactic:
convert prod_X_add_C_coeff (map (fun t => -t) s) _ using 1
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_coeff (map (fun t => -t) s) _ using 1
  · 

Proof state:
case h.e'_2
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ coeff (prod (map (fun x => X + C (-x)) s)) k = coeff (prod (map (fun r => X + C r) (map (fun t => -t) s))) ?convert_1

Next tactic:
rw [map_map]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_coeff (map (fun t => -t) s) _ using 1
  · rw [map_map]; 

Proof state:
case h.e'_2
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ coeff (prod (map (fun x => X + C (-x)) s)) k = coeff (prod (map ((fun r => X + C r) ∘ fun t => -t) s)) ?convert_1
case convert_1 R : Type u_1 inst✝ : CommRing R s : Multiset R k : ℕ h : k ≤ card s ⊢ ℕ

Next tactic:
rfl
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_coeff (map (fun t => -t) s) _ using 1
  · rw [map_map]; rfl
  · 

Proof state:
case h.e'_3
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ (-1) ^ (card s - k) * esymm s (card s - k) = esymm (map (fun t => -t) s) (card (map (fun t => -t) s) - k)

Next tactic:
rw [esymm_neg, card_map]
theorem prod_X_sub_C_coeff (s : Multiset R) {k : ℕ} (h : k ≤ Multiset.card s) :
    (s.map fun t => X - C t).prod.coeff k =
    (-1) ^ (Multiset.card s - k) * s.esymm (Multiset.card s - k) := by
  conv_lhs =>
    congr
    congr
    congr
    ext x
    rw [sub_eq_add_neg]
    rw [← map_neg C x]
  convert prod_X_add_C_coeff (map (fun t => -t) s) _ using 1
  · rw [map_map]; rfl
  · rw [esymm_neg, card_map]
  · 

Proof state:
case convert_2
R : Type u_1
inst✝ : CommRing R
s : Multiset R
k : ℕ
h : k ≤ card s
⊢ k ≤ card (map (fun t => -t) s)

Next tactic:
rwa [card_map]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ coeff p k = leadingCoeff p * (-1) ^ (natDegree p - k) * esymm (roots p) (natDegree p - k)

Next tactic:
conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
| coeff p k

Next tactic:
rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ coeff (C (leadingCoeff p) * prod (map (fun a => X - C a) (roots p))) k =
    leadingCoeff p * (-1) ^ (natDegree p - k) * esymm (roots p) (natDegree p - k)

Next tactic:
rw [coeff_C_mul, mul_assoc]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ leadingCoeff p * coeff (prod (map (fun a => X - C a) (roots p))) k =
    leadingCoeff p * ((-1) ^ (natDegree p - k) * esymm (roots p) (natDegree p - k))

Next tactic:
congr
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  

Proof state:
case e_a
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ coeff (prod (map (fun a => X - C a) (roots p))) k = (-1) ^ (natDegree p - k) * esymm (roots p) (natDegree p - k)

Next tactic:
have : k ≤ card (roots p) := by rw [hroots]; exact h
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  have : k ≤ card (roots p) := by 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ k ≤ card (roots p)

Next tactic:
rw [hroots]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  have : k ≤ card (roots p) := by rw [hroots]; 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
⊢ k ≤ natDegree p

Next tactic:
exact h
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  have : k ≤ card (roots p) := by rw [hroots]; exact h
  

Proof state:
case e_a
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
this : k ≤ card (roots p)
⊢ coeff (prod (map (fun a => X - C a) (roots p))) k = (-1) ^ (natDegree p - k) * esymm (roots p) (natDegree p - k)

Next tactic:
convert p.roots.prod_X_sub_C_coeff this using 3
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  have : k ≤ card (roots p) := by rw [hroots]; exact h
  convert p.roots.prod_X_sub_C_coeff this using 3 <;> 

Proof state:
case h.e'_3.h.e'_5.h.e'_6
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
this : k ≤ card (roots p)
⊢ natDegree p - k = card (roots p) - k

Next tactic:
rw [hroots]
/-- Vieta's formula for the coefficients and the roots of a polynomial over an integral domain
  with as many roots as its degree. -/
theorem _root_.Polynomial.coeff_eq_esymm_roots_of_card [IsDomain R] {p : R[X]}
    (hroots : Multiset.card p.roots = p.natDegree) {k : ℕ} (h : k ≤ p.natDegree) :
    p.coeff k = p.leadingCoeff * (-1) ^ (p.natDegree - k) * p.roots.esymm (p.natDegree - k) := by
  conv_lhs => rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C hroots]
  rw [coeff_C_mul, mul_assoc]; congr
  have : k ≤ card (roots p) := by rw [hroots]; exact h
  convert p.roots.prod_X_sub_C_coeff this using 3 <;> 

Proof state:
case h.e'_3.h.e'_6.h.e'_4
R : Type u_1
inst✝¹ : CommRing R
inst✝ : IsDomain R
p : R[X]
hroots : card (roots p) = natDegree p
k : ℕ
h : k ≤ natDegree p
this : k ≤ card (roots p)
⊢ natDegree p - k = card (roots p) - k

Next tactic:
rw [hroots]
/-- A sum version of Vieta's formula for `MvPolynomial`: viewing `X i` as variables,
the product of linear terms `λ + X i` is equal to a linear combination of
the symmetric polynomials `esymm σ R j`. -/
theorem MvPolynomial.prod_C_add_X_eq_sum_esymm :
    (∏ i : σ, (Polynomial.X + Polynomial.C (MvPolynomial.X i))) =
      ∑ j in range (card σ + 1), Polynomial.C
        (MvPolynomial.esymm σ R j) * Polynomial.X ^ (card σ - j) := by
  

Proof state:
R : Type u_1
σ : Type u_2
inst✝¹ : CommSemiring R
inst✝ : Fintype σ
⊢ ∏ i : σ, (Polynomial.X + Polynomial.C (X i)) =
    ∑ j in range (Fintype.card σ + 1), Polynomial.C (esymm σ R j) * Polynomial.X ^ (Fintype.card σ - j)

Next tactic:
let s := Finset.univ.val.map fun i : σ => (MvPolynomial.X i : MvPolynomial σ R)
/-- A sum version of Vieta's formula for `MvPolynomial`: viewing `X i` as variables,
the product of linear terms `λ + X i` is equal to a linear combination of
the symmetric polynomials `esymm σ R j`. -/
theorem MvPolynomial.prod_C_add_X_eq_sum_esymm :
    (∏ i : σ, (Polynomial.X + Polynomial.C (MvPolynomial.X i))) =
      ∑ j in range (card σ + 1), Polynomial.C
        (MvPolynomial.esymm σ R j) * Polynomial.X ^ (card σ - j) := by
  let s := Finset.univ.val.map fun i : σ => (MvPolynomial.X i : MvPolynomial σ R)
  

Proof state:
R : Type u_1
σ : Type u_2
inst✝¹ : CommSemiring R
inst✝ : Fintype σ
s : Multiset (MvPolynomial σ R) := Multiset.map (fun i => X i) univ.val
⊢ ∏ i : σ, (Polynomial.X + Polynomial.C (X i)) =
    ∑ j in range (Fintype.card σ + 1), Polynomial.C (esymm σ R j) * Polynomial.X ^ (Fintype.card σ - j)

Next tactic:
have : Fintype.card σ = Multiset.card s := by
    rw [Multiset.card_map, ← Finset.card_univ, Finset.card_def]
/-- A sum version of Vieta's formula for `MvPolynomial`: viewing `X i` as variables,
the product of linear terms `λ + X i` is equal to a linear combination of
the symmetric polynomials `esymm σ R j`. -/
theorem MvPolynomial.prod_C_add_X_eq_sum_esymm :
    (∏ i : σ, (Polynomial.X + Polynomial.C (MvPolynomial.X i))) =
      ∑ j in range (card σ + 1), Polynomial.C
        (MvPolynomial.esymm σ R j) * Polynomial.X ^ (card σ - j) := by
  let s := Finset.univ.val.map fun i : σ => (MvPolynomial.X i : MvPolynomial σ R)
  have : Fintype.card σ = Multiset.card s := by
    

Proof state:
R : Type u_1
σ : Type u_2
inst✝¹ : CommSemiring R
inst✝ : Fintype σ
s : Multiset (MvPolynomial σ R) := Multiset.map (fun i => X i) univ.val
⊢ Fintype.card σ = Multiset.card s

Next tactic:
rw [Multiset.card_map, ← Finset.card_univ, Finset.card_def]
/-- A sum version of Vieta's formula for `MvPolynomial`: viewing `X i` as variables,
the product of linear terms `λ + X i` is equal to a linear combination of
the symmetric polynomials `esymm σ R j`. -/
theorem MvPolynomial.prod_C_add_X_eq_sum_esymm :
    (∏ i : σ, (Polynomial.X + Polynomial.C (MvPolynomial.X i))) =
      ∑ j in range (card σ + 1), Polynomial.C
        (MvPolynomial.esymm σ R j) * Polynomial.X ^ (card σ - j) := by
  let s := Finset.univ.val.map fun i : σ => (MvPolynomial.X i : MvPolynomial σ R)
  have : Fintype.card σ = Multiset.card s := by
    rw [Multiset.card_map, ← Finset.card_univ, Finset.card_def]
  

Proof state:
R : Type u_1
σ : Type u_2
inst✝¹ : CommSemiring R
inst✝ : Fintype σ
s : Multiset (MvPolynomial σ R) := Multiset.map (fun i => X i) univ.val
this : Fintype.card σ = Multiset.card s
⊢ ∏ i : σ, (Polynomial.X + Polynomial.C (X i)) =
    ∑ j in range (Fintype.card σ + 1), Polynomial.C (esymm σ R j) * Polynomial.X ^ (Fintype.card σ - j)

Next tactic:
simp_rw [this, MvPolynomial.esymm_eq_multiset_esymm σ R, Finset.prod_eq_multiset_prod]