Theorem: numDerangements_tendsto_inv_e
File: Mathlib/Combinatorics/Derangements/Exponential.lean

tactic: let s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial
state_before: ⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))

tactic: suffices ∀ n : ℕ, (numDerangements n : ℝ) / n.factorial = s (n + 1) by
  simp_rw [this]
  rw [tendsto_add_atTop_iff_nat
    (f := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial) 1]
  apply HasSum.tendsto_sum_nat
  rw [Real.exp_eq_exp_ℝ]
  exact expSeries_div_hasSum_exp ℝ (-1 : ℝ)
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))

tactic: intro n
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
⊢ ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)

tactic: rw [← Int.cast_ofNat, numDerangements_sum]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)

tactic: push_cast
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ↑(∑ k in Finset.range (n + 1), (-1) ^ k * ↑(Nat.ascFactorial k (n - k))) / ↑(Nat.factorial n) = s (n + 1)

tactic: rw [Finset.sum_div]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ (∑ x in Finset.range (n + 1), (-1) ^ x * ↑(Nat.ascFactorial x (n - x))) / ↑(Nat.factorial n) =
    ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)

tactic: refine' Finset.sum_congr (refl _) _
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ∑ x in Finset.range (n + 1), (-1) ^ x * ↑(Nat.ascFactorial x (n - x)) / ↑(Nat.factorial n) =
    ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)

tactic: intro k hk
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n : ℕ
⊢ ∀ (x : ℕ),
    x ∈ Finset.range (n + 1) →
      (-1) ^ x * ↑(Nat.ascFactorial x (n - x)) / ↑(Nat.factorial n) = (-1) ^ x / ↑(Nat.factorial x)

tactic: have h_le : k ≤ n := Finset.mem_range_succ_iff.mp hk
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
⊢ (-1) ^ k * ↑(Nat.ascFactorial k (n - k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)

tactic: rw [Nat.ascFactorial_eq_div, add_tsub_cancel_of_le h_le]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.ascFactorial k (n - k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)

tactic: push_cast [Nat.factorial_dvd_factorial h_le]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.factorial n / Nat.factorial k) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)

tactic: field_simp [Nat.factorial_ne_zero]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * (↑(Nat.factorial n) / ↑(Nat.factorial k)) / ↑(Nat.factorial n) = (-1) ^ k / ↑(Nat.factorial k)

tactic: ring
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
n k : ℕ
hk : k ∈ Finset.range (n + 1)
h_le : k ≤ n
⊢ (-1) ^ k * ↑(Nat.factorial n) * ↑(Nat.factorial k) = (-1) ^ k * (↑(Nat.factorial k) * ↑(Nat.factorial n))

tactic: simp_rw [this]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑(Nat.factorial n)) atTop (𝓝 (Real.exp (-1)))

tactic: rw [tendsto_add_atTop_iff_nat
  (f := fun n => ∑ k in Finset.range n, (-1 : ℝ) ^ k / k.factorial) 1]
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ∑ k in Finset.range (n + 1), (-1) ^ k / ↑(Nat.factorial k)) atTop (𝓝 (Real.exp (-1)))

tactic: apply HasSum.tendsto_sum_nat
state_before: s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ Tendsto (fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)) atTop (𝓝 (Real.exp (-1)))

tactic: rw [Real.exp_eq_exp_ℝ]
state_before: case h
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ HasSum (fun i => (-1) ^ i / ↑(Nat.factorial i)) (Real.exp (-1))

tactic: exact expSeries_div_hasSum_exp ℝ (-1 : ℝ)
state_before: case h
s : ℕ → ℝ := fun n => ∑ k in Finset.range n, (-1) ^ k / ↑(Nat.factorial k)
this : ∀ (n : ℕ), ↑(numDerangements n) / ↑(Nat.factorial n) = s (n + 1)
⊢ HasSum (fun i => (-1) ^ i / ↑(Nat.factorial i)) (exp ℝ (-1))