l3lab/ntp-mathlib huggingface dataset:
theorem factorization_choose_of_lt_three_mul (hp' : p ≠ 2) (hk : p ≤ k) (hk' : p ≤ n - k)
    (hn : n < 3 * p) : (choose n k).factorization p = 0 := by
  cases' em' p.Prime with hp hp
  · exact factorization_eq_zero_of_non_prime (choose n k) hp
  cases' lt_or_le n k with hnk hkn
  · simp [choose_eq_zero_of_lt hnk]
  rw [factorization_def _ hp, @padicValNat_def _ ⟨hp⟩ _ (choose_pos hkn)]
  simp only [hp.multiplicity_choose hkn (lt_add_one _), PartENat.get_natCast, Finset.card_eq_zero,
    Finset.filter_eq_empty_iff, not_le]
  intro i hi
  rcases eq_or_lt_of_le (Finset.mem_Ico.mp hi).1 with (rfl | hi)
  · rw [pow_one, ← add_lt_add_iff_left (2 * p), ← succ_mul, two_mul, add_add_add_comm]
    exact
      lt_of_le_of_lt
        (add_le_add
          (add_le_add_right (le_mul_of_one_le_right' ((one_le_div_iff hp.pos).mpr hk)) (k % p))
          (add_le_add_right (le_mul_of_one_le_right' ((one_le_div_iff hp.pos).mpr hk'))
            ((n - k) % p)))
        (by rwa [div_add_mod, div_add_mod, add_tsub_cancel_of_le hkn])
  · replace hn : n < p ^ i
    have : 3 ≤ p := lt_of_le_of_ne hp.two_le hp'.symm
    · 

Proof state:
case hn
p n k : ℕ
hp' : p ≠ 2
hk : p ≤ k
hk' : p ≤ n - k
hn : n < 3 * p
hp : Prime p
hkn : k ≤ n
i : ℕ
hi✝ : i ∈ Finset.Ico 1 (log p n + 1)
hi : 1 < i
this : 3 ≤ p
⊢ n < p ^ i

Next tactic:
calc
        n < 3 * p := hn
        _ ≤ p * p := mul_le_mul_right' this p
        _ = p ^ 2 := (sq p).symm
        _ ≤ p ^ i := pow_le_pow_right hp.one_lt.le hi
theorem factorization_choose_of_lt_three_mul (hp' : p ≠ 2) (hk : p ≤ k) (hk' : p ≤ n - k)
    (hn : n < 3 * p) : (choose n k).factorization p = 0 := by
  cases' em' p.Prime with hp hp
  · exact factorization_eq_zero_of_non_prime (choose n k) hp
  cases' lt_or_le n k with hnk hkn
  · simp [choose_eq_zero_of_lt hnk]
  rw [factorization_def _ hp, @padicValNat_def _ ⟨hp⟩ _ (choose_pos hkn)]
  simp only [hp.multiplicity_choose hkn (lt_add_one _), PartENat.get_natCast, Finset.card_eq_zero,
    Finset.filter_eq_empty_iff, not_le]
  intro i hi
  rcases eq_or_lt_of_le (Finset.mem_Ico.mp hi).1 with (rfl | hi)
  · rw [pow_one, ← add_lt_add_iff_left (2 * p), ← succ_mul, two_mul, add_add_add_comm]
    exact
      lt_of_le_of_lt
        (add_le_add
          (add_le_add_right (le_mul_of_one_le_right' ((one_le_div_iff hp.pos).mpr hk)) (k % p))
          (add_le_add_right (le_mul_of_one_le_right' ((one_le_div_iff hp.pos).mpr hk'))
            ((n - k) % p)))
        (by rwa [div_add_mod, div_add_mod, add_tsub_cancel_of_le hkn])
  · replace hn : n < p ^ i
    have : 3 ≤ p := lt_of_le_of_ne hp.two_le hp'.symm
    · calc
        n < 3 * p := hn
        _ ≤ p * p := mul_le_mul_right' this p
        _ = p ^ 2 := (sq p).symm
        _ ≤ p ^ i := pow_le_pow_right hp.one_lt.le hi
    

Proof state:
case inr.inr.inr
p n k : ℕ
hp' : p ≠ 2
hk : p ≤ k
hk' : p ≤ n - k
hp : Prime p
hkn : k ≤ n
i : ℕ
hi✝ : i ∈ Finset.Ico 1 (log p n + 1)
hi : 1 < i
hn : n < p ^ i
⊢ k % p ^ i + (n - k) % p ^ i < p ^ i

Next tactic:
rwa [mod_eq_of_lt (lt_of_le_of_lt hkn hn), mod_eq_of_lt (lt_of_le_of_lt tsub_le_self hn),
      add_tsub_cancel_of_le hkn]
/-- Primes greater than about `2 * n / 3` and less than `n` do not appear in the factorization of
`centralBinom n`. -/
theorem factorization_centralBinom_of_two_mul_self_lt_three_mul (n_big : 2 < n) (p_le_n : p ≤ n)
    (big : 2 * n < 3 * p) : (centralBinom n).factorization p = 0 := by
  

Proof state:
p n k : ℕ
n_big : 2 < n
p_le_n : p ≤ n
big : 2 * n < 3 * p
⊢ (factorization (centralBinom n)) p = 0

Next tactic:
refine' factorization_choose_of_lt_three_mul _ p_le_n (p_le_n.trans _) big
/-- Primes greater than about `2 * n / 3` and less than `n` do not appear in the factorization of
`centralBinom n`. -/
theorem factorization_centralBinom_of_two_mul_self_lt_three_mul (n_big : 2 < n) (p_le_n : p ≤ n)
    (big : 2 * n < 3 * p) : (centralBinom n).factorization p = 0 := by
  refine' factorization_choose_of_lt_three_mul _ p_le_n (p_le_n.trans _) big
  · 

Proof state:
case refine'_1
p n k : ℕ
n_big : 2 < n
p_le_n : p ≤ n
big : 2 * n < 3 * p
⊢ p ≠ 2

Next tactic:
rintro rfl
/-- Primes greater than about `2 * n / 3` and less than `n` do not appear in the factorization of
`centralBinom n`. -/
theorem factorization_centralBinom_of_two_mul_self_lt_three_mul (n_big : 2 < n) (p_le_n : p ≤ n)
    (big : 2 * n < 3 * p) : (centralBinom n).factorization p = 0 := by
  refine' factorization_choose_of_lt_three_mul _ p_le_n (p_le_n.trans _) big
  · rintro rfl
    

Proof state:
case refine'_1
n k : ℕ
n_big : 2 < n
p_le_n : 2 ≤ n
big : 2 * n < 3 * 2
⊢ False

Next tactic:
linarith
/-- Primes greater than about `2 * n / 3` and less than `n` do not appear in the factorization of
`centralBinom n`. -/
theorem factorization_centralBinom_of_two_mul_self_lt_three_mul (n_big : 2 < n) (p_le_n : p ≤ n)
    (big : 2 * n < 3 * p) : (centralBinom n).factorization p = 0 := by
  refine' factorization_choose_of_lt_three_mul _ p_le_n (p_le_n.trans _) big
  · rintro rfl
    linarith
  · 

Proof state:
case refine'_2
p n k : ℕ
n_big : 2 < n
p_le_n : p ≤ n
big : 2 * n < 3 * p
⊢ n ≤ 2 * n - n

Next tactic:
rw [two_mul, add_tsub_cancel_left]
theorem factorization_factorial_eq_zero_of_lt (h : n < p) : (factorial n).factorization p = 0 := by
  

Proof state:
p n k : ℕ
h : n < p
⊢ (factorization n !) p = 0

Next tactic:
induction' n with n hn
theorem factorization_factorial_eq_zero_of_lt (h : n < p) : (factorial n).factorization p = 0 := by
  induction' n with n hn; · 

Proof state:
case zero
p n k : ℕ
h : zero < p
⊢ (factorization zero !) p = 0

Next tactic:
simp
theorem factorization_factorial_eq_zero_of_lt (h : n < p) : (factorial n).factorization p = 0 := by
  induction' n with n hn; · simp
  

Proof state:
case succ
p n✝ k n : ℕ
hn : n < p → (factorization n !) p = 0
h : succ n < p
⊢ (factorization (succ n)!) p = 0

Next tactic:
rw [factorial_succ, factorization_mul n.succ_ne_zero n.factorial_ne_zero, Finsupp.coe_add,
    Pi.add_apply, hn (lt_of_succ_lt h), add_zero, factorization_eq_zero_of_lt h]
theorem factorization_choose_eq_zero_of_lt (h : n < p) : (choose n k).factorization p = 0 := by
  

Proof state:
p n k : ℕ
h : n < p
⊢ (factorization (choose n k)) p = 0

Next tactic:
by_cases hnk : n < k
theorem factorization_choose_eq_zero_of_lt (h : n < p) : (choose n k).factorization p = 0 := by
  by_cases hnk : n < k; · 

Proof state:
case pos
p n k : ℕ
h : n < p
hnk : n < k
⊢ (factorization (choose n k)) p = 0

Next tactic:
simp [choose_eq_zero_of_lt hnk]
theorem factorization_choose_eq_zero_of_lt (h : n < p) : (choose n k).factorization p = 0 := by
  by_cases hnk : n < k; · simp [choose_eq_zero_of_lt hnk]
  

Proof state:
case neg
p n k : ℕ
h : n < p
hnk : ¬n < k
⊢ (factorization (choose n k)) p = 0

Next tactic:
rw [choose_eq_factorial_div_factorial (le_of_not_lt hnk),
    factorization_div (factorial_mul_factorial_dvd_factorial (le_of_not_lt hnk)), Finsupp.coe_tsub,
    Pi.sub_apply, factorization_factorial_eq_zero_of_lt h, zero_tsub]
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
⊢ ∏ p in Finset.range (n + 1), p ^ (factorization (choose n k)) p = choose n k

Next tactic:
conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
| ∏ p in Finset.range (n + 1), p ^ (factorization (choose n k)) p = choose n k

Next tactic:
rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
| ∏ p in Finset.range (n + 1), p ^ (factorization (choose n k)) p = choose n k

Next tactic:
rhs
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
| choose n k

Next tactic:
rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
⊢ ∏ p in Finset.range (n + 1), p ^ (factorization (choose n k)) p =
    Finsupp.prod (factorization (choose n k)) fun x x_1 => x ^ x_1

Next tactic:
rw [eq_comm]
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  

Proof state:
p n✝ k✝ n k : ℕ
hkn : k ≤ n
⊢ (Finsupp.prod (factorization (choose n k)) fun x x_1 => x ^ x_1) =
    ∏ p in Finset.range (n + 1), p ^ (factorization (choose n k)) p

Next tactic:
apply Finset.prod_subset
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · 

Proof state:
case h
p n✝ k✝ n k : ℕ
hkn : k ≤ n
⊢ (factorization (choose n k)).support ⊆ Finset.range (n + 1)

Next tactic:
intro p hp
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · intro p hp
    

Proof state:
case h
p✝ n✝ k✝ n k : ℕ
hkn : k ≤ n
p : ℕ
hp : p ∈ (factorization (choose n k)).support
⊢ p ∈ Finset.range (n + 1)

Next tactic:
rw [Finset.mem_range]
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · intro p hp
    rw [Finset.mem_range]
    

Proof state:
case h
p✝ n✝ k✝ n k : ℕ
hkn : k ≤ n
p : ℕ
hp : p ∈ (factorization (choose n k)).support
⊢ p < n + 1

Next tactic:
contrapose! hp
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · intro p hp
    rw [Finset.mem_range]
    contrapose! hp
    

Proof state:
case h
p✝ n✝ k✝ n k : ℕ
hkn : k ≤ n
p : ℕ
hp : n + 1 ≤ p
⊢ p ∉ (factorization (choose n k)).support

Next tactic:
rw [Finsupp.mem_support_iff, Classical.not_not, factorization_choose_eq_zero_of_lt hp]
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · intro p hp
    rw [Finset.mem_range]
    contrapose! hp
    rw [Finsupp.mem_support_iff, Classical.not_not, factorization_choose_eq_zero_of_lt hp]
  · 

Proof state:
case hf
p n✝ k✝ n k : ℕ
hkn : k ≤ n
⊢ ∀ x ∈ Finset.range (n + 1),
    x ∉ (factorization (choose n k)).support → (fun x x_1 => x ^ x_1) x ((factorization (choose n k)) x) = 1

Next tactic:
intro p _ h2
/-- A binomial coefficient is the product of its prime factors, which are at most `n`. -/
theorem prod_pow_factorization_choose (n k : ℕ) (hkn : k ≤ n) :
    (∏ p in Finset.range (n + 1), p ^ (Nat.choose n k).factorization p) = choose n k := by
  conv => -- Porting note: was `nth_rw_rhs`
    rhs
    rw [← factorization_prod_pow_eq_self (choose_pos hkn).ne']
  rw [eq_comm]
  apply Finset.prod_subset
  · intro p hp
    rw [Finset.mem_range]
    contrapose! hp
    rw [Finsupp.mem_support_iff, Classical.not_not, factorization_choose_eq_zero_of_lt hp]
  · intro p _ h2
    

Proof state:
case hf
p✝ n✝ k✝ n k : ℕ
hkn : k ≤ n
p : ℕ
a✝ : p ∈ Finset.range (n + 1)
h2 : p ∉ (factorization (choose n k)).support
⊢ (fun x x_1 => x ^ x_1) p ((factorization (choose n k)) p) = 1

Next tactic:
simp [Classical.not_not.1 (mt Finsupp.mem_support_iff.2 h2)]
/-- The `n`th central binomial coefficient is the product of its prime factors, which are
at most `2n`. -/
theorem prod_pow_factorization_centralBinom (n : ℕ) :
    (∏ p in Finset.range (2 * n + 1), p ^ (centralBinom n).factorization p) = centralBinom n := by
  

Proof state:
p n✝ k n : ℕ
⊢ ∏ p in Finset.range (2 * n + 1), p ^ (factorization (centralBinom n)) p = centralBinom n

Next tactic:
apply prod_pow_factorization_choose
/-- The `n`th central binomial coefficient is the product of its prime factors, which are
at most `2n`. -/
theorem prod_pow_factorization_centralBinom (n : ℕ) :
    (∏ p in Finset.range (2 * n + 1), p ^ (centralBinom n).factorization p) = centralBinom n := by
  apply prod_pow_factorization_choose
  

Proof state:
case hkn
p n✝ k n : ℕ
⊢ n ≤ 2 * n

Next tactic:
linarith
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ S) : l.prod ∈ S := by
  

Proof state:
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
l : List M
hl : ∀ x ∈ l, x ∈ S
⊢ List.prod l ∈ S

Next tactic:
lift l to List S using hl
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ S) : l.prod ∈ S := by
  lift l to List S using hl
  

Proof state:
case intro
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
l : List ↥S
⊢ List.prod (List.map Subtype.val l) ∈ S

Next tactic:
rw [← coe_list_prod]
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ S) : l.prod ∈ S := by
  lift l to List S using hl
  rw [← coe_list_prod]
  

