Theorem: Nat.totient_div_of_dvd
File: Mathlib/Data/Nat/Totient.lean

tactic: rcases d.eq_zero_or_pos with (rfl | hd0)
state_before: n d : ℕ
hnd : d ∣ n
⊢ φ (n / d) = (filter (fun k => n.gcd k = d) (range n)).card
state_after: case inl
n : ℕ
hnd : 0 ∣ n
⊢ φ (n / 0) = (filter (fun k => n.gcd k = 0) (range n)).card

case inr
n d : ℕ
hnd : d ∣ n
hd0 : d > 0
⊢ φ (n / d) = (filter (fun k => n.gcd k = d) (range n)).card

tactic: rcases hnd with ⟨x, rfl⟩
state_before: case inr
n d : ℕ
hnd : d ∣ n
hd0 : d > 0
⊢ φ (n / d) = (filter (fun k => n.gcd k = d) (range n)).card
state_after: case inr.intro
d : ℕ
hd0 : d > 0
x : ℕ
⊢ φ (d * x / d) = (filter (fun k => (d * x).gcd k = d) (range (d * x))).card

tactic: rw [Nat.mul_div_cancel_left x hd0]
state_before: case inr.intro
d : ℕ
hd0 : d > 0
x : ℕ
⊢ φ (d * x / d) = (filter (fun k => (d * x).gcd k = d) (range (d * x))).card
state_after: case inr.intro
d : ℕ
hd0 : d > 0
x : ℕ
⊢ φ x = (filter (fun k => (d * x).gcd k = d) (range (d * x))).card

tactic: apply Finset.card_bij fun k _ => d * k
state_before: case inr.intro
d : ℕ
hd0 : d > 0
x : ℕ
⊢ φ x = (filter (fun k => (d * x).gcd k = d) (range (d * x))).card
state_after: case inr.intro.hi
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a ∈ filter x.Coprime (range x), d * a ∈ filter (fun k => (d * x).gcd k = d) (range (d * x))

case inr.intro.i_inj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a₁ ∈ filter x.Coprime (range x), ∀ a₂ ∈ filter x.Coprime (range x), d * a₁ = d * a₂ → a₁ = a₂

case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ b ∈ filter (fun k => (d * x).gcd k = d) (range (d * x)), ∃ a, ∃ (_ : a ∈ filter x.Coprime (range x)), d * a = b

tactic: simp [eq_zero_of_zero_dvd hnd]
state_before: case inl
n : ℕ
hnd : 0 ∣ n
⊢ φ (n / 0) = (filter (fun k => n.gcd k = 0) (range n)).card
state_after: no goals

tactic: simp only [mem_filter, mem_range, and_imp, Coprime]
state_before: case inr.intro.hi
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a ∈ filter x.Coprime (range x), d * a ∈ filter (fun k => (d * x).gcd k = d) (range (d * x))
state_after: case inr.intro.hi
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a < x, x.gcd a = 1 → d * a < d * x ∧ (d * x).gcd (d * a) = d

tactic: refine fun a ha1 ha2 => ⟨(mul_lt_mul_left hd0).2 ha1, ?_⟩
state_before: case inr.intro.hi
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a < x, x.gcd a = 1 → d * a < d * x ∧ (d * x).gcd (d * a) = d
state_after: case inr.intro.hi
d : ℕ
hd0 : d > 0
x a : ℕ
ha1 : a < x
ha2 : x.gcd a = 1
⊢ (d * x).gcd (d * a) = d

tactic: rw [gcd_mul_left, ha2, mul_one]
state_before: case inr.intro.hi
d : ℕ
hd0 : d > 0
x a : ℕ
ha1 : a < x
ha2 : x.gcd a = 1
⊢ (d * x).gcd (d * a) = d
state_after: no goals

tactic: simp [hd0.ne']
state_before: case inr.intro.i_inj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ a₁ ∈ filter x.Coprime (range x), ∀ a₂ ∈ filter x.Coprime (range x), d * a₁ = d * a₂ → a₁ = a₂
state_after: no goals

tactic: simp only [mem_filter, mem_range, exists_prop, and_imp]
state_before: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ b ∈ filter (fun k => (d * x).gcd k = d) (range (d * x)), ∃ a, ∃ (_ : a ∈ filter x.Coprime (range x)), d * a = b
state_after: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ b < d * x, (d * x).gcd b = d → ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b

tactic: refine fun b hb1 hb2 => ?_
state_before: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x : ℕ
⊢ ∀ b < d * x, (d * x).gcd b = d → ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b
state_after: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b

tactic: have : d ∣ b := by
  rw [← hb2]
  apply gcd_dvd_right
state_before: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b
state_after: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
this : d ∣ b
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b

tactic: rcases this with ⟨q, rfl⟩
state_before: case inr.intro.i_surj
d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
this : d ∣ b
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = b
state_after: case inr.intro.i_surj.intro
d : ℕ
hd0 : d > 0
x q : ℕ
hb1 : d * q < d * x
hb2 : (d * x).gcd (d * q) = d
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = d * q

tactic: refine ⟨q, ⟨⟨(mul_lt_mul_left hd0).1 hb1, ?_⟩, rfl⟩⟩
state_before: case inr.intro.i_surj.intro
d : ℕ
hd0 : d > 0
x q : ℕ
hb1 : d * q < d * x
hb2 : (d * x).gcd (d * q) = d
⊢ ∃ a, (a < x ∧ x.Coprime a) ∧ d * a = d * q
state_after: case inr.intro.i_surj.intro
d : ℕ
hd0 : d > 0
x q : ℕ
hb1 : d * q < d * x
hb2 : (d * x).gcd (d * q) = d
⊢ x.Coprime q

tactic: rwa [gcd_mul_left, mul_right_eq_self_iff hd0] at hb2
state_before: case inr.intro.i_surj.intro
d : ℕ
hd0 : d > 0
x q : ℕ
hb1 : d * q < d * x
hb2 : (d * x).gcd (d * q) = d
⊢ x.Coprime q
state_after: no goals

tactic: rw [← hb2]
state_before: d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
⊢ d ∣ b
state_after: d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
⊢ (d * x).gcd b ∣ b

tactic: apply gcd_dvd_right
state_before: d : ℕ
hd0 : d > 0
x b : ℕ
hb1 : b < d * x
hb2 : (d * x).gcd b = d
⊢ (d * x).gcd b ∣ b
state_after: no goals