Theorem: List.perm_inv_core
File: .lake/packages/batteries/Batteries/Data/List/Perm.lean

tactic: intro s₁ s₂ p
state_before: α : Type u_1
a : α
l₁ l₂ r₁ r₂ : List α
⊢ ∀ (s₁ s₂ : List α), s₁ ~ s₂ → ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = s₁ → l₂ ++ a :: r₂ = s₂ → l₁ ++ r₁ ~ l₂ ++ r₂
state_after: α : Type u_1
a : α
l₁ l₂ r₁ r₂ s₁ s₂ : List α
p : s₁ ~ s₂
⊢ ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = s₁ → l₂ ++ a :: r₂ = s₂ → l₁ ++ r₁ ~ l₂ ++ r₂

tactic: simp at e₁
state_before: case nil
α : Type u_1
a : α
l₁✝ l₂✝ r₁✝ r₂✝ s₁ s₂ l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = []
e₂ : l₂ ++ a :: r₂ = []
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
state_after: no goals

tactic: cases l₁ <;> cases l₂ <;>
  dsimp at e₁ e₂ <;> injections <;> subst_vars
state_before: case cons
α : Type u_1
a : α
l₁✝¹ l₂✝¹ r₁✝ r₂✝ s₁ s₂ : List α
x : α
l₁✝ l₂✝ : List α
p : l₁✝ ~ l₂✝
IH : ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = l₁✝ → l₂ ++ a :: r₂ = l₂✝ → l₁ ++ r₁ ~ l₂ ++ r₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = x :: l₁✝
e₂ : l₂ ++ a :: r₂ = x :: l₂✝
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
state_after: case cons.nil.nil
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ : List α
x : α
r₁ r₂ : List α
head_eq✝ : x = x
p : r₁ ~ r₂
IH : ∀ {l₁ l₂ r₁_1 r₂_1 : List α}, l₁ ++ x :: r₁_1 = r₁ → l₂ ++ x :: r₂_1 = r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ [] ++ r₁ ~ [] ++ r₂

case cons.nil.cons
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
head✝ : α
tail✝ : List α
p : r₁ ~ tail✝ ++ head✝ :: r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ head✝ :: r₁_1 = r₁ → l₂ ++ head✝ :: r₂_1 = tail✝ ++ head✝ :: r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ [] ++ r₁ ~ head✝ :: tail✝ ++ r₂

case cons.cons.nil
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
head✝ : α
tail✝ : List α
p : tail✝ ++ head✝ :: r₁ ~ r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ head✝ :: r₁_1 = tail✝ ++ head✝ :: r₁ → l₂ ++ head✝ :: r₂_1 = r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ head✝ :: tail✝ ++ r₁ ~ [] ++ r₂

case cons.cons.cons
α : Type u_1
a : α
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ tail✝¹ : List α
head✝ : α
tail✝ : List α
p : tail✝¹ ++ a :: r₁ ~ tail✝ ++ a :: r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ a :: r₁_1 = tail✝¹ ++ a :: r₁ → l₂ ++ a :: r₂_1 = tail✝ ++ a :: r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ head✝ :: tail✝¹ ++ r₁ ~ head✝ :: tail✝ ++ r₂

tactic: exact p
state_before: case cons.nil.nil
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ : List α
x : α
r₁ r₂ : List α
head_eq✝ : x = x
p : r₁ ~ r₂
IH : ∀ {l₁ l₂ r₁_1 r₂_1 : List α}, l₁ ++ x :: r₁_1 = r₁ → l₂ ++ x :: r₂_1 = r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ [] ++ r₁ ~ [] ++ r₂
state_after: no goals

tactic: exact p.trans perm_middle
state_before: case cons.nil.cons
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
head✝ : α
tail✝ : List α
p : r₁ ~ tail✝ ++ head✝ :: r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ head✝ :: r₁_1 = r₁ → l₂ ++ head✝ :: r₂_1 = tail✝ ++ head✝ :: r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ [] ++ r₁ ~ head✝ :: tail✝ ++ r₂
state_after: no goals

