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

tactic: let s : ℕ → ℝ := fun n => ∑ k ∈ Finset.range n, (-1 : ℝ) ^ k / k.factorial
state_before: ⊢ Tendsto (fun n => ↑(numDerangements n) / ↑n.factorial) atTop (𝓝 (Real.exp (-1)))
state_after: s : ℕ → ℝ := fun n => ∑ k ∈ Finset.range n, (-1) ^ k / ↑k.factorial
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑n.factorial) 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 ∈ 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 ∈ Finset.range n, (-1) ^ k / ↑k.factorial
⊢ Tendsto (fun n => ↑(numDerangements n) / ↑n.factorial) atTop (𝓝 (Real.exp (-1)))
state_after: s : ℕ → ℝ := fun n => ∑ k ∈ Finset.range n, (-1) ^ k / ↑k.factorial
⊢ ∀ (n : ℕ), ↑(numDerangements n) / ↑n.factorial = s (n + 1)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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