-- Mathlib/RingTheory/UniqueFactorizationDomain/NormalizedFactors.lean
theorem normalizedFactors_mul {x y : α} (hx : x ≠ 0) (hy : y ≠ 0) :
    normalizedFactors (x * y) = normalizedFactors x + normalizedFactors y

Proof state:
case hst.hf
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ ∀ x_1 ∈ normalizedFactors x + normalizedFactors y, Irreducible x_1

Tactic:
intro x hx

Result:
case hst.hf
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x✝ y : α
hx✝ : x✝ ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
x : α
hx : x ∈ normalizedFactors x✝ + normalizedFactors y
⊢ Irreducible x

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
⊢ normalizedFactors (x * y) = normalizedFactors x + normalizedFactors y

Tactic:
have h : (normalize : α → α) = Associates.out ∘ Associates.mk := by
  ext
  rw [Function.comp_apply, Associates.out_mk]

Result:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ normalizedFactors (x * y) = normalizedFactors x + normalizedFactors y

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.map Associates.mk (normalizedFactors x + normalizedFactors y) =
    Multiset.map Associates.mk (normalizedFactors (x * y))

Tactic:
apply Multiset.map_mk_eq_map_mk_of_rel

Result:
case hst
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.Rel (⇑(Associated.setoid α)) (normalizedFactors x + normalizedFactors y) (normalizedFactors (x * y))

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.map Associates.out (Multiset.map Associates.mk (normalizedFactors x + normalizedFactors y)) =
    Multiset.map Associates.out (Multiset.map Associates.mk (normalizedFactors (x * y)))

Tactic:
refine congr rfl ?_

Result:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.map Associates.mk (normalizedFactors x + normalizedFactors y) =
    Multiset.map Associates.mk (normalizedFactors (x * y))

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
⊢ ⇑normalize = Associates.out ∘ Associates.mk

Tactic:
ext

Result:
case h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
x✝ : α
⊢ normalize x✝ = (Associates.out ∘ Associates.mk) x✝

Proof state:
case hst.h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ (normalizedFactors x).prod * (normalizedFactors y).prod ~ᵤ (normalizedFactors (x * y)).prod

Tactic:
exact
  ((prod_normalizedFactors hx).mul_mul (prod_normalizedFactors hy)).trans
    (prod_normalizedFactors (mul_ne_zero hx hy)).symm

Result:
no goals

Proof state:
case hst.h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ (normalizedFactors x + normalizedFactors y).prod ~ᵤ (normalizedFactors (x * y)).prod

Tactic:
rw [Multiset.prod_add]

Result:
case hst.h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ (normalizedFactors x).prod * (normalizedFactors y).prod ~ᵤ (normalizedFactors (x * y)).prod

Proof state:
case hst
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.Rel (⇑(Associated.setoid α)) (normalizedFactors x + normalizedFactors y) (normalizedFactors (x * y))

Tactic:
apply factors_unique

Result:
case hst.hf
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ ∀ x_1 ∈ normalizedFactors x + normalizedFactors y, Irreducible x_1

case hst.hg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ ∀ x_1 ∈ normalizedFactors (x * y), Irreducible x_1

case hst.h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ (normalizedFactors x + normalizedFactors y).prod ~ᵤ (normalizedFactors (x * y)).prod

Proof state:
case h
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
x✝ : α
⊢ normalize x✝ = (Associates.out ∘ Associates.mk) x✝

Tactic:
rw [Function.comp_apply, Associates.out_mk]

Result:
no goals

Proof state:
case hst.hg
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ ∀ x_1 ∈ normalizedFactors (x * y), Irreducible x_1

Tactic:
exact irreducible_of_normalized_factor

Result:
no goals

Proof state:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ normalizedFactors (x * y) = normalizedFactors x + normalizedFactors y

Tactic:
rw [← Multiset.map_id' (normalizedFactors (x * y)), ← Multiset.map_id' (normalizedFactors x), ←
  Multiset.map_id' (normalizedFactors y), ← Multiset.map_congr rfl normalize_normalized_factor, ←
  Multiset.map_congr rfl normalize_normalized_factor, ←
  Multiset.map_congr rfl normalize_normalized_factor, ← Multiset.map_add, h, ←
  Multiset.map_map Associates.out, eq_comm, ← Multiset.map_map Associates.out]

Result:
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x y : α
hx : x ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
⊢ Multiset.map Associates.out (Multiset.map Associates.mk (normalizedFactors x + normalizedFactors y)) =
    Multiset.map Associates.out (Multiset.map Associates.mk (normalizedFactors (x * y)))

Proof state:
case hst.hf
α : Type u_1
inst✝² : CancelCommMonoidWithZero α
inst✝¹ : NormalizationMonoid α
inst✝ : UniqueFactorizationMonoid α
x✝ y : α
hx✝ : x✝ ≠ 0
hy : y ≠ 0
h : ⇑normalize = Associates.out ∘ Associates.mk
x : α
hx : x ∈ normalizedFactors x✝ + normalizedFactors y
⊢ Irreducible x

Tactic:
rcases Multiset.mem_add.1 hx with (hx | hx) <;> exact irreducible_of_normalized_factor x hx

Result:
no goals