File: Mathlib/Algebra/BigOperators/Group/List.lean

full_name: List.prod
code: /-- Product of a list.

`List.prod [a, b, c] = ((1 * a) * b) * c` -/
@[to_additive "Sum of a list.\n\n`List.sum [a, b, c] = ((0 + a) + b) + c`"]
def prod {α} [Mul α] [One α] : List α → α 
goal: List α → α

full_name: List.sum
code: /-- Product of a list.

`List.prod [a, b, c] = ((1 * a) * b) * c` -/
@[to_additive "Sum of a list.\n\n`List.sum [a, b, c] = ((0 + a) + b) + c`"]
def prod {α} [Mul α] [One α] : List α → α 
goal: List α → α

full_name: List.alternatingSum
code: /-- The alternating sum of a list. -/
def alternatingSum {G : Type*} [Zero G] [Add G] [Neg G] : List G → G
  
goal: List G → G

full_name: List.alternatingProd
code: /-- The alternating product of a list. -/
@[to_additive existing]
def alternatingProd {G : Type*} [One G] [Mul G] [Inv G] : List G → G
  
goal: List G → G

full_name: List.sum_nil
code: @[to_additive (attr := simp)]
theorem prod_nil : ([] : List M).prod = 1 
goal: [].sum = 0

full_name: List.prod_nil
code: @[to_additive (attr := simp)]
theorem prod_nil : ([] : List M).prod = 1 
goal: [].prod = 1

full_name: List.sum_singleton
code: @[to_additive]
theorem prod_singleton : [a].prod = a 
goal: [a].sum = a

full_name: List.prod_singleton
code: @[to_additive]
theorem prod_singleton : [a].prod = a 
goal: [a].prod = a

full_name: List.prod_one_cons
code: @[to_additive (attr := simp)]
theorem prod_one_cons : (1 :: l).prod = l.prod 
goal: (1 :: l).prod = l.prod

full_name: List.sum_zero_cons
code: @[to_additive (attr := simp)]
theorem prod_one_cons : (1 :: l).prod = l.prod 
goal: (0 :: l).sum = l.sum

full_name: List.prod_map_one
code: @[to_additive]
theorem prod_map_one {l : List ι} :
    (l.map fun _ => (1 : M)).prod = 1 
goal: (List.map (fun x => 1) l).prod = 1

full_name: List.sum_map_zero
code: @[to_additive]
theorem prod_map_one {l : List ι} :
    (l.map fun _ => (1 : M)).prod = 1 
goal: (List.map (fun x => 0) l).sum = 0

full_name: List.prod_cons
code: @[to_additive (attr := simp)]
theorem prod_cons : (a :: l).prod = a * l.prod 
goal: (a :: l).prod = a * l.prod

full_name: List.sum_cons
code: @[to_additive (attr := simp)]
theorem prod_cons : (a :: l).prod = a * l.prod 
goal: (a :: l).sum = a + l.sum

full_name: List.sum_induction
code: @[to_additive]
lemma prod_induction
    (p : M → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ l, p x) :
    p l.prod 
goal: p l.sum

full_name: List.prod_induction
code: @[to_additive]
lemma prod_induction
    (p : M → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ l, p x) :
    p l.prod 
goal: p l.prod

full_name: List.prod_append
code: @[to_additive (attr := simp)]
theorem prod_append : (l₁ ++ l₂).prod = l₁.prod * l₂.prod 
goal: (l₁ ++ l₂).prod = l₁.prod * l₂.prod

full_name: List.sum_append
code: @[to_additive (attr := simp)]
theorem prod_append : (l₁ ++ l₂).prod = l₁.prod * l₂.prod 
goal: (l₁ ++ l₂).sum = l₁.sum + l₂.sum

full_name: List.sum_concat
code: @[to_additive]
theorem prod_concat : (l.concat a).prod = l.prod * a 
goal: (l.concat a).sum = l.sum + a

full_name: List.prod_concat
code: @[to_additive]
theorem prod_concat : (l.concat a).prod = l.prod * a 
goal: (l.concat a).prod = l.prod * a

full_name: List.sum_join
code: @[to_additive (attr := simp)]
theorem prod_join {l : List (List M)} : l.join.prod = (l.map List.prod).prod 
goal: l.join.sum = (List.map List.sum l).sum

full_name: List.prod_join
code: @[to_additive (attr := simp)]
theorem prod_join {l : List (List M)} : l.join.prod = (l.map List.prod).prod 
goal: l.join.prod = (List.map List.prod l).prod

full_name: List.sum_eq_foldr
code: @[to_additive]
theorem prod_eq_foldr : ∀ {l : List M}, l.prod = foldr (· * ·) 1 l
  
goal: l.sum = List.foldr (fun x x_1 => x + x_1) 0 l

full_name: List.prod_eq_foldr
code: @[to_additive]
theorem prod_eq_foldr : ∀ {l : List M}, l.prod = foldr (· * ·) 1 l
  
goal: l.prod = List.foldr (fun x x_1 => x * x_1) 1 l

full_name: List.sum_replicate
code: @[to_additive (attr := simp)]
theorem prod_replicate (n : ℕ) (a : M) : (replicate n a).prod = a ^ n 
goal: (List.replicate n a).sum = n • a

full_name: List.prod_replicate
code: @[to_additive (attr := simp)]
theorem prod_replicate (n : ℕ) (a : M) : (replicate n a).prod = a ^ n 
goal: (List.replicate n a).prod = a ^ n

full_name: List.prod_eq_pow_card
code: @[to_additive sum_eq_card_nsmul]
theorem prod_eq_pow_card (l : List M) (m : M) (h : ∀ x ∈ l, x = m) : l.prod = m ^ l.length 
goal: l.prod = m ^ l.length

full_name: List.sum_eq_card_nsmul
code: @[to_additive sum_eq_card_nsmul]
theorem prod_eq_pow_card (l : List M) (m : M) (h : ∀ x ∈ l, x = m) : l.prod = m ^ l.length 
goal: l.sum = l.length • m

full_name: List.prod_hom_rel
code: @[to_additive]
theorem prod_hom_rel (l : List ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1)
    (h₂ : ∀ ⦃i a b⦄, r a b → r (f i * a) (g i * b)) : r (l.map f).prod (l.map g).prod 
goal: r (List.map f l).prod (List.map g l).prod

full_name: List.sum_hom_rel
code: @[to_additive]
theorem prod_hom_rel (l : List ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1)
    (h₂ : ∀ ⦃i a b⦄, r a b → r (f i * a) (g i * b)) : r (l.map f).prod (l.map g).prod 
goal: r (List.map f l).sum (List.map g l).sum