tactic: exact perm_middle.symm.trans p
state_before: case cons.cons.nil
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
head✝ : α
tail✝ : List α
p : tail✝ ++ head✝ :: r₁ ~ r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ head✝ :: r₁_1 = tail✝ ++ head✝ :: r₁ → l₂ ++ head✝ :: r₂_1 = r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ head✝ :: tail✝ ++ r₁ ~ [] ++ r₂
state_after: no goals

tactic: exact (IH rfl rfl).cons _
state_before: case cons.cons.cons
α : Type u_1
a : α
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ tail✝¹ : List α
head✝ : α
tail✝ : List α
p : tail✝¹ ++ a :: r₁ ~ tail✝ ++ a :: r₂
IH :
  ∀ {l₁ l₂ r₁_1 r₂_1 : List α},
    l₁ ++ a :: r₁_1 = tail✝¹ ++ a :: r₁ → l₂ ++ a :: r₂_1 = tail✝ ++ a :: r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ head✝ :: tail✝¹ ++ r₁ ~ head✝ :: tail✝ ++ r₂
state_after: no goals

tactic: obtain _ | ⟨y, _ | ⟨z, l₁⟩⟩ := l₁
  <;> obtain _ | ⟨u, _ | ⟨v, l₂⟩⟩ := l₂
  <;> dsimp at e₁ e₂ <;> injections <;> subst_vars
  <;> try exact p.cons _
state_before: case swap'
α : Type u_1
a : α
l₁✝¹ l₂✝¹ r₁✝ r₂✝ s₁ s₂ : List α
x y : α
l₁✝ l₂✝ : List α
p : l₁✝ ~ l₂✝
IH : ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = l₁✝ → l₂ ++ a :: r₂ = l₂✝ → l₁ ++ r₁ ~ l₂ ++ r₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = y :: x :: l₁✝
e₂ : l₂ ++ a :: r₂ = x :: y :: l₂✝
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
state_after: case swap'.nil.cons.cons
α : Type u_1
l₁ l₂✝ r₁ r₂✝ s₁ s₂ l₁✝ r₂ : List α
u v : α
l₂ : List α
p : l₁✝ ~ l₂ ++ v :: r₂
IH : ∀ {l₁ l₂_1 r₁ r₂_1 : List α}, l₁ ++ v :: r₁ = l₁✝ → l₂_1 ++ v :: r₂_1 = l₂ ++ v :: r₂ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ [] ++ u :: l₁✝ ~ u :: v :: l₂ ++ r₂

case swap'.cons.nil.cons.cons
α : Type u_1
l₁ l₂✝ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
u v : α
l₂ : List α
p : r₁ ~ l₂ ++ u :: r₂
IH :
  ∀ {l₁ l₂_1 r₁_1 r₂_1 : List α}, l₁ ++ u :: r₁_1 = r₁ → l₂_1 ++ u :: r₂_1 = l₂ ++ u :: r₂ → l₁ ++ r₁_1 ~ l₂_1 ++ r₂_1
⊢ [v] ++ r₁ ~ u :: v :: l₂ ++ r₂

case swap'.cons.cons.nil
α : Type u_1
l₁✝ l₂ r₁✝ r₂ s₁ s₂ l₂✝ r₁ : List α
y z : α
l₁ : List α
p : l₁ ++ z :: r₁ ~ l₂✝
IH : ∀ {l₁_1 l₂ r₁_1 r₂ : List α}, l₁_1 ++ z :: r₁_1 = l₁ ++ z :: r₁ → l₂ ++ z :: r₂ = l₂✝ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ y :: l₂✝

case swap'.cons.cons.cons.nil
α : Type u_1
l₁✝ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
y : α
l₁ : List α
u : α
p : l₁ ++ y :: r₁ ~ r₂
IH :
  ∀ {l₁_1 l₂ r₁_1 r₂_1 : List α}, l₁_1 ++ y :: r₁_1 = l₁ ++ y :: r₁ → l₂ ++ y :: r₂_1 = r₂ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂_1
⊢ y :: u :: l₁ ++ r₁ ~ [u] ++ r₂

case swap'.cons.cons.cons.cons
α : Type u_1
a : α
l₁✝ l₂✝ r₁✝ r₂✝ s₁ s₂ r₁ r₂ l₁ : List α
u v : α
l₂ : List α
p : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH :
  ∀ {l₁_1 l₂_1 r₁_1 r₂_1 : List α},
    l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁_1 ++ r₁_1 ~ l₂_1 ++ r₂_1
