Theorem: Polynomial.coeff_list_prod_of_natDegree_le
File: Mathlib/Algebra/Polynomial/BigOperators.lean

tactic: induction' l with hd tl IH
state_before: R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
⊢ coeff (List.prod l) (List.length l * n) = List.prod (List.map (fun p => coeff p n) l)

tactic: simp
state_before: case nil
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hl : ∀ (p : S[X]), p ∈ [] → natDegree p ≤ n
⊢ coeff (List.prod []) (List.length [] * n) = List.prod (List.map (fun p => coeff p n) [])

tactic: have hl' : ∀ p ∈ tl, natDegree p ≤ n := fun p hp => hl p (List.mem_cons_of_mem _ hp)
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
⊢ coeff (List.prod (hd :: tl)) (List.length (hd :: tl) * n) = List.prod (List.map (fun p => coeff p n) (hd :: tl))

tactic: simp only [List.prod_cons, List.map, List.length]
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ coeff (List.prod (hd :: tl)) (List.length (hd :: tl) * n) = List.prod (List.map (fun p => coeff p n) (hd :: tl))

tactic: rw [add_mul, one_mul, add_comm, ← IH hl', mul_comm tl.length]
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ coeff (hd * List.prod tl) ((List.length tl + 1) * n) = coeff hd n * List.prod (List.map (fun p => coeff p n) tl)

tactic: have h : natDegree tl.prod ≤ n * tl.length := by
  refine' (natDegree_list_prod_le _).trans _
  rw [← tl.length_map natDegree, mul_comm]
  refine' List.sum_le_card_nsmul _ _ _
  simpa using hl'
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ coeff (hd * List.prod tl) (n + n * List.length tl) = coeff hd n * coeff (List.prod tl) (n * List.length tl)

tactic: have hdn : natDegree hd ≤ n := hl _ (List.mem_cons_self _ _)
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
h : natDegree (List.prod tl) ≤ n * List.length tl
⊢ coeff (hd * List.prod tl) (n + n * List.length tl) = coeff hd n * coeff (List.prod tl) (n * List.length tl)

tactic: rcases hdn.eq_or_lt with (rfl | hdn')
state_before: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
h : natDegree (List.prod tl) ≤ n * List.length tl
hdn : natDegree hd ≤ n
⊢ coeff (hd * List.prod tl) (n + n * List.length tl) = coeff hd n * coeff (List.prod tl) (n * List.length tl)

tactic: refine' (natDegree_list_prod_le _).trans _
state_before: R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ natDegree (List.prod tl) ≤ n * List.length tl

tactic: rw [← tl.length_map natDegree, mul_comm]
state_before: R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ List.sum (List.map natDegree tl) ≤ n * List.length tl

tactic: refine' List.sum_le_card_nsmul _ _ _
state_before: R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ List.sum (List.map natDegree tl) ≤ List.length (List.map natDegree tl) * n

tactic: simpa using hl'
state_before: R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
⊢ ∀ (x : ℕ), x ∈ List.map natDegree tl → x ≤ n

tactic: cases' h.eq_or_lt with h' h'
state_before: case cons.inl
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
hd : S[X]
tl : List S[X]
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ natDegree hd
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd) →
    coeff (List.prod tl) (List.length tl * natDegree hd) = List.prod (List.map (fun p => coeff p (natDegree hd)) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ natDegree hd
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd
h : natDegree (List.prod tl) ≤ natDegree hd * List.length tl
hdn : natDegree hd ≤ natDegree hd
⊢ coeff (hd * List.prod tl) (natDegree hd + natDegree hd * List.length tl) =
    coeff hd (natDegree hd) * coeff (List.prod tl) (natDegree hd * List.length tl)

tactic: rw [← h', coeff_mul_degree_add_degree, leadingCoeff, leadingCoeff]
state_before: case cons.inl.inl
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
hd : S[X]
tl : List S[X]
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ natDegree hd
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd) →
    coeff (List.prod tl) (List.length tl * natDegree hd) = List.prod (List.map (fun p => coeff p (natDegree hd)) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ natDegree hd
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd
h : natDegree (List.prod tl) ≤ natDegree hd * List.length tl
hdn : natDegree hd ≤ natDegree hd
h' : natDegree (List.prod tl) = natDegree hd * List.length tl
⊢ coeff (hd * List.prod tl) (natDegree hd + natDegree hd * List.length tl) =
    coeff hd (natDegree hd) * coeff (List.prod tl) (natDegree hd * List.length tl)

tactic: rw [coeff_eq_zero_of_natDegree_lt, coeff_eq_zero_of_natDegree_lt h', mul_zero]
state_before: case cons.inl.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
hd : S[X]
tl : List S[X]
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ natDegree hd
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd) →
    coeff (List.prod tl) (List.length tl * natDegree hd) = List.prod (List.map (fun p => coeff p (natDegree hd)) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ natDegree hd
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd
h : natDegree (List.prod tl) ≤ natDegree hd * List.length tl
hdn : natDegree hd ≤ natDegree hd
h' : natDegree (List.prod tl) < natDegree hd * List.length tl
⊢ coeff (hd * List.prod tl) (natDegree hd + natDegree hd * List.length tl) =
    coeff hd (natDegree hd) * coeff (List.prod tl) (natDegree hd * List.length tl)

tactic: exact natDegree_mul_le.trans_lt (add_lt_add_left h' _)
state_before: case cons.inl.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
hd : S[X]
tl : List S[X]
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ natDegree hd
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd) →
    coeff (List.prod tl) (List.length tl * natDegree hd) = List.prod (List.map (fun p => coeff p (natDegree hd)) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ natDegree hd
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ natDegree hd
h : natDegree (List.prod tl) ≤ natDegree hd * List.length tl
hdn : natDegree hd ≤ natDegree hd
h' : natDegree (List.prod tl) < natDegree hd * List.length tl
⊢ natDegree (hd * List.prod tl) < natDegree hd + natDegree hd * List.length tl

tactic: rw [coeff_eq_zero_of_natDegree_lt hdn', coeff_eq_zero_of_natDegree_lt, zero_mul]
state_before: case cons.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
h : natDegree (List.prod tl) ≤ n * List.length tl
hdn : natDegree hd ≤ n
hdn' : natDegree hd < n
⊢ coeff (hd * List.prod tl) (n + n * List.length tl) = coeff hd n * coeff (List.prod tl) (n * List.length tl)

tactic: exact natDegree_mul_le.trans_lt (add_lt_add_of_lt_of_le hdn' h)
state_before: case cons.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
l : List S[X]
n : ℕ
hl✝ : ∀ (p : S[X]), p ∈ l → natDegree p ≤ n
hd : S[X]
tl : List S[X]
IH :
  (∀ (p : S[X]), p ∈ tl → natDegree p ≤ n) →
    coeff (List.prod tl) (List.length tl * n) = List.prod (List.map (fun p => coeff p n) tl)
hl : ∀ (p : S[X]), p ∈ hd :: tl → natDegree p ≤ n
hl' : ∀ (p : S[X]), p ∈ tl → natDegree p ≤ n
h : natDegree (List.prod tl) ≤ n * List.length tl
hdn : natDegree hd ≤ n
hdn' : natDegree hd < n
⊢ natDegree (hd * List.prod tl) < n + n * List.length tl