full_name: List.rel_sum
code: @[to_additive]
theorem rel_prod {R : M → N → Prop} (h : R 1 1) (hf : (R ⇒ R ⇒ R) (· * ·) (· * ·)) :
    (Forall₂ R ⇒ R) prod prod 
goal: (List.Forall₂ R ⇒ R) List.sum List.sum

full_name: List.rel_prod
code: @[to_additive]
theorem rel_prod {R : M → N → Prop} (h : R 1 1) (hf : (R ⇒ R ⇒ R) (· * ·) (· * ·)) :
    (Forall₂ R ⇒ R) prod prod 
goal: (List.Forall₂ R ⇒ R) List.prod List.prod

full_name: List.sum_hom
code: @[to_additive]
theorem prod_hom (l : List M) {F : Type*} [FunLike F M N] [MonoidHomClass F M N] (f : F) :
    (l.map f).prod = f l.prod 
goal: (List.map (⇑f) l).sum = f l.sum

full_name: List.prod_hom
code: @[to_additive]
theorem prod_hom (l : List M) {F : Type*} [FunLike F M N] [MonoidHomClass F M N] (f : F) :
    (l.map f).prod = f l.prod 
goal: (List.map (⇑f) l).prod = f l.prod

full_name: List.sum_hom₂
code: @[to_additive]
theorem prod_hom₂ (l : List ι) (f : M → N → P) (hf : ∀ a b c d, f (a * b) (c * d) = f a c * f b d)
    (hf' : f 1 1 = 1) (f₁ : ι → M) (f₂ : ι → N) :
    (l.map fun i => f (f₁ i) (f₂ i)).prod = f (l.map f₁).prod (l.map f₂).prod 
goal: (List.map (fun i => f (f₁ i) (f₂ i)) l).sum = f (List.map f₁ l).sum (List.map f₂ l).sum

full_name: List.prod_hom₂
code: @[to_additive]
theorem prod_hom₂ (l : List ι) (f : M → N → P) (hf : ∀ a b c d, f (a * b) (c * d) = f a c * f b d)
    (hf' : f 1 1 = 1) (f₁ : ι → M) (f₂ : ι → N) :
    (l.map fun i => f (f₁ i) (f₂ i)).prod = f (l.map f₁).prod (l.map f₂).prod 
goal: (List.map (fun i => f (f₁ i) (f₂ i)) l).prod = f (List.map f₁ l).prod (List.map f₂ l).prod

full_name: List.prod_map_mul
code: @[to_additive (attr := simp)]
theorem prod_map_mul {α : Type*} [CommMonoid α] {l : List ι} {f g : ι → α} :
    (l.map fun i => f i * g i).prod = (l.map f).prod * (l.map g).prod 
goal: (List.map (fun i => f i * g i) l).prod = (List.map f l).prod * (List.map g l).prod

full_name: List.sum_map_add
code: @[to_additive (attr := simp)]
theorem prod_map_mul {α : Type*} [CommMonoid α] {l : List ι} {f g : ι → α} :
    (l.map fun i => f i * g i).prod = (l.map f).prod * (l.map g).prod 
goal: (List.map (fun i => f i + g i) l).sum = (List.map f l).sum + (List.map g l).sum

full_name: List.prod_map_hom
code: @[to_additive]
theorem prod_map_hom (L : List ι) (f : ι → M) {G : Type*} [FunLike G M N] [MonoidHomClass G M N]
    (g : G) :
    (L.map (g ∘ f)).prod = g (L.map f).prod 
goal: (List.map (⇑g ∘ f) L).prod = g (List.map f L).prod

full_name: List.sum_map_hom
code: @[to_additive]
theorem prod_map_hom (L : List ι) (f : ι → M) {G : Type*} [FunLike G M N] [MonoidHomClass G M N]
    (g : G) :
    (L.map (g ∘ f)).prod = g (L.map f).prod 
goal: (List.map (⇑g ∘ f) L).sum = g (List.map f L).sum

full_name: List.prod_isUnit
code: @[to_additive]
theorem prod_isUnit : ∀ {L : List M}, (∀ m ∈ L, IsUnit m) → IsUnit L.prod
  
goal: (∀ m ∈ L, IsUnit m) → IsUnit L.prod

full_name: List.sum_isAddUnit
code: @[to_additive]
theorem prod_isUnit : ∀ {L : List M}, (∀ m ∈ L, IsUnit m) → IsUnit L.prod
  
goal: (∀ m ∈ L, IsAddUnit m) → IsAddUnit L.sum

full_name: List.sum_isAddUnit_iff
code: @[to_additive]
theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} :
    IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m 
goal: IsAddUnit L.sum ↔ ∀ m ∈ L, IsAddUnit m

full_name: List.prod_isUnit_iff
code: @[to_additive]
theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} :
    IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m 
goal: IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m

full_name: List.prod_take_mul_prod_drop
code: @[to_additive (attr := simp)]
theorem prod_take_mul_prod_drop : ∀ (L : List M) (i : ℕ), (L.take i).prod * (L.drop i).prod = L.prod
  
goal: (List.take i L).prod * (List.drop i L).prod = L.prod

full_name: List.sum_take_add_sum_drop
code: @[to_additive (attr := simp)]
theorem prod_take_mul_prod_drop : ∀ (L : List M) (i : ℕ), (L.take i).prod * (L.drop i).prod = L.prod
  
goal: (List.take i L).sum + (List.drop i L).sum = L.sum

full_name: List.prod_take_succ
code: @[to_additive (attr := simp)]
theorem prod_take_succ :
    ∀ (L : List M) (i : ℕ) (p : i < L.length), (L.take (i + 1)).prod = (L.take i).prod * L[i]
  
goal: (List.take (i + 1) L).prod = (List.take i L).prod * L[i]

full_name: List.sum_take_succ
code: @[to_additive (attr := simp)]
theorem prod_take_succ :
    ∀ (L : List M) (i : ℕ) (p : i < L.length), (L.take (i + 1)).prod = (L.take i).prod * L[i]
  
goal: (List.take (i + 1) L).sum = (List.take i L).sum + L[i]

full_name: List.length_pos_of_sum_ne_zero
code: /-- A list with product not one must have positive length. -/
@[to_additive "A list with sum not zero must have positive length."]
theorem length_pos_of_prod_ne_one (L : List M) (h : L.prod ≠ 1) : 0 < L.length 
goal: 0 < L.length

full_name: List.length_pos_of_prod_ne_one
code: /-- A list with product not one must have positive length. -/
@[to_additive "A list with sum not zero must have positive length."]
theorem length_pos_of_prod_ne_one (L : List M) (h : L.prod ≠ 1) : 0 < L.length 
goal: 0 < L.length

