l3lab/ntp-mathlib huggingface dataset:
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  

Proof state:
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ ∀ {n : ℕ}, n ≠ 0 → f n = Finsupp.prod (factorization n) fun p k => f (p ^ k)

Next tactic:
apply Nat.recOnPosPrimePosCoprime
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · 

Proof state:
case hp
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ ∀ (p n : ℕ), Prime p → 0 < n → p ^ n ≠ 0 → f (p ^ n) = Finsupp.prod (factorization (p ^ n)) fun p k => f (p ^ k)

Next tactic:
rintro p k hp - -
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    

Proof state:
case hp
a b m n p✝ : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
p k : ℕ
hp : Prime p
⊢ f (p ^ k) = Finsupp.prod (factorization (p ^ k)) fun p k => f (p ^ k)

Next tactic:
rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    

Proof state:
a b m n p✝ : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
p k : ℕ
hp : Prime p
⊢ f (p ^ 0) = 1

Next tactic:
rwa [pow_zero]
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · 

Proof state:
case h0
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ 0 ≠ 0 → f 0 = Finsupp.prod (factorization 0) fun p k => f (p ^ k)

Next tactic:
simp
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · 

Proof state:
case h1
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ 1 ≠ 0 → f 1 = Finsupp.prod (factorization 1) fun p k => f (p ^ k)

Next tactic:
rintro -
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · rintro -
    

Proof state:
case h1
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ f 1 = Finsupp.prod (factorization 1) fun p k => f (p ^ k)

Next tactic:
rw [factorization_one, hf]
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · rintro -
    rw [factorization_one, hf]
    

Proof state:
case h1
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ 1 = Finsupp.prod 0 fun p k => f (p ^ k)

Next tactic:
simp
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · rintro -
    rw [factorization_one, hf]
    simp
  · 

Proof state:
case h
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
⊢ ∀ (a b : ℕ),
    1 < a →
      1 < b →
        Coprime a b →
          (a ≠ 0 → f a = Finsupp.prod (factorization a) fun p k => f (p ^ k)) →
            (b ≠ 0 → f b = Finsupp.prod (factorization b) fun p k => f (p ^ k)) →
              a * b ≠ 0 → f (a * b) = Finsupp.prod (factorization (a * b)) fun p k => f (p ^ k)

Next tactic:
intro a b _ _ hab ha hb hab_pos
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · rintro -
    rw [factorization_one, hf]
    simp
  · intro a b _ _ hab ha hb hab_pos
    

Proof state:
case h
a✝² b✝ m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
a b : ℕ
a✝¹ : 1 < a
a✝ : 1 < b
hab : Coprime a b
ha : a ≠ 0 → f a = Finsupp.prod (factorization a) fun p k => f (p ^ k)
hb : b ≠ 0 → f b = Finsupp.prod (factorization b) fun p k => f (p ^ k)
hab_pos : a * b ≠ 0
⊢ f (a * b) = Finsupp.prod (factorization (a * b)) fun p k => f (p ^ k)

Next tactic:
rw [h_mult a b hab, ha (left_ne_zero_of_mul hab_pos), hb (right_ne_zero_of_mul hab_pos),
      factorization_mul_of_coprime hab, ← prod_add_index_of_disjoint]
/-- For any multiplicative function `f` with `f 1 = 1` and any `n ≠ 0`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf : f 1 = 1) :
    ∀ {n : ℕ}, n ≠ 0 → f n = n.factorization.prod fun p k => f (p ^ k) := by
  apply Nat.recOnPosPrimePosCoprime
  · rintro p k hp - -
    -- Porting note: replaced `simp` with `rw`
    rw [Prime.factorization_pow hp, Finsupp.prod_single_index _]
    rwa [pow_zero]
  · simp
  · rintro -
    rw [factorization_one, hf]
    simp
  · intro a b _ _ hab ha hb hab_pos
    rw [h_mult a b hab, ha (left_ne_zero_of_mul hab_pos), hb (right_ne_zero_of_mul hab_pos),
      factorization_mul_of_coprime hab, ← prod_add_index_of_disjoint]
    

Proof state:
case h.hd
a✝² b✝ m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf : f 1 = 1
a b : ℕ
a✝¹ : 1 < a
a✝ : 1 < b
hab : Coprime a b
ha : a ≠ 0 → f a = Finsupp.prod (factorization a) fun p k => f (p ^ k)
hb : b ≠ 0 → f b = Finsupp.prod (factorization b) fun p k => f (p ^ k)
hab_pos : a * b ≠ 0
⊢ _root_.Disjoint (factorization a).support (factorization b).support