⊢ v :: u :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂

tactic: exact p.cons _
state_before: case swap'.cons.nil.cons.nil
α : Type u_1
l₁ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
u : α
p : r₁ ~ r₂
IH : ∀ {l₁ l₂ r₁_1 r₂_1 : List α}, l₁ ++ u :: r₁_1 = r₁ → l₂ ++ u :: r₂_1 = r₂ → l₁ ++ r₁_1 ~ l₂ ++ r₂_1
⊢ [u] ++ r₁ ~ [u] ++ r₂
state_after: no goals

tactic: exact (p.trans perm_middle).cons u
state_before: case swap'.nil.cons.cons
α : Type u_1
l₁ l₂✝ r₁ r₂✝ s₁ s₂ l₁✝ r₂ : List α
u v : α
l₂ : List α
p : l₁✝ ~ l₂ ++ v :: r₂
IH : ∀ {l₁ l₂_1 r₁ r₂_1 : List α}, l₁ ++ v :: r₁ = l₁✝ → l₂_1 ++ v :: r₂_1 = l₂ ++ v :: r₂ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ [] ++ u :: l₁✝ ~ u :: v :: l₂ ++ r₂
state_after: no goals

tactic: exact ((p.trans perm_middle).cons _).trans (swap _ _ _)
state_before: case swap'.cons.nil.cons.cons
α : Type u_1
l₁ l₂✝ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
u v : α
l₂ : List α
p : r₁ ~ l₂ ++ u :: r₂
IH :
  ∀ {l₁ l₂_1 r₁_1 r₂_1 : List α}, l₁ ++ u :: r₁_1 = r₁ → l₂_1 ++ u :: r₂_1 = l₂ ++ u :: r₂ → l₁ ++ r₁_1 ~ l₂_1 ++ r₂_1
⊢ [v] ++ r₁ ~ u :: v :: l₂ ++ r₂
state_after: no goals

tactic: exact (perm_middle.symm.trans p).cons y
state_before: case swap'.cons.cons.nil
α : Type u_1
l₁✝ l₂ r₁✝ r₂ s₁ s₂ l₂✝ r₁ : List α
y z : α
l₁ : List α
p : l₁ ++ z :: r₁ ~ l₂✝
IH : ∀ {l₁_1 l₂ r₁_1 r₂ : List α}, l₁_1 ++ z :: r₁_1 = l₁ ++ z :: r₁ → l₂ ++ z :: r₂ = l₂✝ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ y :: l₂✝
state_after: no goals

tactic: exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
state_before: case swap'.cons.cons.cons.nil
α : Type u_1
l₁✝ l₂ r₁✝ r₂✝ s₁ s₂ r₁ r₂ : List α
y : α
l₁ : List α
u : α
p : l₁ ++ y :: r₁ ~ r₂
IH :
  ∀ {l₁_1 l₂ r₁_1 r₂_1 : List α}, l₁_1 ++ y :: r₁_1 = l₁ ++ y :: r₁ → l₂ ++ y :: r₂_1 = r₂ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂_1
⊢ y :: u :: l₁ ++ r₁ ~ [u] ++ r₂
state_after: no goals

tactic: exact (IH rfl rfl).swap' _ _
state_before: case swap'.cons.cons.cons.cons
α : Type u_1
a : α
l₁✝ l₂✝ r₁✝ r₂✝ s₁ s₂ r₁ r₂ l₁ : List α
u v : α
l₂ : List α
p : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH :
  ∀ {l₁_1 l₂_1 r₁_1 r₂_1 : List α},
    l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁_1 ++ r₁_1 ~ l₂_1 ++ r₂_1
⊢ v :: u :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂
state_after: no goals

