l3lab/ntp-mathlib huggingface dataset:
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
⊢ centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3)

Next tactic:
have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
⊢ ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x

Next tactic:
refine' Finset.prod_filter_of_ne fun p _ h => _
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
p : ℕ
x✝ : p ∈ Finset.range (2 * n / 3 + 1)
h : f p ≠ 1
⊢ Nat.Prime p

Next tactic:
contrapose! h
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; 

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
p : ℕ
x✝ : p ∈ Finset.range (2 * n / 3 + 1)
h : ¬Nat.Prime p
⊢ f p = 1

Next tactic:
dsimp only
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
p : ℕ
x✝ : p ∈ Finset.range (2 * n / 3 + 1)
h : ¬Nat.Prime p
⊢ p ^ (Nat.factorization (centralBinom n)) p = 1

Next tactic:
rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
⊢ centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3)

Next tactic:
rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
⊢ (∏ x in Finset.filter (fun x => x ≤ sqrt (2 * n)) S, f x) * ∏ x in Finset.filter (fun x => ¬x ≤ sqrt (2 * n)) S, f x ≤
    (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3)

Next tactic:
apply mul_le_mul'
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · 

Proof state:
case h₁
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
⊢ ∏ x in Finset.filter (fun x => x ≤ sqrt (2 * n)) S, f x ≤ (2 * n) ^ sqrt (2 * n)

Next tactic:
refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
    · 

Proof state:
case h₁.refine'_1
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
p : ℕ
x✝ : p ∈ Finset.filter (fun x => x ≤ sqrt (2 * n)) S
⊢ f p ≤ 2 * n

Next tactic:
exact pow_factorization_choose_le (mul_pos two_pos n_pos)
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
    · exact pow_factorization_choose_le (mul_pos two_pos n_pos)
    

Proof state:
case h₁.refine'_2
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
⊢ ∏ i in Finset.filter (fun x => x ≤ sqrt (2 * n)) S, 2 * n ≤ (2 * n) ^ sqrt (2 * n)

Next tactic:
have : (Finset.Icc 1 (sqrt (2 * n))).card = sqrt (2 * n) := by rw [card_Icc, Nat.add_sub_cancel]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
    · exact pow_factorization_choose_le (mul_pos two_pos n_pos)
    have : (Finset.Icc 1 (sqrt (2 * n))).card = sqrt (2 * n) := by 

Proof state:
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
⊢ Finset.card (Finset.Icc 1 (sqrt (2 * n))) = sqrt (2 * n)

Next tactic:
rw [card_Icc, Nat.add_sub_cancel]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
    · exact pow_factorization_choose_le (mul_pos two_pos n_pos)
    have : (Finset.Icc 1 (sqrt (2 * n))).card = sqrt (2 * n) := by rw [card_Icc, Nat.add_sub_cancel]
    

Proof state:
case h₁.refine'_2
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this✝ : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
this : Finset.card (Finset.Icc 1 (sqrt (2 * n))) = sqrt (2 * n)
⊢ ∏ i in Finset.filter (fun x => x ≤ sqrt (2 * n)) S, 2 * n ≤ (2 * n) ^ sqrt (2 * n)

Next tactic:
rw [Finset.prod_const]
/-- An upper bound on the central binomial coefficient used in the proof of Bertrand's postulate.
The bound splits the prime factors of `centralBinom n` into those
1. At most `sqrt (2 * n)`, which contribute at most `2 * n` for each such prime.
2. Between `sqrt (2 * n)` and `2 * n / 3`, which contribute at most `4^(2 * n / 3)` in total.
3. Between `2 * n / 3` and `n`, which do not exist.
4. Between `n` and `2 * n`, which would not exist in the case where Bertrand's postulate is false.
5. Above `2 * n`, which do not exist.
-/
theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_big : 2 < n)
    (no_prime : ¬∃ p : ℕ, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n) :
    centralBinom n ≤ (2 * n) ^ sqrt (2 * n) * 4 ^ (2 * n / 3) := by
  have n_pos : 0 < n := (Nat.zero_le _).trans_lt n_big
  have n2_pos : 1 ≤ 2 * n := mul_pos (zero_lt_two' ℕ) n_pos
  let S := (Finset.range (2 * n / 3 + 1)).filter Nat.Prime
  let f x := x ^ n.centralBinom.factorization x
  have : ∏ x : ℕ in S, f x = ∏ x : ℕ in Finset.range (2 * n / 3 + 1), f x := by
    refine' Finset.prod_filter_of_ne fun p _ h => _
    contrapose! h; dsimp only
    rw [factorization_eq_zero_of_non_prime n.centralBinom h, _root_.pow_zero]
  rw [centralBinom_factorization_small n n_big no_prime, ← this, ←
    Finset.prod_filter_mul_prod_filter_not S (· ≤ sqrt (2 * n))]
  apply mul_le_mul'
  · refine' (Finset.prod_le_prod' fun p _ => (_ : f p ≤ 2 * n)).trans _
    · exact pow_factorization_choose_le (mul_pos two_pos n_pos)
    have : (Finset.Icc 1 (sqrt (2 * n))).card = sqrt (2 * n) := by rw [card_Icc, Nat.add_sub_cancel]
    rw [Finset.prod_const]
    

Proof state:
case h₁.refine'_2
n : ℕ
n_big : 2 < n
no_prime : ¬∃ p, Nat.Prime p ∧ n < p ∧ p ≤ 2 * n
n_pos : 0 < n
n2_pos : 1 ≤ 2 * n
S : Finset ℕ := Finset.filter Nat.Prime (Finset.range (2 * n / 3 + 1))
f : ℕ → ℕ := fun x => x ^ (Nat.factorization (centralBinom n)) x
this✝ : ∏ x in S, f x = ∏ x in Finset.range (2 * n / 3 + 1), f x
this : Finset.card (Finset.Icc 1 (sqrt (2 * n))) = sqrt (2 * n)
⊢ (2 * n) ^ Finset.card (Finset.filter (fun x => x ≤ sqrt (2 * n)) S) ≤ (2 * n) ^ sqrt (2 * n)

Next tactic:
refine' pow_le_pow_right n2_pos ((Finset.card_le_of_subset fun x hx => _).trans this.le)