Proof state:
case intro
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
l : List ↥S
⊢ ↑(List.prod l) ∈ S

Next tactic:
exact l.prod.coe_prop
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] [SetLike B M] [SubmonoidClass B M] (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  

Proof state:
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝⁵ : Monoid M✝
inst✝⁴ : SetLike B M✝
inst✝³ : SubmonoidClass B M✝
S : B
M : Type u_4
inst✝² : CommMonoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
m : Multiset M
hm : ∀ a ∈ m, a ∈ S
⊢ Multiset.prod m ∈ S

Next tactic:
lift m to Multiset S using hm
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] [SetLike B M] [SubmonoidClass B M] (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  lift m to Multiset S using hm
  

Proof state:
case intro
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝⁵ : Monoid M✝
inst✝⁴ : SetLike B M✝
inst✝³ : SubmonoidClass B M✝
S : B
M : Type u_4
inst✝² : CommMonoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
m : Multiset ↥S
⊢ Multiset.prod (Multiset.map Subtype.val m) ∈ S

Next tactic:
rw [← coe_multiset_prod]
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] [SetLike B M] [SubmonoidClass B M] (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  lift m to Multiset S using hm
  rw [← coe_multiset_prod]
  

Proof state:
case intro
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝⁵ : Monoid M✝
inst✝⁴ : SetLike B M✝
inst✝³ : SubmonoidClass B M✝
S : B
M : Type u_4
inst✝² : CommMonoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
m : Multiset ↥S
⊢ ↑(Multiset.prod m) ∈ S

Next tactic:
exact m.prod.coe_prop
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ s) : l.prod ∈ s := by
  