Next tactic:
exact hab.disjoint_primeFactors
/-- For any multiplicative function `f` with `f 1 = 1` and `f 0 = 1`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization' {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf0 : f 0 = 1) (hf1 : f 1 = 1) :
    f n = n.factorization.prod fun p k => f (p ^ k) := by
  

Proof state:
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf0 : f 0 = 1
hf1 : f 1 = 1
⊢ f n = Finsupp.prod (factorization n) fun p k => f (p ^ k)

Next tactic:
obtain rfl | hn := eq_or_ne n 0
/-- For any multiplicative function `f` with `f 1 = 1` and `f 0 = 1`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization' {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf0 : f 0 = 1) (hf1 : f 1 = 1) :
    f n = n.factorization.prod fun p k => f (p ^ k) := by
  obtain rfl | hn := eq_or_ne n 0
  · 

Proof state:
case inl
a b m p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf0 : f 0 = 1
hf1 : f 1 = 1
⊢ f 0 = Finsupp.prod (factorization 0) fun p k => f (p ^ k)

Next tactic:
simpa
/-- For any multiplicative function `f` with `f 1 = 1` and `f 0 = 1`,
we can evaluate `f n` by evaluating `f` at `p ^ k` over the factorization of `n` -/
theorem multiplicative_factorization' {β : Type*} [CommMonoid β] (f : ℕ → β)
    (h_mult : ∀ x y : ℕ, Coprime x y → f (x * y) = f x * f y) (hf0 : f 0 = 1) (hf1 : f 1 = 1) :
    f n = n.factorization.prod fun p k => f (p ^ k) := by
  obtain rfl | hn := eq_or_ne n 0
  · simpa
  · 

Proof state:
case inr
a b m n p : ℕ
β : Type u_1
inst✝ : CommMonoid β
f : ℕ → β
h_mult : ∀ (x y : ℕ), Coprime x y → f (x * y) = f x * f y
hf0 : f 0 = 1
hf1 : f 1 = 1
hn : n ≠ 0
⊢ f n = Finsupp.prod (factorization n) fun p k => f (p ^ k)

Next tactic:
exact multiplicative_factorization _ h_mult hf1 hn
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  

Proof state:
a✝ b✝ m n p a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
⊢ a = b ↔ ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b

Next tactic:
constructor
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · 

Proof state:
case mp
a✝ b✝ m n p a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
⊢ a = b → ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b

Next tactic:
rintro rfl
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    

Proof state:
case mp
a✝ b m n p a : ℕ
ha hb : a ≠ 0
⊢ ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p a

Next tactic:
simp
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    simp
  · 

Proof state:
case mpr
a✝ b✝ m n p a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
⊢ (∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b) → a = b

Next tactic:
intro h
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    simp
  · intro h
    

Proof state:
case mpr
a✝ b✝ m n p a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
h : ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b
⊢ a = b

Next tactic:
refine' eq_of_factorization_eq ha hb fun p => _
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    simp
  · intro h
    refine' eq_of_factorization_eq ha hb fun p => _
    

Proof state:
case mpr
a✝ b✝ m n p✝ a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
h : ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b
p : ℕ
⊢ (factorization a) p = (factorization b) p

Next tactic:
by_cases pp : p.Prime
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    simp
  · intro h
    refine' eq_of_factorization_eq ha hb fun p => _
    by_cases pp : p.Prime
    · 

Proof state:
case pos
a✝ b✝ m n p✝ a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
h : ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b
p : ℕ
pp : Prime p
⊢ (factorization a) p = (factorization b) p

Next tactic:
simp [factorization_def, pp, h p pp]
/-- Two positive naturals are equal if their prime padic valuations are equal -/
theorem eq_iff_prime_padicValNat_eq (a b : ℕ) (ha : a ≠ 0) (hb : b ≠ 0) :
    a = b ↔ ∀ p : ℕ, p.Prime → padicValNat p a = padicValNat p b := by
  constructor
  · rintro rfl
    simp
  · intro h
    refine' eq_of_factorization_eq ha hb fun p => _
    by_cases pp : p.Prime
    · simp [factorization_def, pp, h p pp]
    · 

Proof state:
case neg
a✝ b✝ m n p✝ a b : ℕ
ha : a ≠ 0
hb : b ≠ 0
h : ∀ (p : ℕ), Prime p → padicValNat p a = padicValNat p b
p : ℕ
pp : ¬Prime p
⊢ (factorization a) p = (factorization b) p

Next tactic:
simp [factorization_eq_zero_of_non_prime, pp]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ ∏ p in Finset.filter Prime (Finset.range m), p ^ padicValNat p n = n

Next tactic:
conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
| ∏ p in Finset.filter Prime (Finset.range m), p ^ padicValNat p n = n

