Theorem: Finset.card_eq_of_bijective
File: Mathlib/Data/Finset/Card.lean

tactic: classical
  have : ∀ a : α, a ∈ s ↔ ∃ (i : _)(hi : i ∈ range n), f i (mem_range.1 hi) = a := fun a =>
    ⟨fun ha =>
      let ⟨i, hi, eq⟩ := hf a ha
      ⟨i, mem_range.2 hi, eq⟩,
      fun ⟨i, hi, eq⟩ => eq ▸ hf' i (mem_range.1 hi)⟩
  have : s = (range n).attach.image fun i => f i.1 (mem_range.1 i.2) := by
    simpa only [ext_iff, mem_image, exists_prop, Subtype.exists, mem_attach, true_and_iff]
  calc
    s.card = card ((range n).attach.image fun i => f i.1 (mem_range.1 i.2)) := by rw [this]
    _ = card (range n).attach :=
      (card_image_of_injective _) fun ⟨i, hi⟩ ⟨j, hj⟩ eq =>
        Subtype.eq <| f_inj i j (mem_range.1 hi) (mem_range.1 hj) eq
    _ = card (range n) := card_attach
    _ = n := card_range n
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
⊢ card s = n

tactic: have : ∀ a : α, a ∈ s ↔ ∃ (i : _)(hi : i ∈ range n), f i (mem_range.1 hi) = a := fun a =>
  ⟨fun ha =>
    let ⟨i, hi, eq⟩ := hf a ha
    ⟨i, mem_range.2 hi, eq⟩,
    fun ⟨i, hi, eq⟩ => eq ▸ hf' i (mem_range.1 hi)⟩
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
⊢ card s = n

tactic: have : s = (range n).attach.image fun i => f i.1 (mem_range.1 i.2) := by
  simpa only [ext_iff, mem_image, exists_prop, Subtype.exists, mem_attach, true_and_iff]
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
this : ∀ (a : α), a ∈ s ↔ ∃ i hi, f i (_ : i < n) = a
⊢ card s = n

tactic: calc
  s.card = card ((range n).attach.image fun i => f i.1 (mem_range.1 i.2)) := by rw [this]
  _ = card (range n).attach :=
    (card_image_of_injective _) fun ⟨i, hi⟩ ⟨j, hj⟩ eq =>
      Subtype.eq <| f_inj i j (mem_range.1 hi) (mem_range.1 hj) eq
  _ = card (range n) := card_attach
  _ = n := card_range n
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
this✝ : ∀ (a : α), a ∈ s ↔ ∃ i hi, f i (_ : i < n) = a
this : s = image (fun i => f ↑i (_ : ↑i < n)) (attach (range n))
⊢ card s = n

tactic: simpa only [ext_iff, mem_image, exists_prop, Subtype.exists, mem_attach, true_and_iff]
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
this : ∀ (a : α), a ∈ s ↔ ∃ i hi, f i (_ : i < n) = a
⊢ s = image (fun i => f ↑i (_ : ↑i < n)) (attach (range n))

tactic: rw [this]
state_before: α : Type u_1
β : Type ?u.20200
s t : Finset α
f✝ : α → β
n : ℕ
f : (i : ℕ) → i < n → α
hf : ∀ (a : α), a ∈ s → ∃ i h, f i h = a
hf' : ∀ (i : ℕ) (h : i < n), f i h ∈ s
f_inj : ∀ (i j : ℕ) (hi : i < n) (hj : j < n), f i hi = f j hj → i = j
this✝ : ∀ (a : α), a ∈ s ↔ ∃ i hi, f i (_ : i < n) = a
this : s = image (fun i => f ↑i (_ : ↑i < n)) (attach (range n))
⊢ card s = card (image (fun i => f ↑i (_ : ↑i < n)) (attach (range n)))