full_name: List.length_pos_of_sum_pos
code: /-- A list with product greater than one must have positive length. -/
@[to_additive length_pos_of_sum_pos "A list with positive sum must have positive length."]
theorem length_pos_of_one_lt_prod [Preorder M] (L : List M) (h : 1 < L.prod) : 0 < L.length 
goal: 0 < L.length

full_name: List.length_pos_of_one_lt_prod
code: /-- A list with product greater than one must have positive length. -/
@[to_additive length_pos_of_sum_pos "A list with positive sum must have positive length."]
theorem length_pos_of_one_lt_prod [Preorder M] (L : List M) (h : 1 < L.prod) : 0 < L.length 
goal: 0 < L.length

full_name: List.length_pos_of_prod_lt_one
code: /-- A list with product less than one must have positive length. -/
@[to_additive "A list with negative sum must have positive length."]
theorem length_pos_of_prod_lt_one [Preorder M] (L : List M) (h : L.prod < 1) : 0 < L.length 
goal: 0 < L.length

full_name: List.length_pos_of_sum_neg
code: /-- A list with product less than one must have positive length. -/
@[to_additive "A list with negative sum must have positive length."]
theorem length_pos_of_prod_lt_one [Preorder M] (L : List M) (h : L.prod < 1) : 0 < L.length 
goal: 0 < L.length

full_name: List.prod_set
code: @[to_additive]
theorem prod_set :
    ∀ (L : List M) (n : ℕ) (a : M),
      (L.set n a).prod =
        ((L.take n).prod * if n < L.length then a else 1) * (L.drop (n + 1)).prod
  
goal: (L.set n a).prod = ((List.take n L).prod * if n < L.length then a else 1) * (List.drop (n + 1) L).prod

full_name: List.sum_set
code: @[to_additive]
theorem prod_set :
    ∀ (L : List M) (n : ℕ) (a : M),
      (L.set n a).prod =
        ((L.take n).prod * if n < L.length then a else 1) * (L.drop (n + 1)).prod
  
goal: (L.set n a).sum = ((List.take n L).sum + if n < L.length then a else 0) + (List.drop (n + 1) L).sum