Proof state:
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
s : Submonoid M
l : List M
hl : ∀ x ∈ l, x ∈ s
⊢ List.prod l ∈ s

Next tactic:
lift l to List s using hl
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ s) : l.prod ∈ s := by
  lift l to List s using hl
  

Proof state:
case intro
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
s : Submonoid M
l : List ↥s
⊢ List.prod (List.map Subtype.val l) ∈ s

Next tactic:
rw [← coe_list_prod]
/-- Product of a list of elements in a submonoid is in the submonoid. -/
@[to_additive "Sum of a list of elements in an `AddSubmonoid` is in the `AddSubmonoid`."]
theorem list_prod_mem {l : List M} (hl : ∀ x ∈ l, x ∈ s) : l.prod ∈ s := by
  lift l to List s using hl
  rw [← coe_list_prod]
  

Proof state:
case intro
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S : B
s : Submonoid M
l : List ↥s
⊢ ↑(List.prod l) ∈ s

Next tactic:
exact l.prod.coe_prop
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] (S : Submonoid M) (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  

Proof state:
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝³ : Monoid M✝
inst✝² : SetLike B M✝
inst✝¹ : SubmonoidClass B M✝
S✝ : B
s : Submonoid M✝
M : Type u_4
inst✝ : CommMonoid M
S : Submonoid M
m : Multiset M
hm : ∀ a ∈ m, a ∈ S
⊢ Multiset.prod m ∈ S

Next tactic:
lift m to Multiset S using hm
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] (S : Submonoid M) (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  lift m to Multiset S using hm
  

Proof state:
case intro
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝³ : Monoid M✝
inst✝² : SetLike B M✝
inst✝¹ : SubmonoidClass B M✝
S✝ : B
s : Submonoid M✝
M : Type u_4
inst✝ : CommMonoid M
S : Submonoid M
m : Multiset ↥S
⊢ Multiset.prod (Multiset.map Subtype.val m) ∈ S

Next tactic:
rw [← coe_multiset_prod]
/-- Product of a multiset of elements in a submonoid of a `CommMonoid` is in the submonoid. -/
@[to_additive
      "Sum of a multiset of elements in an `AddSubmonoid` of an `AddCommMonoid` is
      in the `AddSubmonoid`."]
theorem multiset_prod_mem {M} [CommMonoid M] (S : Submonoid M) (m : Multiset M)
    (hm : ∀ a ∈ m, a ∈ S) : m.prod ∈ S := by
  lift m to Multiset S using hm
  rw [← coe_multiset_prod]
  

Proof state:
case intro
M✝ : Type u_1
A : Type u_2
B : Type u_3
inst✝³ : Monoid M✝
inst✝² : SetLike B M✝
inst✝¹ : SubmonoidClass B M✝
S✝ : B
s : Submonoid M✝
M : Type u_4
inst✝ : CommMonoid M
S : Submonoid M
m : Multiset ↥S
⊢ ↑(Multiset.prod m) ∈ S

Next tactic:
exact m.prod.coe_prop
@[to_additive]
theorem multiset_noncommProd_mem (S : Submonoid M) (m : Multiset M) (comm) (h : ∀ x ∈ m, x ∈ S) :
    m.noncommProd comm ∈ S := by
  

Proof state:
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S✝ : B
s S : Submonoid M
m : Multiset M
comm : Set.Pairwise {x | x ∈ m} Commute
h : ∀ x ∈ m, x ∈ S
⊢ Multiset.noncommProd m comm ∈ S

Next tactic:
induction' m using Quotient.inductionOn with l
@[to_additive]
theorem multiset_noncommProd_mem (S : Submonoid M) (m : Multiset M) (comm) (h : ∀ x ∈ m, x ∈ S) :
    m.noncommProd comm ∈ S := by
  induction' m using Quotient.inductionOn with l
  

Proof state:
case h
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S✝ : B
s S : Submonoid M
l : List M
comm : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
h : ∀ x ∈ ⟦l⟧, x ∈ S
⊢ Multiset.noncommProd ⟦l⟧ comm ∈ S

Next tactic:
simp only [Multiset.quot_mk_to_coe, Multiset.noncommProd_coe]
@[to_additive]
theorem multiset_noncommProd_mem (S : Submonoid M) (m : Multiset M) (comm) (h : ∀ x ∈ m, x ∈ S) :
    m.noncommProd comm ∈ S := by
  induction' m using Quotient.inductionOn with l
  simp only [Multiset.quot_mk_to_coe, Multiset.noncommProd_coe]
  

Proof state:
case h
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S✝ : B
s S : Submonoid M
l : List M
comm : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
h : ∀ x ∈ ⟦l⟧, x ∈ S
⊢ List.prod l ∈ S

Next tactic:
exact Submonoid.list_prod_mem _ h
@[to_additive]
theorem noncommProd_mem (S : Submonoid M) {ι : Type*} (t : Finset ι) (f : ι → M) (comm)
    (h : ∀ c ∈ t, f c ∈ S) : t.noncommProd f comm ∈ S := by
  

Proof state:
M : Type u_1
A : Type u_2
B : Type u_3
inst✝² : Monoid M
inst✝¹ : SetLike B M
inst✝ : SubmonoidClass B M
S✝ : B
s S : Submonoid M
ι : Type u_4
t : Finset ι
f : ι → M
comm : Set.Pairwise ↑t fun a b => Commute (f a) (f b)
h : ∀ c ∈ t, f c ∈ S
⊢ Finset.noncommProd t f comm ∈ S

Next tactic:
apply multiset_noncommProd_mem