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 ∈ l, p.natDegree ≤ n
⊢ l.prod.coeff (l.length * n) = (List.map (fun p => p.coeff n) l).prod
state_after: case nil
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hl : ∀ p ∈ [], p.natDegree ≤ n
⊢ [].prod.coeff ([].length * n) = (List.map (fun p => p.coeff n) []).prod

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

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

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
⊢ (hd :: tl).prod.coeff ((hd :: tl).length * n) = (List.map (fun p => p.coeff n) (hd :: tl)).prod
state_after: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd :: tl).prod.coeff ((hd :: tl).length * n) = (List.map (fun p => p.coeff n) (hd :: tl)).prod

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd :: tl).prod.coeff ((hd :: tl).length * n) = (List.map (fun p => p.coeff n) (hd :: tl)).prod
state_after: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd * tl.prod).coeff ((tl.length + 1) * n) = hd.coeff n * (List.map (fun p => p.coeff n) tl).prod

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd * tl.prod).coeff ((tl.length + 1) * n) = hd.coeff n * (List.map (fun p => p.coeff n) tl).prod
state_after: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)
state_after: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)
state_after: case cons
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
hdn : hd.natDegree ≤ n
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
hdn : hd.natDegree ≤ n
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)
state_after: case cons.inl
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
⊢ (hd * tl.prod).coeff (hd.natDegree + hd.natDegree * tl.length) =
    hd.coeff hd.natDegree * tl.prod.coeff (hd.natDegree * tl.length)

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

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

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

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

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

tactic: rcases 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
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
⊢ (hd * tl.prod).coeff (hd.natDegree + hd.natDegree * tl.length) =
    hd.coeff hd.natDegree * tl.prod.coeff (hd.natDegree * tl.length)
state_after: case cons.inl.inl
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
h' : tl.prod.natDegree = hd.natDegree * tl.length
⊢ (hd * tl.prod).coeff (hd.natDegree + hd.natDegree * tl.length) =
    hd.coeff hd.natDegree * tl.prod.coeff (hd.natDegree * tl.length)

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

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
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
h' : tl.prod.natDegree = hd.natDegree * tl.length
⊢ (hd * tl.prod).coeff (hd.natDegree + hd.natDegree * tl.length) =
    hd.coeff hd.natDegree * tl.prod.coeff (hd.natDegree * tl.length)
state_after: no goals

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
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
h' : tl.prod.natDegree < hd.natDegree * tl.length
⊢ (hd * tl.prod).coeff (hd.natDegree + hd.natDegree * tl.length) =
    hd.coeff hd.natDegree * tl.prod.coeff (hd.natDegree * tl.length)
state_after: case cons.inl.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
h' : tl.prod.natDegree < hd.natDegree * tl.length
⊢ (hd * tl.prod).natDegree < hd.natDegree + hd.natDegree * tl.length

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
hd : S[X]
tl : List S[X]
IH :
  (∀ p ∈ tl, p.natDegree ≤ hd.natDegree) →
    tl.prod.coeff (tl.length * hd.natDegree) = (List.map (fun p => p.coeff hd.natDegree) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ hd.natDegree
hl' : ∀ p ∈ tl, p.natDegree ≤ hd.natDegree
h : tl.prod.natDegree ≤ hd.natDegree * tl.length
hdn : hd.natDegree ≤ hd.natDegree
h' : tl.prod.natDegree < hd.natDegree * tl.length
⊢ (hd * tl.prod).natDegree < hd.natDegree + hd.natDegree * tl.length
state_after: no goals

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
hdn : hd.natDegree ≤ n
hdn' : hd.natDegree < n
⊢ (hd * tl.prod).coeff (n + n * tl.length) = hd.coeff n * tl.prod.coeff (n * tl.length)
state_after: case cons.inr
R : Type u
ι : Type w
s : Finset ι
S : Type u_1
inst✝ : Semiring S
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
hdn : hd.natDegree ≤ n
hdn' : hd.natDegree < n
⊢ (hd * tl.prod).natDegree < n + n * tl.length

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
n : ℕ
hd : S[X]
tl : List S[X]
IH : (∀ p ∈ tl, p.natDegree ≤ n) → tl.prod.coeff (tl.length * n) = (List.map (fun p => p.coeff n) tl).prod
hl : ∀ p ∈ hd :: tl, p.natDegree ≤ n
hl' : ∀ p ∈ tl, p.natDegree ≤ n
h : tl.prod.natDegree ≤ n * tl.length
hdn : hd.natDegree ≤ n
hdn' : hd.natDegree < n
⊢ (hd * tl.prod).natDegree < n + n * tl.length
state_after: no goals