l3lab/ntp-mathlib huggingface dataset:
/-- For all positive bases, there exist infinite **Fermat pseudoprimes** to that base.
Given in this form: for all numbers `b ≥ 1` and `m`, there exists a pseudoprime `n` to base `b` such
that `m ≤ n`. This form is similar to `Nat.exists_infinite_primes`.
-/
theorem exists_infinite_pseudoprimes {b : ℕ} (h : 1 ≤ b) (m : ℕ) :
    ∃ n : ℕ, FermatPsp n b ∧ m ≤ n := by
  by_cases b_ge_two : 2 ≤ b
  -- If `2 ≤ b`, then because there exist infinite prime numbers, there is a prime number p with
  -- `m ≤ p` and `¬p ∣ b*(b^2 - 1)`. We pick a prime number `b*(b^2 - 1) + 1 + m ≤ p` because we
  -- automatically know that `p` is greater than m and that it does not divide `b*(b^2 - 1)`
  -- (because `p` can't divide a number less than `p`).
  -- From `p`, we can use the lemmas we proved earlier to show that
  -- `((b^p - 1)/(b - 1)) * ((b^p + 1)/(b + 1))` is a pseudoprime to base `b`.
  · have h := Nat.exists_infinite_primes (b * (b ^ 2 - 1) + 1 + m)
    cases' h with p hp
    cases' hp with hp₁ hp₂
    have h₁ : 0 < b := pos_of_gt (Nat.succ_le_iff.mp b_ge_two)
    have h₂ : 4 ≤ b ^ 2 := pow_le_pow_left' b_ge_two 2
    have h₃ : 0 < b ^ 2 - 1 := tsub_pos_of_lt (gt_of_ge_of_gt h₂ (by norm_num))
    have h₄ : 0 < b * (b ^ 2 - 1) := mul_pos h₁ h₃
    have h₅ : b * (b ^ 2 - 1) < p := by linarith
    have h₆ : ¬p ∣ b * (b ^ 2 - 1) := Nat.not_dvd_of_pos_of_lt h₄ h₅
    have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right h₃
    have h₈ : 2 ≤ b * (b ^ 2 - 1) := le_trans b_ge_two h₇
    have h₉ : 2 < p := gt_of_gt_of_ge h₅ h₈
    have h₁₀ := psp_from_prime_gt_p b_ge_two hp₂ h₉
    use psp_from_prime b p
    constructor
    · exact psp_from_prime_psp b_ge_two hp₂ h₉ h₆
    · exact le_trans (show m ≤ p by linarith) (le_of_lt h₁₀)
  -- If `¬2 ≤ b`, then `b = 1`. Since all composite numbers are pseudoprimes to base 1, we can pick
  -- any composite number greater than m. We choose `2 * (m + 2)` because it is greater than `m` and
  -- is composite for all natural numbers `m`.
  · have h₁ : b = 1 := by linarith
    rw [h₁]
    use 2 * (m + 2)
    have : ¬Nat.Prime (2 * (m + 2)) := Nat.not_prime_mul (by norm_num) (by norm_num)
    

Proof state:
case h
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ FermatPsp (2 * (m + 2)) 1 ∧ m ≤ 2 * (m + 2)

Next tactic:
exact ⟨fermatPsp_base_one (by linarith) this, by linarith⟩
/-- For all positive bases, there exist infinite **Fermat pseudoprimes** to that base.
Given in this form: for all numbers `b ≥ 1` and `m`, there exists a pseudoprime `n` to base `b` such
that `m ≤ n`. This form is similar to `Nat.exists_infinite_primes`.
-/
theorem exists_infinite_pseudoprimes {b : ℕ} (h : 1 ≤ b) (m : ℕ) :
    ∃ n : ℕ, FermatPsp n b ∧ m ≤ n := by
  by_cases b_ge_two : 2 ≤ b
  -- If `2 ≤ b`, then because there exist infinite prime numbers, there is a prime number p with
  -- `m ≤ p` and `¬p ∣ b*(b^2 - 1)`. We pick a prime number `b*(b^2 - 1) + 1 + m ≤ p` because we
  -- automatically know that `p` is greater than m and that it does not divide `b*(b^2 - 1)`
  -- (because `p` can't divide a number less than `p`).
  -- From `p`, we can use the lemmas we proved earlier to show that
  -- `((b^p - 1)/(b - 1)) * ((b^p + 1)/(b + 1))` is a pseudoprime to base `b`.
  · have h := Nat.exists_infinite_primes (b * (b ^ 2 - 1) + 1 + m)
    cases' h with p hp
    cases' hp with hp₁ hp₂
    have h₁ : 0 < b := pos_of_gt (Nat.succ_le_iff.mp b_ge_two)
    have h₂ : 4 ≤ b ^ 2 := pow_le_pow_left' b_ge_two 2
    have h₃ : 0 < b ^ 2 - 1 := tsub_pos_of_lt (gt_of_ge_of_gt h₂ (by norm_num))
    have h₄ : 0 < b * (b ^ 2 - 1) := mul_pos h₁ h₃
    have h₅ : b * (b ^ 2 - 1) < p := by linarith
    have h₆ : ¬p ∣ b * (b ^ 2 - 1) := Nat.not_dvd_of_pos_of_lt h₄ h₅
    have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right h₃
    have h₈ : 2 ≤ b * (b ^ 2 - 1) := le_trans b_ge_two h₇
    have h₉ : 2 < p := gt_of_gt_of_ge h₅ h₈
    have h₁₀ := psp_from_prime_gt_p b_ge_two hp₂ h₉
    use psp_from_prime b p
    constructor
    · exact psp_from_prime_psp b_ge_two hp₂ h₉ h₆
    · exact le_trans (show m ≤ p by linarith) (le_of_lt h₁₀)
  -- If `¬2 ≤ b`, then `b = 1`. Since all composite numbers are pseudoprimes to base 1, we can pick
  -- any composite number greater than m. We choose `2 * (m + 2)` because it is greater than `m` and
  -- is composite for all natural numbers `m`.
  · have h₁ : b = 1 := by linarith
    rw [h₁]
    use 2 * (m + 2)
    have : ¬Nat.Prime (2 * (m + 2)) := Nat.not_prime_mul (by norm_num) (by norm_num)
    exact ⟨fermatPsp_base_one (by 

Proof state:
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ 1 < 2 * (m + 2)

Next tactic:
linarith
/-- For all positive bases, there exist infinite **Fermat pseudoprimes** to that base.
Given in this form: for all numbers `b ≥ 1` and `m`, there exists a pseudoprime `n` to base `b` such
that `m ≤ n`. This form is similar to `Nat.exists_infinite_primes`.
-/
theorem exists_infinite_pseudoprimes {b : ℕ} (h : 1 ≤ b) (m : ℕ) :
    ∃ n : ℕ, FermatPsp n b ∧ m ≤ n := by
  by_cases b_ge_two : 2 ≤ b
  -- If `2 ≤ b`, then because there exist infinite prime numbers, there is a prime number p with
  -- `m ≤ p` and `¬p ∣ b*(b^2 - 1)`. We pick a prime number `b*(b^2 - 1) + 1 + m ≤ p` because we
  -- automatically know that `p` is greater than m and that it does not divide `b*(b^2 - 1)`
  -- (because `p` can't divide a number less than `p`).
  -- From `p`, we can use the lemmas we proved earlier to show that
  -- `((b^p - 1)/(b - 1)) * ((b^p + 1)/(b + 1))` is a pseudoprime to base `b`.
  · have h := Nat.exists_infinite_primes (b * (b ^ 2 - 1) + 1 + m)
    cases' h with p hp
    cases' hp with hp₁ hp₂
    have h₁ : 0 < b := pos_of_gt (Nat.succ_le_iff.mp b_ge_two)
    have h₂ : 4 ≤ b ^ 2 := pow_le_pow_left' b_ge_two 2
    have h₃ : 0 < b ^ 2 - 1 := tsub_pos_of_lt (gt_of_ge_of_gt h₂ (by norm_num))
    have h₄ : 0 < b * (b ^ 2 - 1) := mul_pos h₁ h₃
    have h₅ : b * (b ^ 2 - 1) < p := by linarith
    have h₆ : ¬p ∣ b * (b ^ 2 - 1) := Nat.not_dvd_of_pos_of_lt h₄ h₅
    have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right h₃
    have h₈ : 2 ≤ b * (b ^ 2 - 1) := le_trans b_ge_two h₇
    have h₉ : 2 < p := gt_of_gt_of_ge h₅ h₈
    have h₁₀ := psp_from_prime_gt_p b_ge_two hp₂ h₉
    use psp_from_prime b p
    constructor
    · exact psp_from_prime_psp b_ge_two hp₂ h₉ h₆
    · exact le_trans (show m ≤ p by linarith) (le_of_lt h₁₀)
  -- If `¬2 ≤ b`, then `b = 1`. Since all composite numbers are pseudoprimes to base 1, we can pick
  -- any composite number greater than m. We choose `2 * (m + 2)` because it is greater than `m` and
  -- is composite for all natural numbers `m`.
  · have h₁ : b = 1 := by linarith
    rw [h₁]
    use 2 * (m + 2)
    have : ¬Nat.Prime (2 * (m + 2)) := Nat.not_prime_mul (by norm_num) (by norm_num)
    exact ⟨fermatPsp_base_one (by linarith) this, by 

Proof state:
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ m ≤ 2 * (m + 2)

Next tactic:
linarith
theorem frequently_atTop_fermatPsp {b : ℕ} (h : 1 ≤ b) : ∃ᶠ n in Filter.atTop, FermatPsp n b := by
  -- Based on the proof of `Nat.frequently_atTop_modEq_one`
  

Proof state:
b : ℕ
h : 1 ≤ b
⊢ ∃ᶠ (n : ℕ) in Filter.atTop, FermatPsp n b

Next tactic:
refine' Filter.frequently_atTop.2 fun n => _
theorem frequently_atTop_fermatPsp {b : ℕ} (h : 1 ≤ b) : ∃ᶠ n in Filter.atTop, FermatPsp n b := by
  -- Based on the proof of `Nat.frequently_atTop_modEq_one`
  refine' Filter.frequently_atTop.2 fun n => _
  

Proof state:
b : ℕ
h : 1 ≤ b
n : ℕ
⊢ ∃ b_1 ≥ n, FermatPsp b_1 b

Next tactic:
obtain ⟨p, hp⟩ := exists_infinite_pseudoprimes h n
theorem frequently_atTop_fermatPsp {b : ℕ} (h : 1 ≤ b) : ∃ᶠ n in Filter.atTop, FermatPsp n b := by
  -- Based on the proof of `Nat.frequently_atTop_modEq_one`
  refine' Filter.frequently_atTop.2 fun n => _
  obtain ⟨p, hp⟩ := exists_infinite_pseudoprimes h n
  

Proof state:
case intro
b : ℕ
h : 1 ≤ b
n p : ℕ
hp : FermatPsp p b ∧ n ≤ p
⊢ ∃ b_1 ≥ n, FermatPsp b_1 b

Next tactic:
exact ⟨p, hp.2, hp.1⟩
/-- The recursion `hermite (n+1) = (x - d/dx) (hermite n)` -/
@[simp]
theorem hermite_succ (n : ℕ) : hermite (n + 1) = X * hermite n - derivative (hermite n) := by
  

Proof state:
n : ℕ
⊢ hermite (n + 1) = X * hermite n - derivative (hermite n)

Next tactic:
rw [hermite]
theorem hermite_eq_iterate (n : ℕ) : hermite n = (fun p => X * p - derivative p)^[n] 1 := by
  

Proof state:
n : ℕ
⊢ hermite n = (fun p => X * p - derivative p)^[n] 1

Next tactic:
induction' n with n ih
theorem hermite_eq_iterate (n : ℕ) : hermite n = (fun p => X * p - derivative p)^[n] 1 := by
  induction' n with n ih
  · 

Proof state:
case zero
⊢ hermite Nat.zero = (fun p => X * p - derivative p)^[Nat.zero] 1

Next tactic:
rfl
theorem hermite_eq_iterate (n : ℕ) : hermite n = (fun p => X * p - derivative p)^[n] 1 := by
  induction' n with n ih
  · rfl
  · 

Proof state:
case succ
n : ℕ
ih : hermite n = (fun p => X * p - derivative p)^[n] 1
⊢ hermite (Nat.succ n) = (fun p => X * p - derivative p)^[Nat.succ n] 1

Next tactic:
rw [Function.iterate_succ_apply', ← ih, hermite_succ]
theorem hermite_one : hermite 1 = X := by
  

Proof state:
⊢ hermite 1 = X

Next tactic:
rw [hermite_succ, hermite_zero]
theorem hermite_one : hermite 1 = X := by
  rw [hermite_succ, hermite_zero]
  

Proof state:
⊢ X * C 1 - derivative (C 1) = X

Next tactic:
simp only [map_one, mul_one, derivative_one, sub_zero]
theorem coeff_hermite_succ_zero (n : ℕ) : coeff (hermite (n + 1)) 0 = -coeff (hermite n) 1 := by
  

Proof state:
n : ℕ
⊢ coeff (hermite (n + 1)) 0 = -coeff (hermite n) 1

Next tactic:
simp [coeff_derivative]
theorem coeff_hermite_succ_succ (n k : ℕ) : coeff (hermite (n + 1)) (k + 1) =
    coeff (hermite n) k - (k + 2) * coeff (hermite n) (k + 2) := by
  

Proof state:
n k : ℕ
⊢ coeff (hermite (n + 1)) (k + 1) = coeff (hermite n) k - (↑k + 2) * coeff (hermite n) (k + 2)

Next tactic:
rw [hermite_succ, coeff_sub, coeff_X_mul, coeff_derivative, mul_comm]
theorem coeff_hermite_succ_succ (n k : ℕ) : coeff (hermite (n + 1)) (k + 1) =
    coeff (hermite n) k - (k + 2) * coeff (hermite n) (k + 2) := by
  rw [hermite_succ, coeff_sub, coeff_X_mul, coeff_derivative, mul_comm]
  

Proof state:
n k : ℕ
⊢ coeff (hermite n) k - (↑(k + 1) + 1) * coeff (hermite n) (k + 1 + 1) =
    coeff (hermite n) k - (↑k + 2) * coeff (hermite n) (k + 2)

Next tactic:
norm_cast
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  

Proof state:
n k : ℕ
hnk : n < k
⊢ coeff (hermite n) k = 0

Next tactic:
obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  

Proof state:
case intro
n k : ℕ
hnk : n < n + k + 1
⊢ coeff (hermite n) (n + k + 1) = 0

Next tactic:
clear hnk
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  clear hnk
  

Proof state:
case intro
n k : ℕ
⊢ coeff (hermite n) (n + k + 1) = 0

Next tactic:
induction' n with n ih generalizing k
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  clear hnk
  induction' n with n ih generalizing k
  · 

Proof state:
case intro.zero
k : ℕ
⊢ coeff (hermite Nat.zero) (Nat.zero + k + 1) = 0

Next tactic:
apply coeff_C
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  clear hnk
  induction' n with n ih generalizing k
  · apply coeff_C
  · 

Proof state:
case intro.succ
n : ℕ
ih : ∀ (k : ℕ), coeff (hermite n) (n + k + 1) = 0
k : ℕ
⊢ coeff (hermite (Nat.succ n)) (Nat.succ n + k + 1) = 0

Next tactic:
have : n + k + 1 + 2 = n + (k + 2) + 1 := by ring
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  clear hnk
  induction' n with n ih generalizing k
  · apply coeff_C
  · have : n + k + 1 + 2 = n + (k + 2) + 1 := by 

Proof state:
n : ℕ
ih : ∀ (k : ℕ), coeff (hermite n) (n + k + 1) = 0
k : ℕ
⊢ n + k + 1 + 2 = n + (k + 2) + 1

Next tactic:
ring
theorem coeff_hermite_of_lt {n k : ℕ} (hnk : n < k) : coeff (hermite n) k = 0 := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt hnk
  clear hnk
  induction' n with n ih generalizing k
  · apply coeff_C
  · have : n + k + 1 + 2 = n + (k + 2) + 1 := by ring
    

Proof state:
case intro.succ
n : ℕ
ih : ∀ (k : ℕ), coeff (hermite n) (n + k + 1) = 0
k : ℕ
this : n + k + 1 + 2 = n + (k + 2) + 1
⊢ coeff (hermite (Nat.succ n)) (Nat.succ n + k + 1) = 0

Next tactic:
rw [Nat.succ_eq_add_one, coeff_hermite_succ_succ, add_right_comm, this, ih k, ih (k + 2),
      mul_zero, sub_zero]
@[simp]
theorem coeff_hermite_self (n : ℕ) : coeff (hermite n) n = 1 := by
  

Proof state:
n : ℕ
⊢ coeff (hermite n) n = 1

Next tactic:
induction' n with n ih
@[simp]
theorem coeff_hermite_self (n : ℕ) : coeff (hermite n) n = 1 := by
  induction' n with n ih
  · 

Proof state:
case zero
⊢ coeff (hermite Nat.zero) Nat.zero = 1

Next tactic:
apply coeff_C
@[simp]
theorem coeff_hermite_self (n : ℕ) : coeff (hermite n) n = 1 := by
  induction' n with n ih
  · apply coeff_C
  · 

Proof state:
case succ
n : ℕ
ih : coeff (hermite n) n = 1
⊢ coeff (hermite (Nat.succ n)) (Nat.succ n) = 1

Next tactic:
rw [coeff_hermite_succ_succ, ih, coeff_hermite_of_lt, mul_zero, sub_zero]
@[simp]
theorem coeff_hermite_self (n : ℕ) : coeff (hermite n) n = 1 := by
  induction' n with n ih
  · apply coeff_C
  · rw [coeff_hermite_succ_succ, ih, coeff_hermite_of_lt, mul_zero, sub_zero]
    

Proof state:
case succ
n : ℕ
ih : coeff (hermite n) n = 1
⊢ n < n + 2

Next tactic:
simp
@[simp]
theorem degree_hermite (n : ℕ) : (hermite n).degree = n := by
  

Proof state:
n : ℕ
⊢ degree (hermite n) = ↑n

Next tactic:
rw [degree_eq_of_le_of_coeff_ne_zero]
@[simp]
theorem degree_hermite (n : ℕ) : (hermite n).degree = n := by
  rw [degree_eq_of_le_of_coeff_ne_zero]
  

Proof state:
case pn
n : ℕ
⊢ degree (hermite n) ≤ ↑n
case p1 n : ℕ ⊢ coeff (hermite n) n ≠ 0

Next tactic:
simp_rw [degree_le_iff_coeff_zero, Nat.cast_lt]
@[simp]
theorem degree_hermite (n : ℕ) : (hermite n).degree = n := by
  rw [degree_eq_of_le_of_coeff_ne_zero]
  simp_rw [degree_le_iff_coeff_zero, Nat.cast_lt]
  · 

Proof state:
case pn
n : ℕ
⊢ ∀ (m : ℕ), n < m → coeff (hermite n) m = 0

Next tactic:
rintro m hnm
@[simp]
theorem degree_hermite (n : ℕ) : (hermite n).degree = n := by
  rw [degree_eq_of_le_of_coeff_ne_zero]
  simp_rw [degree_le_iff_coeff_zero, Nat.cast_lt]
  · rintro m hnm
    

Proof state:
case pn
n m : ℕ
hnm : n < m
⊢ coeff (hermite n) m = 0

Next tactic:
exact coeff_hermite_of_lt hnm
@[simp]
theorem degree_hermite (n : ℕ) : (hermite n).degree = n := by
  rw [degree_eq_of_le_of_coeff_ne_zero]
  simp_rw [degree_le_iff_coeff_zero, Nat.cast_lt]
  · rintro m hnm
    exact coeff_hermite_of_lt hnm
  · 

Proof state:
case p1
n : ℕ
⊢ coeff (hermite n) n ≠ 0

Next tactic:
simp [coeff_hermite_self n]
@[simp]
theorem leadingCoeff_hermite (n : ℕ) : (hermite n).leadingCoeff = 1 := by
  

Proof state:
n : ℕ
⊢ leadingCoeff (hermite n) = 1

Next tactic:
rw [← coeff_natDegree, natDegree_hermite, coeff_hermite_self]
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  

Proof state:
n k : ℕ
hnk : Odd (n + k)
⊢ coeff (hermite n) k = 0

Next tactic:
induction' n with n ih generalizing k
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · 

Proof state:
case zero
k : ℕ
hnk : Odd (Nat.zero + k)
⊢ coeff (hermite Nat.zero) k = 0

Next tactic:
rw [Nat.zero_eq, zero_add k] at hnk
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    

Proof state:
case zero
k : ℕ
hnk : Odd k
⊢ coeff (hermite Nat.zero) k = 0

Next tactic:
exact coeff_hermite_of_lt hnk.pos
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · 

Proof state:
case succ
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (Nat.succ n + k)
⊢ coeff (hermite (Nat.succ n)) k = 0

Next tactic:
cases' k with k
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · 

Proof state:
case succ.zero
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
hnk : Odd (Nat.succ n + Nat.zero)
⊢ coeff (hermite (Nat.succ n)) Nat.zero = 0

Next tactic:
rw [Nat.succ_add_eq_add_succ] at hnk
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      

Proof state:
case succ.zero
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
hnk : Odd (n + Nat.succ Nat.zero)
⊢ coeff (hermite (Nat.succ n)) Nat.zero = 0

Next tactic:
rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
    · 

Proof state:
case succ.succ
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (Nat.succ n + Nat.succ k)
⊢ coeff (hermite (Nat.succ n)) (Nat.succ k) = 0

Next tactic:
rw [coeff_hermite_succ_succ, ih, ih, mul_zero, sub_zero]
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
    · rw [coeff_hermite_succ_succ, ih, ih, mul_zero, sub_zero]
      · 

Proof state:
case succ.succ
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (Nat.succ n + Nat.succ k)
⊢ Odd (n + (k + 2))

Next tactic:
rwa [Nat.succ_add_eq_add_succ] at hnk
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
    · rw [coeff_hermite_succ_succ, ih, ih, mul_zero, sub_zero]
      · rwa [Nat.succ_add_eq_add_succ] at hnk
      · 

Proof state:
case succ.succ
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (Nat.succ n + Nat.succ k)
⊢ Odd (n + k)

Next tactic:
rw [(by rw [Nat.succ_add, Nat.add_succ] : n.succ + k.succ = n + k + 2)] at hnk
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
    · rw [coeff_hermite_succ_succ, ih, ih, mul_zero, sub_zero]
      · rwa [Nat.succ_add_eq_add_succ] at hnk
      · rw [(by 

Proof state:
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (Nat.succ n + Nat.succ k)
⊢ Nat.succ n + Nat.succ k = n + k + 2

Next tactic:
rw [Nat.succ_add, Nat.add_succ]
theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by
  induction' n with n ih generalizing k
  · rw [Nat.zero_eq, zero_add k] at hnk
    exact coeff_hermite_of_lt hnk.pos
  · cases' k with k
    · rw [Nat.succ_add_eq_add_succ] at hnk
      rw [coeff_hermite_succ_zero, ih hnk, neg_zero]
    · rw [coeff_hermite_succ_succ, ih, ih, mul_zero, sub_zero]
      · rwa [Nat.succ_add_eq_add_succ] at hnk
      · rw [(by rw [Nat.succ_add, Nat.add_succ] : n.succ + k.succ = n + k + 2)] at hnk
        

Proof state:
case succ.succ
n : ℕ
ih : ∀ {k : ℕ}, Odd (n + k) → coeff (hermite n) k = 0
k : ℕ
hnk : Odd (n + k + 2)
⊢ Odd (n + k)

Next tactic:
exact (Nat.odd_add.mp hnk).mpr even_two
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by 

Proof state:
x✝ : ℕ
⊢ coeff (hermite (2 * 0 + x✝)) x✝ = (-1) ^ 0 * ↑(2 * 0 - 1)‼ * ↑(Nat.choose (2 * 0 + x✝) x✝)

Next tactic:
simp
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by simp
  | n + 1, 0 => by
    

Proof state:
n : ℕ
⊢ coeff (hermite (2 * (n + 1) + 0)) 0 = (-1) ^ (n + 1) * ↑(2 * (n + 1) - 1)‼ * ↑(Nat.choose (2 * (n + 1) + 0) 0)

Next tactic:
convert coeff_hermite_succ_zero (2 * n + 1) using 1
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by simp
  | n + 1, 0 => by
    convert coeff_hermite_succ_zero (2 * n + 1) using 1
    -- porting note: ring_nf did not solve the goal on line 165
    

Proof state:
case h.e'_3
n : ℕ
⊢ (-1) ^ (n + 1) * ↑(2 * (n + 1) - 1)‼ * ↑(Nat.choose (2 * (n + 1) + 0) 0) = -coeff (hermite (2 * n + 1)) 1

Next tactic:
rw [coeff_hermite_explicit n 1, (by rw [Nat.left_distrib, mul_one, Nat.add_one_sub_one] :
      2 * (n + 1) - 1 = 2 * n + 1), Nat.doubleFactorial_add_one, Nat.choose_zero_right,
      Nat.choose_one_right, pow_succ]
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by simp
  | n + 1, 0 => by
    convert coeff_hermite_succ_zero (2 * n + 1) using 1
    -- porting note: ring_nf did not solve the goal on line 165
    rw [coeff_hermite_explicit n 1, (by 

Proof state:
n : ℕ
⊢ 2 * (n + 1) - 1 = 2 * n + 1

Next tactic:
rw [Nat.left_distrib, mul_one, Nat.add_one_sub_one]
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by simp
  | n + 1, 0 => by
    convert coeff_hermite_succ_zero (2 * n + 1) using 1
    -- porting note: ring_nf did not solve the goal on line 165
    rw [coeff_hermite_explicit n 1, (by rw [Nat.left_distrib, mul_one, Nat.add_one_sub_one] :
      2 * (n + 1) - 1 = 2 * n + 1), Nat.doubleFactorial_add_one, Nat.choose_zero_right,
      Nat.choose_one_right, pow_succ]
    

Proof state:
case h.e'_3
n : ℕ
⊢ -1 * (-1) ^ n * ↑((2 * n + 1) * (2 * n - 1)‼) * ↑1 = -((-1) ^ n * ↑(2 * n - 1)‼ * ↑(2 * n + 1))

Next tactic:
push_cast
/-- Because of `coeff_hermite_of_odd_add`, every nonzero coefficient is described as follows. -/
theorem coeff_hermite_explicit :
    ∀ n k : ℕ, coeff (hermite (2 * n + k)) k = (-1) ^ n * (2 * n - 1)‼ * Nat.choose (2 * n + k) k
  | 0, _ => by simp
  | n + 1, 0 => by
    convert coeff_hermite_succ_zero (2 * n + 1) using 1
    -- porting note: ring_nf did not solve the goal on line 165
    rw [coeff_hermite_explicit n 1, (by rw [Nat.left_distrib, mul_one, Nat.add_one_sub_one] :
      2 * (n + 1) - 1 = 2 * n + 1), Nat.doubleFactorial_add_one, Nat.choose_zero_right,
      Nat.choose_one_right, pow_succ]
    push_cast
    

Proof state:
case h.e'_3
n : ℕ
⊢ -1 * (-1) ^ n * ((2 * ↑n + 1) * ↑(2 * n - 1)‼) * 1 = -((-1) ^ n * ↑(2 * n - 1)‼ * (2 * ↑n + 1))

Next tactic:
ring