l3lab/ntp-mathlib huggingface dataset:
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    

Proof state:
case H
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a : α
M : Monoid α
l₁ l₂ : List α
h✝ : l₁ ~ l₂
hc : Pairwise Commute l₁
x y : α
h : ∀ (z : α), z * x * y = z * y * x
z : α
⊢ z * y * x = z * x * y

Next tactic:
exact (h z).symm
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    exact (h z).symm
  · 

Proof state:
case H₁
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a : α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ ∀ x ∈ l₁, ∀ (z : α), z * x * x = z * x * x

Next tactic:
intros
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    exact (h z).symm
  · intros; 

Proof state:
case H₁
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a : α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
x✝ : α
a✝ : x✝ ∈ l₁
z✝ : α
⊢ z✝ * x✝ * x✝ = z✝ * x✝ * x✝

Next tactic:
rfl
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    exact (h z).symm
  · intros; rfl
  · 

Proof state:
case H₂
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a : α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ Pairwise (fun x y => ∀ (z : α), z * x * y = z * y * x) l₁

Next tactic:
apply hc.imp
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    exact (h z).symm
  · intros; rfl
  · apply hc.imp
    

Proof state:
case H₂
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a : α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ ∀ {a b : α}, Commute a b → ∀ (z : α), z * a * b = z * b * a

Next tactic:
intro a b h z
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
      "If elements of a list additively commute with each other, then their sum does not
      depend on the order of elements."]
theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
    l₁.prod = l₂.prod := by
  refine h.foldl_eq' ?_ _
  apply Pairwise.forall_of_forall
  · intro x y h z
    exact (h z).symm
  · intros; rfl
  · apply hc.imp
    intro a b h z
    

Proof state:
case H₂
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a✝ : α
M : Monoid α
l₁ l₂ : List α
h✝ : l₁ ~ l₂
hc : Pairwise Commute l₁
a b : α
h : Commute a b
z : α
⊢ z * a * b = z * b * a

Next tactic:
rw [mul_assoc z, mul_assoc z, h]
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
o₁ o₂ : Option α
⊢ Option.toList o₁ ~ Option.toList o₂ ↔ o₁ = o₂

Next tactic:
refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
o₁ o₂ : Option α
p : Option.toList o₁ ~ Option.toList o₂
⊢ o₁ = o₂

Next tactic:
cases' o₁ with a
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
o₂ : Option α
p : Option.toList none ~ Option.toList o₂
⊢ none = o₂

Next tactic:
cases' o₂ with b
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝ : α
o₂ : Option α
a : α
p : Option.toList (some a) ~ Option.toList o₂
⊢ some a = o₂

Next tactic:
cases' o₂ with b
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> cases' o₂ with b; · 

Proof state:
case none.none
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
p : Option.toList none ~ Option.toList none
⊢ none = none

Next tactic:
rfl
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> cases' o₂ with b; · rfl
  · 

Proof state:
case none.some
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a b : α
p : Option.toList none ~ Option.toList (some b)
⊢ none = some b

Next tactic:
cases p.length_eq
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> cases' o₂ with b; · rfl
  · cases p.length_eq
  · 

Proof state:
case some.none
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝ a : α
p : Option.toList (some a) ~ Option.toList none
⊢ some a = none

Next tactic:
cases p.length_eq
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> cases' o₂ with b; · rfl
  · cases p.length_eq
  · cases p.length_eq
  · 

Proof state:
case some.some
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝ a b : α
p : Option.toList (some a) ~ Option.toList (some b)
⊢ some a = some b