full_name: List.get?_zero_mul_tail_prod
code: /-- We'd like to state this as `L.headI * L.tail.prod = L.prod`, but because `L.headI` relies on an
inhabited instance to return a garbage value on the empty list, this is not possible.
Instead, we write the statement in terms of `(L.get? 0).getD 1`.
-/
@[to_additive "We'd like to state this as `L.headI + L.tail.sum = L.sum`, but because `L.headI`
  relies on an inhabited instance to return a garbage value on the empty list, this is not possible.
  Instead, we write the statement in terms of `(L.get? 0).getD 0`."]
theorem get?_zero_mul_tail_prod (l : List M) : (l.get? 0).getD 1 * l.tail.prod = l.prod 
goal: (l.get? 0).getD 1 * l.tail.prod = l.prod

full_name: List.get?_zero_add_tail_sum
code: /-- We'd like to state this as `L.headI * L.tail.prod = L.prod`, but because `L.headI` relies on an
inhabited instance to return a garbage value on the empty list, this is not possible.
Instead, we write the statement in terms of `(L.get? 0).getD 1`.
-/
@[to_additive "We'd like to state this as `L.headI + L.tail.sum = L.sum`, but because `L.headI`
  relies on an inhabited instance to return a garbage value on the empty list, this is not possible.
  Instead, we write the statement in terms of `(L.get? 0).getD 0`."]
theorem get?_zero_mul_tail_prod (l : List M) : (l.get? 0).getD 1 * l.tail.prod = l.prod 
goal: (l.get? 0).getD 0 + l.tail.sum = l.sum

full_name: List.headI_add_tail_sum_of_ne_nil
code: /-- Same as `get?_zero_mul_tail_prod`, but avoiding the `List.headI` garbage complication by
  requiring the list to be nonempty. -/
@[to_additive "Same as `get?_zero_add_tail_sum`, but avoiding the `List.headI` garbage complication
  by requiring the list to be nonempty."]
theorem headI_mul_tail_prod_of_ne_nil [Inhabited M] (l : List M) (h : l ≠ []) :
    l.headI * l.tail.prod = l.prod 
goal: l.headI + l.tail.sum = l.sum

full_name: List.headI_mul_tail_prod_of_ne_nil
code: /-- Same as `get?_zero_mul_tail_prod`, but avoiding the `List.headI` garbage complication by
  requiring the list to be nonempty. -/
@[to_additive "Same as `get?_zero_add_tail_sum`, but avoiding the `List.headI` garbage complication
  by requiring the list to be nonempty."]
theorem headI_mul_tail_prod_of_ne_nil [Inhabited M] (l : List M) (h : l ≠ []) :
    l.headI * l.tail.prod = l.prod 
goal: l.headI * l.tail.prod = l.prod

full_name: Commute.list_prod_right
code: @[to_additive]
theorem _root_.Commute.list_prod_right (l : List M) (y : M) (h : ∀ x ∈ l, Commute y x) :
    Commute y l.prod 
goal: Commute y l.prod

full_name: AddCommute.list_sum_right
code: @[to_additive]
theorem _root_.Commute.list_prod_right (l : List M) (y : M) (h : ∀ x ∈ l, Commute y x) :
    Commute y l.prod 
goal: AddCommute y l.sum

full_name: Commute.list_prod_left
code: @[to_additive]
theorem _root_.Commute.list_prod_left (l : List M) (y : M) (h : ∀ x ∈ l, Commute x y) :
    Commute l.prod y 
goal: Commute l.prod y

full_name: AddCommute.list_sum_left
code: @[to_additive]
theorem _root_.Commute.list_prod_left (l : List M) (y : M) (h : ∀ x ∈ l, Commute x y) :
    Commute l.prod y 
goal: AddCommute l.sum y

full_name: List.sum_range_succ
code: @[to_additive] lemma prod_range_succ (f : ℕ → M) (n : ℕ) :
    ((range n.succ).map f).prod = ((range n).map f).prod * f n 
goal: (List.map f (List.range n.succ)).sum = (List.map f (List.range n)).sum + f n

full_name: List.prod_range_succ
code: @[to_additive] lemma prod_range_succ (f : ℕ → M) (n : ℕ) :
    ((range n.succ).map f).prod = ((range n).map f).prod * f n 
goal: (List.map f (List.range n.succ)).prod = (List.map f (List.range n)).prod * f n

full_name: List.sum_range_succ'
code: /-- A variant of `prod_range_succ` which pulls off the first term in the product rather than the
last. -/
@[to_additive
"A variant of `sum_range_succ` which pulls off the first term in the sum rather than the last."]
lemma prod_range_succ' (f : ℕ → M) (n : ℕ) :
    ((range n.succ).map f).prod = f 0 * ((range n).map fun i ↦ f i.succ).prod 
goal: (List.map f (List.range n.succ)).sum = f 0 + (List.map (fun i => f i.succ) (List.range n)).sum

full_name: List.prod_range_succ'
code: /-- A variant of `prod_range_succ` which pulls off the first term in the product rather than the
last. -/
@[to_additive
"A variant of `sum_range_succ` which pulls off the first term in the sum rather than the last."]
lemma prod_range_succ' (f : ℕ → M) (n : ℕ) :
    ((range n.succ).map f).prod = f 0 * ((range n).map fun i ↦ f i.succ).prod 
goal: (List.map f (List.range n.succ)).prod = f 0 * (List.map (fun i => f i.succ) (List.range n)).prod

full_name: List.sum_eq_zero
code: @[to_additive] lemma prod_eq_one (hl : ∀ x ∈ l, x = 1) : l.prod = 1 
goal: l.sum = 0

full_name: List.prod_eq_one
code: @[to_additive] lemma prod_eq_one (hl : ∀ x ∈ l, x = 1) : l.prod = 1 
goal: l.prod = 1

full_name: List.exists_mem_ne_zero_of_sum_ne_zero
code: @[to_additive] lemma exists_mem_ne_one_of_prod_ne_one (h : l.prod ≠ 1) :
    ∃ x ∈ l, x ≠ (1 : M) 
goal: ∃ x ∈ l, x ≠ 0

full_name: List.exists_mem_ne_one_of_prod_ne_one
code: @[to_additive] lemma exists_mem_ne_one_of_prod_ne_one (h : l.prod ≠ 1) :
    ∃ x ∈ l, x ≠ (1 : M) 
goal: ∃ x ∈ l, x ≠ 1

full_name: List.sum_erase_of_comm
code: @[to_additive]
lemma prod_erase_of_comm [DecidableEq M] (ha : a ∈ l) (comm : ∀ x ∈ l, ∀ y ∈ l, x * y = y * x) :
    a * (l.erase a).prod = l.prod 
goal: a + (l.erase a).sum = l.sum

full_name: List.prod_erase_of_comm
code: @[to_additive]
lemma prod_erase_of_comm [DecidableEq M] (ha : a ∈ l) (comm : ∀ x ∈ l, ∀ y ∈ l, x * y = y * x) :
    a * (l.erase a).prod = l.prod 
goal: a * (l.erase a).prod = l.prod

full_name: List.prod_map_eq_pow_single
code: @[to_additive]
lemma prod_map_eq_pow_single [DecidableEq α] {l : List α} (a : α) (f : α → M)
    (hf : ∀ a', a' ≠ a → a' ∈ l → f a' = 1) : (l.map f).prod = f a ^ l.count a 
goal: (List.map f l).prod = f a ^ List.count a l

full_name: List.sum_map_eq_nsmul_single
code: @[to_additive]
lemma prod_map_eq_pow_single [DecidableEq α] {l : List α} (a : α) (f : α → M)
    (hf : ∀ a', a' ≠ a → a' ∈ l → f a' = 1) : (l.map f).prod = f a ^ l.count a 
goal: (List.map f l).sum = List.count a l • f a

full_name: List.sum_eq_nsmul_single
code: @[to_additive]
lemma prod_eq_pow_single [DecidableEq M] (a : M) (h : ∀ a', a' ≠ a → a' ∈ l → a' = 1) :
    l.prod = a ^ l.count a 
goal: l.sum = List.count a l • a

full_name: List.prod_eq_pow_single
code: @[to_additive]
lemma prod_eq_pow_single [DecidableEq M] (a : M) (h : ∀ a', a' ≠ a → a' ∈ l → a' = 1) :
    l.prod = a ^ l.count a 
goal: l.prod = a ^ List.count a l

full_name: List.Perm.sum_eq'
code: /-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive "If elements of a list additively commute with each other, then their sum does not
depend on the order of elements."]
lemma Perm.prod_eq' (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) : l₁.prod = l₂.prod 
goal: l₁.sum = l₂.sum

full_name: List.Perm.prod_eq'
code: /-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive "If elements of a list additively commute with each other, then their sum does not
depend on the order of elements."]
lemma Perm.prod_eq' (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) : l₁.prod = l₂.prod 
goal: l₁.prod = l₂.prod

full_name: List.prod_erase
code: @[to_additive (attr := simp)]
lemma prod_erase [DecidableEq M] (ha : a ∈ l) : a * (l.erase a).prod = l.prod 
goal: a * (l.erase a).prod = l.prod

full_name: List.sum_erase
code: @[to_additive (attr := simp)]
lemma prod_erase [DecidableEq M] (ha : a ∈ l) : a * (l.erase a).prod = l.prod 
goal: a + (l.erase a).sum = l.sum

full_name: List.sum_map_erase
code: @[to_additive (attr := simp)]
lemma prod_map_erase [DecidableEq α] (f : α → M) {a} :
    ∀ {l : List α}, a ∈ l → f a * ((l.erase a).map f).prod = (l.map f).prod
  
goal: a ∈ l → f a + (List.map f (l.erase a)).sum = (List.map f l).sum

full_name: List.prod_map_erase
code: @[to_additive (attr := simp)]
lemma prod_map_erase [DecidableEq α] (f : α → M) {a} :
    ∀ {l : List α}, a ∈ l → f a * ((l.erase a).map f).prod = (l.map f).prod
  
goal: a ∈ l → f a * (List.map f (l.erase a)).prod = (List.map f l).prod

full_name: List.Perm.sum_eq
code: @[to_additive] lemma Perm.prod_eq (h : Perm l₁ l₂) : prod l₁ = prod l₂ 
goal: l₁.sum = l₂.sum

full_name: List.Perm.prod_eq
code: @[to_additive] lemma Perm.prod_eq (h : Perm l₁ l₂) : prod l₁ = prod l₂ 
goal: l₁.prod = l₂.prod

full_name: List.sum_reverse
code: @[to_additive] lemma prod_reverse (l : List M) : prod l.reverse = prod l 
goal: l.reverse.sum = l.sum

full_name: List.prod_reverse
code: @[to_additive] lemma prod_reverse (l : List M) : prod l.reverse = prod l 
goal: l.reverse.prod = l.prod

full_name: List.sum_add_sum_eq_sum_zipWith_add_sum_drop
code: @[to_additive]
lemma prod_mul_prod_eq_prod_zipWith_mul_prod_drop :
    ∀ l l' : List M,
      l.prod * l'.prod =
        (zipWith (· * ·) l l').prod * (l.drop l'.length).prod * (l'.drop l.length).prod
  
goal: l.sum + l'.sum =
  (List.zipWith (fun x x_1 => x + x_1) l l').sum + (List.drop l'.length l).sum + (List.drop l.length l').sum

full_name: List.prod_mul_prod_eq_prod_zipWith_mul_prod_drop
code: @[to_additive]
lemma prod_mul_prod_eq_prod_zipWith_mul_prod_drop :
    ∀ l l' : List M,
      l.prod * l'.prod =
        (zipWith (· * ·) l l').prod * (l.drop l'.length).prod * (l'.drop l.length).prod
  
goal: l.prod * l'.prod =
  (List.zipWith (fun x x_1 => x * x_1) l l').prod * (List.drop l'.length l).prod * (List.drop l.length l').prod

full_name: List.prod_mul_prod_eq_prod_zipWith_of_length_eq
code: @[to_additive]
lemma prod_mul_prod_eq_prod_zipWith_of_length_eq (l l' : List M) (h : l.length = l'.length) :
    l.prod * l'.prod = (zipWith (· * ·) l l').prod 
goal: l.prod * l'.prod = (List.zipWith (fun x x_1 => x * x_1) l l').prod

full_name: List.sum_add_sum_eq_sum_zipWith_of_length_eq
code: @[to_additive]
lemma prod_mul_prod_eq_prod_zipWith_of_length_eq (l l' : List M) (h : l.length = l'.length) :
    l.prod * l'.prod = (zipWith (· * ·) l l').prod 
goal: l.sum + l'.sum = (List.zipWith (fun x x_1 => x + x_1) l l').sum

full_name: List.sum_map_ite
code: @[to_additive]
lemma prod_map_ite (p : α → Prop) [DecidablePred p] (f g : α → M) (l : List α) :
    (l.map fun a => if p a then f a else g a).prod =
      ((l.filter p).map f).prod * ((l.filter fun a ↦ ¬p a).map g).prod 
goal: (List.map (fun a => if p a then f a else g a) l).sum =
  (List.map f (List.filter (fun b => decide (p b)) l)).sum + (List.map g (List.filter (fun a => decide ¬p a) l)).sum

full_name: List.prod_map_ite
code: @[to_additive]
lemma prod_map_ite (p : α → Prop) [DecidablePred p] (f g : α → M) (l : List α) :
    (l.map fun a => if p a then f a else g a).prod =
      ((l.filter p).map f).prod * ((l.filter fun a ↦ ¬p a).map g).prod 
goal: (List.map (fun a => if p a then f a else g a) l).prod =
  (List.map f (List.filter (fun b => decide (p b)) l)).prod * (List.map g (List.filter (fun a => decide ¬p a) l)).prod

full_name: List.prod_map_filter_mul_prod_map_filter_not
code: @[to_additive]
lemma prod_map_filter_mul_prod_map_filter_not (p : α → Prop) [DecidablePred p] (f : α → M)
    (l : List α) :
    ((l.filter p).map f).prod * ((l.filter fun x => ¬p x).map f).prod = (l.map f).prod 
goal: (List.map f (List.filter (fun b => decide (p b)) l)).prod * (List.map f (List.filter (fun x => decide ¬p x) l)).prod =
  (List.map f l).prod

full_name: List.sum_map_filter_add_sum_map_filter_not
code: @[to_additive]
lemma prod_map_filter_mul_prod_map_filter_not (p : α → Prop) [DecidablePred p] (f : α → M)
    (l : List α) :
    ((l.filter p).map f).prod * ((l.filter fun x => ¬p x).map f).prod = (l.map f).prod 
goal: (List.map f (List.filter (fun b => decide (p b)) l)).sum + (List.map f (List.filter (fun x => decide ¬p x) l)).sum =
  (List.map f l).sum

full_name: List.eq_of_sum_take_eq
code: @[to_additive]
lemma eq_of_prod_take_eq [LeftCancelMonoid M] {L L' : List M} (h : L.length = L'.length)
    (h' : ∀ i ≤ L.length, (L.take i).prod = (L'.take i).prod) : L = L' 
goal: L = L'

full_name: List.eq_of_prod_take_eq
code: @[to_additive]
lemma eq_of_prod_take_eq [LeftCancelMonoid M] {L L' : List M} (h : L.length = L'.length)
    (h' : ∀ i ≤ L.length, (L.take i).prod = (L'.take i).prod) : L = L' 
goal: L = L'

full_name: List.prod_inv_reverse
code: /-- This is the `List.prod` version of `mul_inv_rev` -/
@[to_additive "This is the `List.sum` version of `add_neg_rev`"]
theorem prod_inv_reverse : ∀ L : List G, L.prod⁻¹ = (L.map fun x => x⁻¹).reverse.prod
  
goal: L.prod⁻¹ = (List.map (fun x => x⁻¹) L).reverse.prod

full_name: List.sum_neg_reverse
code: /-- This is the `List.prod` version of `mul_inv_rev` -/
@[to_additive "This is the `List.sum` version of `add_neg_rev`"]
theorem prod_inv_reverse : ∀ L : List G, L.prod⁻¹ = (L.map fun x => x⁻¹).reverse.prod
  
goal: -L.sum = (List.map (fun x => -x) L).reverse.sum

full_name: List.prod_reverse_noncomm
code: /-- A non-commutative variant of `List.prod_reverse` -/
@[to_additive "A non-commutative variant of `List.sum_reverse`"]
theorem prod_reverse_noncomm : ∀ L : List G, L.reverse.prod = (L.map fun x => x⁻¹).prod⁻¹ 
goal: L.reverse.prod = (List.map (fun x => x⁻¹) L).prod⁻¹

full_name: List.sum_reverse_noncomm
code: /-- A non-commutative variant of `List.prod_reverse` -/
@[to_additive "A non-commutative variant of `List.sum_reverse`"]
theorem prod_reverse_noncomm : ∀ L : List G, L.reverse.prod = (L.map fun x => x⁻¹).prod⁻¹ 
goal: L.reverse.sum = -(List.map (fun x => -x) L).sum

full_name: List.prod_drop_succ
code: /-- Counterpart to `List.prod_take_succ` when we have an inverse operation -/
@[to_additive (attr := simp)
  "Counterpart to `List.sum_take_succ` when we have a negation operation"]
theorem prod_drop_succ :
    ∀ (L : List G) (i : ℕ) (p), (L.drop (i + 1)).prod = (L.get ⟨i, p⟩)⁻¹ * (L.drop i).prod
  
goal: (List.drop (i + 1) L).prod = (L.get ⟨i, p⟩)⁻¹ * (List.drop i L).prod

full_name: List.sum_drop_succ
code: /-- Counterpart to `List.prod_take_succ` when we have an inverse operation -/
@[to_additive (attr := simp)
  "Counterpart to `List.sum_take_succ` when we have a negation operation"]
theorem prod_drop_succ :
    ∀ (L : List G) (i : ℕ) (p), (L.drop (i + 1)).prod = (L.get ⟨i, p⟩)⁻¹ * (L.drop i).prod
  
goal: (List.drop (i + 1) L).sum = -L.get ⟨i, p⟩ + (List.drop i L).sum

full_name: List.prod_range_div'
code: /-- Cancellation of a telescoping product. -/
@[to_additive "Cancellation of a telescoping sum."]
theorem prod_range_div' (n : ℕ) (f : ℕ → G) :
    ((range n).map fun k ↦ f k / f (k + 1)).prod = f 0 / f n 
goal: (List.map (fun k => f k / f (k + 1)) (List.range n)).prod = f 0 / f n

full_name: List.sum_range_sub'
code: /-- Cancellation of a telescoping product. -/
@[to_additive "Cancellation of a telescoping sum."]
theorem prod_range_div' (n : ℕ) (f : ℕ → G) :
    ((range n).map fun k ↦ f k / f (k + 1)).prod = f 0 / f n 
goal: (List.map (fun k => f k - f (k + 1)) (List.range n)).sum = f 0 - f n

full_name: List.prod_rotate_eq_one_of_prod_eq_one
code: lemma prod_rotate_eq_one_of_prod_eq_one :
    ∀ {l : List G} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  
goal: l.prod = 1 → ∀ (n : ℕ), (l.rotate n).prod = 1

full_name: List.sum_neg
code: /-- This is the `List.prod` version of `mul_inv` -/
@[to_additive "This is the `List.sum` version of `add_neg`"]
theorem prod_inv : ∀ L : List G, L.prod⁻¹ = (L.map fun x => x⁻¹).prod
  
goal: -L.sum = (List.map (fun x => -x) L).sum

full_name: List.prod_inv
code: /-- This is the `List.prod` version of `mul_inv` -/
@[to_additive "This is the `List.sum` version of `add_neg`"]
theorem prod_inv : ∀ L : List G, L.prod⁻¹ = (L.map fun x => x⁻¹).prod
  
goal: L.prod⁻¹ = (List.map (fun x => x⁻¹) L).prod

full_name: List.sum_range_sub
code: /-- Cancellation of a telescoping product. -/
@[to_additive "Cancellation of a telescoping sum."]
theorem prod_range_div (n : ℕ) (f : ℕ → G) :
    ((range n).map fun k ↦ f (k + 1) / f k).prod = f n / f 0 
goal: (List.map (fun k => f (k + 1) - f k) (List.range n)).sum = f n - f 0

full_name: List.prod_range_div
code: /-- Cancellation of a telescoping product. -/
@[to_additive "Cancellation of a telescoping sum."]
theorem prod_range_div (n : ℕ) (f : ℕ → G) :
    ((range n).map fun k ↦ f (k + 1) / f k).prod = f n / f 0 
goal: (List.map (fun k => f (k + 1) / f k) (List.range n)).prod = f n / f 0

full_name: List.sum_set'
code: /-- Alternative version of `List.prod_set` when the list is over a group -/
@[to_additive "Alternative version of `List.sum_set` when the list is over a group"]
theorem prod_set' (L : List G) (n : ℕ) (a : G) :
    (L.set n a).prod = L.prod * if hn : n < L.length then (L.get ⟨n, hn⟩)⁻¹ * a else 1 
goal: (L.set n a).sum = L.sum + if hn : n < L.length then -L.get ⟨n, hn⟩ + a else 0

full_name: List.prod_set'
code: /-- Alternative version of `List.prod_set` when the list is over a group -/
@[to_additive "Alternative version of `List.sum_set` when the list is over a group"]
theorem prod_set' (L : List G) (n : ℕ) (a : G) :
    (L.set n a).prod = L.prod * if hn : n < L.length then (L.get ⟨n, hn⟩)⁻¹ * a else 1 
goal: (L.set n a).prod = L.prod * if hn : n < L.length then (L.get ⟨n, hn⟩)⁻¹ * a else 1

full_name: List.prod_map_ite_eq
code: @[to_additive]
lemma prod_map_ite_eq {A : Type*} [DecidableEq A] (l : List A) (f g : A → G) (a : A) :
    (l.map fun x => if x = a then f x else g x).prod
      = (f a / g a) ^ (l.count a) * (l.map g).prod 
goal: (List.map (fun x => if x = a then f x else g x) l).prod = (f a / g a) ^ List.count a l * (List.map g l).prod

full_name: List.sum_map_ite_eq
code: @[to_additive]
lemma prod_map_ite_eq {A : Type*} [DecidableEq A] (l : List A) (f g : A → G) (a : A) :
    (l.map fun x => if x = a then f x else g x).prod
      = (f a / g a) ^ (l.count a) * (l.map g).prod 
goal: (List.map (fun x => if x = a then f x else g x) l).sum = List.count a l • (f a - g a) + (List.map g l).sum

full_name: List.sum_const_nat
code: theorem sum_const_nat (m n : ℕ) : sum (replicate m n) = m * n 
goal: (List.replicate m n).sum = m * n

full_name: List.headI_add_tail_sum
code: /-- This relies on `default ℕ = 0`. -/
theorem headI_add_tail_sum (L : List ℕ) : L.headI + L.tail.sum = L.sum 
goal: L.headI + L.tail.sum = L.sum

full_name: List.headI_le_sum
code: /-- This relies on `default ℕ = 0`. -/
theorem headI_le_sum (L : List ℕ) : L.headI ≤ L.sum 
goal: L.headI ≤ L.sum

full_name: List.tail_sum
code: /-- This relies on `default ℕ = 0`. -/
theorem tail_sum (L : List ℕ) : L.tail.sum = L.sum - L.headI 
goal: L.tail.sum = L.sum - L.headI

full_name: List.alternatingProd_nil
code: @[to_additive (attr := simp)]
theorem alternatingProd_nil : alternatingProd ([] : List α) = 1 
goal: [].alternatingProd = 1

full_name: List.alternatingSum_nil
code: @[to_additive (attr := simp)]
theorem alternatingProd_nil : alternatingProd ([] : List α) = 1 
goal: [].alternatingSum = 0

full_name: List.alternatingProd_singleton
code: @[to_additive (attr := simp)]
theorem alternatingProd_singleton (a : α) : alternatingProd [a] = a 
goal: [a].alternatingProd = a

full_name: List.alternatingSum_singleton
code: @[to_additive (attr := simp)]
theorem alternatingProd_singleton (a : α) : alternatingProd [a] = a 
goal: [a].alternatingSum = a

full_name: List.alternatingProd_cons_cons'
code: @[to_additive]
theorem alternatingProd_cons_cons' (a b : α) (l : List α) :
    alternatingProd (a :: b :: l) = a * b⁻¹ * alternatingProd l 
goal: (a :: b :: l).alternatingProd = a * b⁻¹ * l.alternatingProd

full_name: List.alternatingSum_cons_cons'
code: @[to_additive]
theorem alternatingProd_cons_cons' (a b : α) (l : List α) :
    alternatingProd (a :: b :: l) = a * b⁻¹ * alternatingProd l 
goal: (a :: b :: l).alternatingSum = a + -b + l.alternatingSum

full_name: List.alternatingSum_cons_cons
code: @[to_additive]
theorem alternatingProd_cons_cons [DivInvMonoid α] (a b : α) (l : List α) :
    alternatingProd (a :: b :: l) = a / b * alternatingProd l 
goal: (a :: b :: l).alternatingSum = a - b + l.alternatingSum

full_name: List.alternatingProd_cons_cons
code: @[to_additive]
theorem alternatingProd_cons_cons [DivInvMonoid α] (a b : α) (l : List α) :
    alternatingProd (a :: b :: l) = a / b * alternatingProd l 
goal: (a :: b :: l).alternatingProd = a / b * l.alternatingProd

full_name: List.alternatingSum_cons'
code: @[to_additive]
theorem alternatingProd_cons' :
    ∀ (a : α) (l : List α), alternatingProd (a :: l) = a * (alternatingProd l)⁻¹
  
goal: (a :: l).alternatingSum = a + -l.alternatingSum

full_name: List.alternatingProd_cons'
code: @[to_additive]
theorem alternatingProd_cons' :
    ∀ (a : α) (l : List α), alternatingProd (a :: l) = a * (alternatingProd l)⁻¹
  
goal: (a :: l).alternatingProd = a * l.alternatingProd⁻¹

full_name: List.alternatingSum_cons
code: @[to_additive (attr := simp)]
theorem alternatingProd_cons (a : α) (l : List α) :
    alternatingProd (a :: l) = a / alternatingProd l 
goal: (a :: l).alternatingSum = a - l.alternatingSum

full_name: List.alternatingProd_cons
code: @[to_additive (attr := simp)]
theorem alternatingProd_cons (a : α) (l : List α) :
    alternatingProd (a :: l) = a / alternatingProd l 
goal: (a :: l).alternatingProd = a / l.alternatingProd

full_name: List.sum_nat_mod
code: lemma sum_nat_mod (l : List ℕ) (n : ℕ) : l.sum % n = (l.map (· % n)).sum % n 
goal: l.sum % n = (List.map (fun x => x % n) l).sum % n

full_name: List.prod_nat_mod
code: lemma prod_nat_mod (l : List ℕ) (n : ℕ) : l.prod % n = (l.map (· % n)).prod % n 
goal: l.prod % n = (List.map (fun x => x % n) l).prod % n

full_name: List.sum_int_mod
code: lemma sum_int_mod (l : List ℤ) (n : ℤ) : l.sum % n = (l.map (· % n)).sum % n 
goal: l.sum % n = (List.map (fun x => x % n) l).sum % n

full_name: List.prod_int_mod
code: lemma prod_int_mod (l : List ℤ) (n : ℤ) : l.prod % n = (l.map (· % n)).prod % n 
goal: l.prod % n = (List.map (fun x => x % n) l).prod % n

full_name: List.sum_map_count_dedup_filter_eq_countP
code: /-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/
theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) :
    ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p 
goal: (List.map (fun x => List.count x l) (List.filter p l.dedup)).sum = List.countP p l

full_name: List.sum_map_count_dedup_eq_length
code: theorem sum_map_count_dedup_eq_length (l : List α) :
    (l.dedup.map fun x => l.count x).sum = l.length 
goal: (List.map (fun x => List.count x l) l.dedup).sum = l.length

full_name: map_list_sum
code: @[to_additive]
theorem map_list_prod {F : Type*} [FunLike F M N] [MonoidHomClass F M N] (f : F) (l : List M) :
    f l.prod = (l.map f).prod 
goal: f l.sum = (List.map (⇑f) l).sum

full_name: map_list_prod
code: @[to_additive]
theorem map_list_prod {F : Type*} [FunLike F M N] [MonoidHomClass F M N] (f : F) (l : List M) :
    f l.prod = (l.map f).prod 
goal: f l.prod = (List.map (⇑f) l).prod

full_name: AddMonoidHom.map_list_sum
code: @[to_additive]
protected theorem map_list_prod (f : M →* N) (l : List M) : f l.prod = (l.map f).prod 
goal: f l.sum = (List.map (⇑f) l).sum

full_name: MonoidHom.map_list_prod
code: @[to_additive]
protected theorem map_list_prod (f : M →* N) (l : List M) : f l.prod = (l.map f).prod 
goal: f l.prod = (List.map (⇑f) l).prod

full_name: Nat.sum_eq_listSum
code: @[simp] lemma Nat.sum_eq_listSum (l : List ℕ) : Nat.sum l = l.sum 
goal: Nat.sum l = l.sum

full_name: List.length_sigma
code: lemma length_sigma {σ : α → Type*} (l₁ : List α) (l₂ : ∀ a, List (σ a)) :
    length (l₁.sigma l₂) = (l₁.map fun a ↦ length (l₂ a)).sum 
goal: (l₁.sigma l₂).length = (List.map (fun a => (l₂ a).length) l₁).sum

full_name: List.ranges_join
code: lemma ranges_join (l : List ℕ) : l.ranges.join = range l.sum 
goal: l.ranges.join = List.range l.sum

full_name: List.mem_mem_ranges_iff_lt_sum
code: /-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum`. -/
lemma mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} :
    (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum 
goal: (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum

full_name: List.length_join
code: @[simp]
theorem length_join (L : List (List α)) : length (join L) = sum (map length L) 
goal: L.join.length = (List.map List.length L).sum

full_name: List.countP_join
code: lemma countP_join (p : α → Bool) : ∀ L : List (List α), countP p L.join = (L.map (countP p)).sum
  
goal: List.countP p L.join = (List.map (List.countP p) L).sum

full_name: List.count_join
code: lemma count_join [BEq α] (L : List (List α)) (a : α) : L.join.count a = (L.map (count a)).sum 
goal: List.count a L.join = (List.map (List.count a) L).sum

full_name: List.length_bind
code: @[simp]
theorem length_bind (l : List α) (f : α → List β) :
    length (List.bind l f) = sum (map (length ∘ f) l) 
goal: (l.bind f).length = (List.map (List.length ∘ f) l).sum

full_name: List.countP_bind
code: lemma countP_bind (p : β → Bool) (l : List α) (f : α → List β) :
    countP p (l.bind f) = sum (map (countP p ∘ f) l) 
goal: List.countP p (l.bind f) = (List.map (List.countP p ∘ f) l).sum

full_name: List.count_bind
code: lemma count_bind [BEq β] (l : List α) (f : α → List β) (x : β) :
    count x (l.bind f) = sum (map (count x ∘ f) l) 
goal: List.count x (l.bind f) = (List.map (List.count x ∘ f) l).sum

full_name: List.take_sum_join
code: /-- In a join, taking the first elements up to an index which is the sum of the lengths of the
first `i` sublists, is the same as taking the join of the first `i` sublists. -/
lemma take_sum_join (L : List (List α)) (i : ℕ) :
    L.join.take ((L.map length).take i).sum = (L.take i).join 
goal: List.take (List.take i (List.map List.length L)).sum L.join = (List.take i L).join

full_name: List.drop_sum_join
code: /-- In a join, dropping all the elements up to an index which is the sum of the lengths of the
first `i` sublists, is the same as taking the join after dropping the first `i` sublists. -/
lemma drop_sum_join (L : List (List α)) (i : ℕ) :
    L.join.drop ((L.map length).take i).sum = (L.drop i).join 
goal: List.drop (List.take i (List.map List.length L)).sum L.join = (List.drop i L).join

full_name: List.drop_take_succ_join_eq_getElem
code: /-- In a join of sublists, taking the slice between the indices `A` and `B - 1` gives back the
original sublist of index `i` if `A` is the sum of the lengths of sublists of index `< i`, and
`B` is the sum of the lengths of sublists of index `≤ i`. -/
lemma drop_take_succ_join_eq_getElem (L : List (List α)) (i : Nat) (h : i < L.length) :
    (L.join.take ((L.map length).take (i + 1)).sum).drop ((L.map length).take i).sum = L[i] 
goal: List.drop (List.take i (List.map List.length L)).sum
    (List.take (List.take (i + 1) (List.map List.length L)).sum L.join) =
  L[i]

full_name: List.drop_take_succ_join_eq_get
code: @[deprecated drop_take_succ_join_eq_getElem (since := "2024-06-11")]
lemma drop_take_succ_join_eq_get (L : List (List α)) (i : Fin L.length) :
    (L.join.take ((L.map length).take (i + 1)).sum).drop ((L.map length).take i).sum = get L i 
goal: List.drop (List.take (↑i) (List.map List.length L)).sum
    (List.take (List.take (↑i + 1) (List.map List.length L)).sum L.join) =
  L.get i

full_name: List.neg_one_mem_of_prod_eq_neg_one
code: /-- If a product of integers is `-1`, then at least one factor must be `-1`. -/
theorem neg_one_mem_of_prod_eq_neg_one {l : List ℤ} (h : l.prod = -1) : (-1 : ℤ) ∈ l 
goal: -1 ∈ l

full_name: List.length_le_sum_of_one_le
code: /-- If all elements in a list are bounded below by `1`, then the length of the list is bounded
by the sum of the elements. -/
theorem length_le_sum_of_one_le (L : List ℕ) (h : ∀ i ∈ L, 1 ≤ i) : L.length ≤ L.sum 
goal: L.length ≤ L.sum

full_name: List.dvd_prod
code: theorem dvd_prod [CommMonoid M] {a} {l : List M} (ha : a ∈ l) : a ∣ l.prod 
goal: a ∣ l.prod

full_name: List.Sublist.prod_dvd_prod
code: theorem Sublist.prod_dvd_prod [CommMonoid M] {l₁ l₂ : List M} (h : l₁ <+ l₂) :
    l₁.prod ∣ l₂.prod 
goal: l₁.prod ∣ l₂.prod

full_name: List.alternatingProd_append
code: @[to_additive]
theorem alternatingProd_append :
    ∀ l₁ l₂ : List α,
      alternatingProd (l₁ ++ l₂) = alternatingProd l₁ * alternatingProd l₂ ^ (-1 : ℤ) ^ length l₁
  
goal: (l₁ ++ l₂).alternatingProd = l₁.alternatingProd * l₂.alternatingProd ^ (-1) ^ l₁.length

full_name: List.alternatingSum_append
code: @[to_additive]
theorem alternatingProd_append :
    ∀ l₁ l₂ : List α,
      alternatingProd (l₁ ++ l₂) = alternatingProd l₁ * alternatingProd l₂ ^ (-1 : ℤ) ^ length l₁
  
goal: (l₁ ++ l₂).alternatingSum = l₁.alternatingSum + (-1) ^ l₁.length • l₂.alternatingSum

full_name: List.alternatingSum_reverse
code: @[to_additive]
theorem alternatingProd_reverse :
    ∀ l : List α, alternatingProd (reverse l) = alternatingProd l ^ (-1 : ℤ) ^ (length l + 1)
  
goal: l.reverse.alternatingSum = (-1) ^ (l.length + 1) • l.alternatingSum

full_name: List.alternatingProd_reverse
code: @[to_additive]
theorem alternatingProd_reverse :
    ∀ l : List α, alternatingProd (reverse l) = alternatingProd l ^ (-1 : ℤ) ^ (length l + 1)
  
goal: l.reverse.alternatingProd = l.alternatingProd ^ (-1) ^ (l.length + 1)

full_name: MulOpposite.op_list_prod
code: lemma op_list_prod : ∀ l : List M, op l.prod = (l.map op).reverse.prod 
goal: MulOpposite.op l.prod = (List.map MulOpposite.op l).reverse.prod

full_name: MulOpposite.unop_list_prod
code: lemma unop_list_prod (l : List Mᵐᵒᵖ) : l.prod.unop = (l.map unop).reverse.prod 
goal: MulOpposite.unop l.prod = (List.map MulOpposite.unop l).reverse.prod

full_name: unop_map_list_prod
code: /-- A morphism into the opposite monoid acts on the product by acting on the reversed elements. -/
lemma unop_map_list_prod {F : Type*} [FunLike F M Nᵐᵒᵖ] [MonoidHomClass F M Nᵐᵒᵖ]
    (f : F) (l : List M) :
    (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod 
goal: MulOpposite.unop (f l.prod) = (List.map (MulOpposite.unop ∘ ⇑f) l).reverse.prod

full_name: MonoidHom.unop_map_list_prod
code: /-- A morphism into the opposite monoid acts on the product by acting on the reversed elements. -/
@[deprecated _root_.unop_map_list_prod (since := "2023-01-10")]
protected theorem unop_map_list_prod (f : M →* Nᵐᵒᵖ) (l : List M) :
    (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod 
goal: MulOpposite.unop (f l.prod) = (List.map (MulOpposite.unop ∘ ⇑f) l).reverse.prod