Theorem: perm_of_prod_eq_prod
File: Mathlib/Data/List/Prime.lean

tactic: classical
  have hl₁' : ∀ p ∈ l₁, Prime p := fun p hp => hl₁ p (mem_cons_of_mem _ hp)
  have hl₂' : ∀ p ∈ (b :: l₂).erase a, Prime p := fun p hp => hl₂ p (mem_of_mem_erase hp)
  have ha : a ∈ b :: l₂ :=
    mem_list_primes_of_dvd_prod (hl₁ a (mem_cons_self _ _)) hl₂
      (h ▸ by rw [prod_cons] ; exact dvd_mul_right _ _)
  have hb : b :: l₂ ~ a :: (b :: l₂).erase a := perm_cons_erase ha
  have hl : prod l₁ = prod ((b :: l₂).erase a) :=
    (mul_right_inj' (hl₁ a (mem_cons_self _ _)).ne_zero).1 <| by
      rwa [← prod_cons, ← prod_cons, ← hb.prod_eq]
  exact Perm.trans ((perm_of_prod_eq_prod hl hl₁' hl₂').cons _) hb.symm
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
⊢ a :: l₁ ~ b :: l₂

tactic: have hl₁' : ∀ p ∈ l₁, Prime p := fun p hp => hl₁ p (mem_cons_of_mem _ hp)
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
⊢ a :: l₁ ~ b :: l₂

tactic: have hl₂' : ∀ p ∈ (b :: l₂).erase a, Prime p := fun p hp => hl₂ p (mem_of_mem_erase hp)
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
⊢ a :: l₁ ~ b :: l₂

tactic: have ha : a ∈ b :: l₂ :=
  mem_list_primes_of_dvd_prod (hl₁ a (mem_cons_self _ _)) hl₂
    (h ▸ by rw [prod_cons] ; exact dvd_mul_right _ _)
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
⊢ a :: l₁ ~ b :: l₂

tactic: have hb : b :: l₂ ~ a :: (b :: l₂).erase a := perm_cons_erase ha
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
ha : a ∈ b :: l₂
⊢ a :: l₁ ~ b :: l₂

tactic: have hl : prod l₁ = prod ((b :: l₂).erase a) :=
  (mul_right_inj' (hl₁ a (mem_cons_self _ _)).ne_zero).1 <| by
    rwa [← prod_cons, ← prod_cons, ← hb.prod_eq]
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
ha : a ∈ b :: l₂
hb : b :: l₂ ~ a :: List.erase (b :: l₂) a
⊢ a :: l₁ ~ b :: l₂

tactic: exact Perm.trans ((perm_of_prod_eq_prod hl hl₁' hl₂').cons _) hb.symm
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
ha : a ∈ b :: l₂
hb : b :: l₂ ~ a :: List.erase (b :: l₂) a
hl : prod l₁ = prod (List.erase (b :: l₂) a)
⊢ a :: l₁ ~ b :: l₂

tactic: rw [prod_cons]
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
⊢ a ∣ prod (a :: l₁)

tactic: exact dvd_mul_right _ _
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
⊢ a ∣ a * prod l₁

tactic: rwa [← prod_cons, ← prod_cons, ← hb.prod_eq]
state_before: M : Type u_1
inst✝¹ : CancelCommMonoidWithZero M
inst✝ : Unique Mˣ
a : M
l₁ : List M
b : M
l₂ : List M
h : prod (a :: l₁) = prod (b :: l₂)
hl₁ : ∀ (p : M), p ∈ a :: l₁ → Prime p
hl₂ : ∀ (p : M), p ∈ b :: l₂ → Prime p
hl₁' : ∀ (p : M), p ∈ l₁ → Prime p
hl₂' : ∀ (p : M), p ∈ List.erase (b :: l₂) a → Prime p
ha : a ∈ b :: l₂
hb : b :: l₂ ~ a :: List.erase (b :: l₂) a
⊢ a * prod l₁ = a * prod (List.erase (b :: l₂) a)