Next tactic:
exact Option.mem_toList.1 (p.symm.subset <| by simp)
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
  refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
  cases' o₁ with a <;> cases' o₂ with b; · rfl
  · cases p.length_eq
  · cases p.length_eq
  · exact Option.mem_toList.1 (p.symm.subset <| by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝ a b : α
p : Option.toList (some a) ~ Option.toList (some b)
⊢ b ∈ Option.toList (some b)

Next tactic:
simp
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a✝ a : α
l₁ l₂ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ l₂
s : l₁ <+~ l₂
⊢ a :: l₁ <+~ l₂

Next tactic:
rcases s with ⟨l, p, s⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₁ l₂ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ l₂
l : List α
p : l ~ l₁
s : l <+ l₂
⊢ a :: l₁ <+~ l₂

Next tactic:
induction s generalizing l₁
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  

Proof state:
case intro.intro.slnil
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []
case intro.intro.cons
α : Type u_1
β : Type u_2
l✝ l₁✝¹ l₂✝¹ : List α
a✝² a : α
l₂ l l₁✝ l₂✝ : List α
a✝¹ : α
a✝ : l₁✝ <+ l₂✝
a_ih✝ : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ l₂✝ → l₁✝ ~ l₁ → a :: l₁ <+~ l₂✝
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ a✝¹ :: l₂✝
p : l₁✝ ~ l₁
⊢ a :: l₁ <+~ a✝¹ :: l₂✝
case intro.intro.cons₂
α : Type u_1
β : Type u_2
l✝ l₁✝¹ l₂✝¹ : List α
a✝² a : α
l₂ l l₁✝ l₂✝ : List α
a✝¹ : α
a✝ : l₁✝ <+ l₂✝
a_ih✝ : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ l₂✝ → l₁✝ ~ l₁ → a :: l₁ <+~ l₂✝
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ a✝¹ :: l₂✝
p : a✝¹ :: l₁✝ ~ l₁
⊢ a :: l₁ <+~ a✝¹ :: l₂✝

Next tactic:
case slnil => cases h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []

Next tactic:
case slnil => cases h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []

Next tactic:
cases h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  

Proof state:
case intro.intro.cons
α : Type u_1
β : Type u_2
l✝ l₁✝¹ l₂✝¹ : List α
a✝² a : α
l₂ l l₁✝ l₂✝ : List α
a✝¹ : α
a✝ : l₁✝ <+ l₂✝
a_ih✝ : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ l₂✝ → l₁✝ ~ l₁ → a :: l₁ <+~ l₂✝
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ a✝¹ :: l₂✝
p : l₁✝ ~ l₁
⊢ a :: l₁ <+~ a✝¹ :: l₂✝
case intro.intro.cons₂
α : Type u_1
β : Type u_2
l✝ l₁✝¹ l₂✝¹ : List α
a✝² a : α
l₂ l l₁✝ l₂✝ : List α
a✝¹ : α
a✝ : l₁✝ <+ l₂✝
a_ih✝ : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ l₂✝ → l₁✝ ~ l₁ → a :: l₁ <+~ l₂✝
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ a✝¹ :: l₂✝
p : a✝¹ :: l₁✝ ~ l₁
⊢ a :: l₁ <+~ a✝¹ :: l₂✝

Next tactic:
case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : r₁ ~ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : r₁ ~ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says 

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : r₁ ~ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
simp only [Bool.not_eq_true, mem_cons] at h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : r₁ ~ l₁
h₂ : a = b ∨ a ∈ r₂
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
cases' h₂ with e m
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · 

Proof state:
case inl
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : r₁ ~ l₁
e : a = b
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
subst b
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      

Proof state:
case inl
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : r₁ ~ l₁
⊢ a :: l₁ <+~ a :: r₂

Next tactic:
exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · 

Proof state:
case inr
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s' : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : r₁ ~ l₁
m : a ∈ r₂
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      

Proof state:
case inr.intro.intro
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝ a : α
l₂ l r₁ r₂ : List α
b : α
s'✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : r₁ ~ l₁
m : a ∈ r₂
t : List α
p' : t ~ a :: l₁
s' : t <+ r₂
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
exact ⟨t, p', s'.cons _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  

Proof state:
case intro.intro.cons₂
α : Type u_1
β : Type u_2
l✝ l₁✝¹ l₂✝¹ : List α
a✝² a : α
l₂ l l₁✝ l₂✝ : List α
a✝¹ : α
a✝ : l₁✝ <+ l₂✝
a_ih✝ : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ l₂✝ → l₁✝ ~ l₁ → a :: l₁ <+~ l₂✝
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ a✝¹ :: l₂✝
p : a✝¹ :: l₁✝ ~ l₁
⊢ a :: l₁ <+~ a✝¹ :: l₂✝

Next tactic:
case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    have am : a ∈ r₂ := by
      simp only [find?, mem_cons] at h₂
      exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
    rcases mem_split bm with ⟨t₁, t₂, rfl⟩
    have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp
    rcases ih (d₁.sublist st) (mt (fun x => st.subset x) h₁) am
        (Perm.cons_inv <| p.trans perm_middle) with
      ⟨t, p', s'⟩
    exact
      ⟨b :: t, (p'.cons b).trans <| (swap _ _ _).trans (perm_middle.symm.cons a), s'.cons₂ _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : b :: r₁ ~ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    have am : a ∈ r₂ := by
      simp only [find?, mem_cons] at h₂
      exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
    rcases mem_split bm with ⟨t₁, t₂, rfl⟩
    have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp
    rcases ih (d₁.sublist st) (mt (fun x => st.subset x) h₁) am
        (Perm.cons_inv <| p.trans perm_middle) with
      ⟨t, p', s'⟩
    exact
      ⟨b :: t, (p'.cons b).trans <| (swap _ _ _).trans (perm_middle.symm.cons a), s'.cons₂ _⟩
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  case cons₂ r₁ r₂ b _ ih =>
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : b :: r₁ ~ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : b :: r₁ ~ l₁
bm : b ∈ l₁
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
have am : a ∈ r₂ := by
      simp only [find?, mem_cons] at h₂
      exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    have am : a ∈ r₂ := by
      

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : b :: r₁ ~ l₁
bm : b ∈ l₁
⊢ a ∈ r₂

Next tactic:
simp only [find?, mem_cons] at h₂
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    have am : a ∈ r₂ := by
      simp only [find?, mem_cons] at h₂
      

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
p : b :: r₁ ~ l₁
bm : b ∈ l₁
h₂ : a = b ∨ a ∈ r₂
⊢ a ∈ r₂

Next tactic:
exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
    (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
  rcases s with ⟨l, p, s⟩
  induction s generalizing l₁
  case slnil => cases h₂
  case cons r₁ r₂ b s' ih =>
    simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
    cases' h₂ with e m
    · subst b
      exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
    · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
      exact ⟨t, p', s'.cons _⟩
  case cons₂ r₁ r₂ b _ ih =>
    have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
    have am : a ∈ r₂ := by
      simp only [find?, mem_cons] at h₂
      exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁✝ l₂✝ : List α
a✝¹ a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → a ∉ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
l₁ : List α
d₁ : Nodup l₁
h₁ : a ∉ l₁
h₂ : a ∈ b :: r₂
p : b :: r₁ ~ l₁
bm : b ∈ l₁
am : a ∈ r₂
⊢ a :: l₁ <+~ b :: r₂

Next tactic:
rcases mem_split bm with ⟨t₁, t₂, rfl⟩