tactic: subst e₁ e₂
state_before: case trans
α : Type u_1
a : α
l₁✝¹ l₂✝¹ r₁✝ r₂✝ s₁ s₂ l₁✝ l₂✝ l₃✝ : List α
p₁ : l₁✝ ~ l₂✝
p₂ : l₂✝ ~ l₃✝
IH₁ : ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = l₁✝ → l₂ ++ a :: r₂ = l₂✝ → l₁ ++ r₁ ~ l₂ ++ r₂
IH₂ : ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = l₂✝ → l₂ ++ a :: r₂ = l₃✝ → l₁ ++ r₁ ~ l₂ ++ r₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = l₁✝
e₂ : l₂ ++ a :: r₂ = l₃✝
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
state_after: case trans
α : Type u_1
a : α
l₁✝ l₂✝¹ r₁✝ r₂✝ s₁ s₂ l₂✝ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂✝
IH₁ : ∀ {l₁_1 l₂ r₁_1 r₂ : List α}, l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂ ++ a :: r₂ = l₂✝ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂
p₂ : l₂✝ ~ l₂ ++ a :: r₂
IH₂ : ∀ {l₁ l₂_1 r₁ r₂_1 : List α}, l₁ ++ a :: r₁ = l₂✝ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ l₁ ++ r₁ ~ l₂ ++ r₂

tactic: obtain ⟨l₂, r₂, rfl⟩ := append_of_mem (a := a) (p₁.subset (by simp))
state_before: case trans
α : Type u_1
a : α
l₁✝ l₂✝¹ r₁✝ r₂✝ s₁ s₂ l₂✝ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂✝
IH₁ : ∀ {l₁_1 l₂ r₁_1 r₂ : List α}, l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂ ++ a :: r₂ = l₂✝ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂
p₂ : l₂✝ ~ l₂ ++ a :: r₂
IH₂ : ∀ {l₁ l₂_1 r₁ r₂_1 : List α}, l₁ ++ a :: r₁ = l₂✝ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
state_after: case trans.intro.intro
α : Type u_1
a : α
l₁✝ l₂✝¹ r₁✝ r₂✝¹ s₁ s₂ l₁ l₂✝ r₁ r₂✝ l₂ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH₁ :
  ∀ {l₁_1 l₂_1 r₁_1 r₂_1 : List α},
    l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁_1 ++ r₁_1 ~ l₂_1 ++ r₂_1
p₂ : l₂ ++ a :: r₂ ~ l₂✝ ++ a :: r₂✝
IH₂ :
  ∀ {l₁ l₂_1 r₁ r₂_1 : List α},
    l₁ ++ a :: r₁ = l₂ ++ a :: r₂ → l₂_1 ++ a :: r₂_1 = l₂✝ ++ a :: r₂✝ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ l₁ ++ r₁ ~ l₂✝ ++ r₂✝

tactic: exact (IH₁ rfl rfl).trans (IH₂ rfl rfl)
state_before: case trans.intro.intro
α : Type u_1
a : α
l₁✝ l₂✝¹ r₁✝ r₂✝¹ s₁ s₂ l₁ l₂✝ r₁ r₂✝ l₂ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH₁ :
  ∀ {l₁_1 l₂_1 r₁_1 r₂_1 : List α},
    l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁_1 ++ r₁_1 ~ l₂_1 ++ r₂_1
p₂ : l₂ ++ a :: r₂ ~ l₂✝ ++ a :: r₂✝
IH₂ :
  ∀ {l₁ l₂_1 r₁ r₂_1 : List α},
    l₁ ++ a :: r₁ = l₂ ++ a :: r₂ → l₂_1 ++ a :: r₂_1 = l₂✝ ++ a :: r₂✝ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ l₁ ++ r₁ ~ l₂✝ ++ r₂✝
state_after: no goals

tactic: simp
state_before: α : Type u_1
a : α
l₁✝ l₂✝¹ r₁✝ r₂✝ s₁ s₂ l₂✝ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂✝
IH₁ : ∀ {l₁_1 l₂ r₁_1 r₂ : List α}, l₁_1 ++ a :: r₁_1 = l₁ ++ a :: r₁ → l₂ ++ a :: r₂ = l₂✝ → l₁_1 ++ r₁_1 ~ l₂ ++ r₂
p₂ : l₂✝ ~ l₂ ++ a :: r₂
IH₂ : ∀ {l₁ l₂_1 r₁ r₂_1 : List α}, l₁ ++ a :: r₁ = l₂✝ → l₂_1 ++ a :: r₂_1 = l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂_1 ++ r₂_1
⊢ a ∈ l₁ ++ a :: r₁
state_after: no goals