Next tactic:
rhs
    rw [← factorization_prod_pow_eq_self hn]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
| ∏ p in Finset.filter Prime (Finset.range m), p ^ padicValNat p n = n

Next tactic:
rhs
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
| n

Next tactic:
rw [← factorization_prod_pow_eq_self hn]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ ∏ p in Finset.filter Prime (Finset.range m), p ^ padicValNat p n = Finsupp.prod (factorization n) fun x x_1 => x ^ x_1

Next tactic:
rw [eq_comm]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  

Proof state:
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ (Finsupp.prod (factorization n) fun x x_1 => x ^ x_1) =
    ∏ p in Finset.filter Prime (Finset.range m), p ^ padicValNat p n

Next tactic:
apply Finset.prod_subset_one_on_sdiff
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · 

Proof state:
case h
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ (factorization n).support ⊆ Finset.filter Prime (Finset.range m)

Next tactic:
exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · 

Proof state:
case hg
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ ∀ x ∈ Finset.filter Prime (Finset.range m) \ (factorization n).support, x ^ padicValNat x n = 1

Next tactic:
intro p hp
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · intro p hp
    

Proof state:
case hg
a b m✝ n✝ p✝ n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
p : ℕ
hp : p ∈ Finset.filter Prime (Finset.range m) \ (factorization n).support
⊢ p ^ padicValNat p n = 1

Next tactic:
cases' Finset.mem_sdiff.mp hp with hp1 hp2
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · intro p hp
    cases' Finset.mem_sdiff.mp hp with hp1 hp2
    

Proof state:
case hg.intro
a b m✝ n✝ p✝ n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
p : ℕ
hp : p ∈ Finset.filter Prime (Finset.range m) \ (factorization n).support
hp1 : p ∈ Finset.filter Prime (Finset.range m)
hp2 : p ∉ (factorization n).support
⊢ p ^ padicValNat p n = 1

Next tactic:
rw [← factorization_def n (Finset.mem_filter.mp hp1).2]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · intro p hp
    cases' Finset.mem_sdiff.mp hp with hp1 hp2
    rw [← factorization_def n (Finset.mem_filter.mp hp1).2]
    

Proof state:
case hg.intro
a b m✝ n✝ p✝ n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
p : ℕ
hp : p ∈ Finset.filter Prime (Finset.range m) \ (factorization n).support
hp1 : p ∈ Finset.filter Prime (Finset.range m)
hp2 : p ∉ (factorization n).support
⊢ p ^ (factorization n) p = 1

Next tactic:
simp [Finsupp.not_mem_support_iff.mp hp2]
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · intro p hp
    cases' Finset.mem_sdiff.mp hp with hp1 hp2
    rw [← factorization_def n (Finset.mem_filter.mp hp1).2]
    simp [Finsupp.not_mem_support_iff.mp hp2]
  · 

Proof state:
case hfg
a b m✝ n✝ p n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
⊢ ∀ x ∈ (factorization n).support, (fun x x_1 => x ^ x_1) x ((factorization n) x) = x ^ padicValNat x n

Next tactic:
intro p hp
theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < m) :
    (∏ p in Finset.filter Nat.Prime (Finset.range m), p ^ padicValNat p n) = n := by
  -- Porting note: was `nth_rw_rhs`
  conv =>
    rhs
    rw [← factorization_prod_pow_eq_self hn]
  rw [eq_comm]
  apply Finset.prod_subset_one_on_sdiff
  · exact fun p hp => Finset.mem_filter.mpr ⟨Finset.mem_range.2 <| pr.trans_le' <|
      le_of_mem_primeFactors hp, prime_of_mem_primeFactors hp⟩
  · intro p hp
    cases' Finset.mem_sdiff.mp hp with hp1 hp2
    rw [← factorization_def n (Finset.mem_filter.mp hp1).2]
    simp [Finsupp.not_mem_support_iff.mp hp2]
  · intro p hp
    

Proof state:
case hfg
a b m✝ n✝ p✝ n : ℕ
hn : n ≠ 0
m : ℕ
pr : n < m
p : ℕ
hp : p ∈ (factorization n).support
⊢ (fun x x_1 => x ^ x_1) p ((factorization n) p) = p ^ padicValNat p n

Next tactic:
simp [factorization_def n (prime_of_mem_primeFactors hp)]
/-- Exactly `n / p` naturals in `[1, n]` are multiples of `p`. -/
theorem card_multiples (n p : ℕ) : card ((Finset.range n).filter fun e => p ∣ e + 1) = n / p := by
  

Proof state:
a b m n✝ p✝ n p : ℕ
⊢ card (Finset.filter (fun e => p ∣ e + 1) (Finset.range n)) = n / p

Next tactic:
induction' n with n hn