[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
x✝³ : α
x✝² x✝¹ : List α
x✝ : x✝² ~ x✝¹
hs : a ∈ x✝² ↔ a ∈ x✝¹
⊢ a ∈ x✝³ :: x✝² ↔ a ∈ x✝³ :: x✝¹
[PROOFSTEP]
simp only [mem_cons, hs]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
x✝² x✝¹ : α
x✝ : List α
⊢ a ∈ x✝¹ :: x✝² :: x✝ ↔ a ∈ x✝² :: x✝¹ :: x✝
[PROOFSTEP]
simp only [mem_cons, or_left_comm]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a : α
l : List α
⊢ a :: (l ++ []) ~ a :: l
[PROOFSTEP]
rw [append_nil]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂✝ l₂ : List α
⊢ [] ++ l₂ ~ l₂ ++ []
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
a : α
⊢ concat l a ~ a :: l
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ : List α
p : l₁✝ ~ l₂✝
_x : α
l₁ l₂ : List α
_p : l₁ ~ l₂
r : length l₁ = length l₂
⊢ length (_x :: l₁) = length (_x :: l₂)
[PROOFSTEP]
simp [r]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ : List α
p : l₁ ~ l₂
_x _y : α
l : List α
⊢ length (_y :: _x :: l) = length (_x :: _y :: l)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
l : List α
x✝ : [] ~ x :: l
p : [] ~ x :: l := x✝
⊢ False
[PROOFSTEP]
injection p.symm.eq_nil
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a : α
l : List α
⊢ reverse (a :: l) ~ a :: l
[PROOFSTEP]
rw [reverse_cons]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a : α
l : List α
⊢ reverse l ++ [a] ~ a :: l
[PROOFSTEP]
exact (perm_append_singleton _ _).trans ((reverse_perm l).cons a)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b : α
⊢ [a] ~ [b] ↔ a = b
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option β
l₁ l₂ : List α
p : l₁ ~ l₂
⊢ List.filterMap f l₁ ~ List.filterMap f l₂
[PROOFSTEP]
induction p with
| nil => simp
| cons x _p IH => cases h : f x <;> simp [h, filterMap, IH, Perm.cons]
| swap x y l₂ => cases hx : f x <;> cases hy : f y <;> simp [hx, hy, filterMap, swap]
| trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option β
l₁ l₂ : List α
p : l₁ ~ l₂
⊢ List.filterMap f l₁ ~ List.filterMap f l₂
[PROOFSTEP]
induction p with
| nil => simp
| cons x _p IH => cases h : f x <;> simp [h, filterMap, IH, Perm.cons]
| swap x y l₂ => cases hx : f x <;> cases hy : f y <;> simp [hx, hy, filterMap, swap]
| trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option β
l₁ l₂ : List α
⊢ List.filterMap f [] ~ List.filterMap f []
[PROOFSTEP]

| nil => simp
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option β
l₁ l₂ : List α
⊢ List.filterMap f [] ~ List.filterMap f []
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
⊢ List.filterMap f (x :: l₁✝) ~ List.filterMap f (x :: l₂✝)
[PROOFSTEP]

| cons x _p IH => cases h : f x <;> simp [h, filterMap, IH, Perm.cons]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
⊢ List.filterMap f (x :: l₁✝) ~ List.filterMap f (x :: l₂✝)
[PROOFSTEP]
cases h : f x
[GOAL]
case cons.none
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
h : f x = none
⊢ List.filterMap f (x :: l₁✝) ~ List.filterMap f (x :: l₂✝)
[PROOFSTEP]
simp [h, filterMap, IH, Perm.cons]
[GOAL]
case cons.some
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
val✝ : β
h : f x = some val✝
⊢ List.filterMap f (x :: l₁✝) ~ List.filterMap f (x :: l₂✝)
[PROOFSTEP]
simp [h, filterMap, IH, Perm.cons]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]

| swap x y l₂ => cases hx : f x <;> cases hy : f y <;> simp [hx, hy, filterMap, swap]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
cases hx : f x
[GOAL]
case swap.none
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
hx : f x = none
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
cases hy : f y
[GOAL]
case swap.some
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
val✝ : β
hx : f x = some val✝
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
cases hy : f y
[GOAL]
case swap.none.none
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
hx : f x = none
hy : f y = none
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
simp [hx, hy, filterMap, swap]
[GOAL]
case swap.none.some
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
hx : f x = none
val✝ : β
hy : f y = some val✝
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
simp [hx, hy, filterMap, swap]
[GOAL]
case swap.some.none
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
val✝ : β
hx : f x = some val✝
hy : f y = none
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
simp [hx, hy, filterMap, swap]
[GOAL]
case swap.some.some
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
f : α → Option β
l₁ l₂✝ : List α
x y : α
l₂ : List α
val✝¹ : β
hx : f x = some val✝¹
val✝ : β
hy : f y = some val✝
⊢ List.filterMap f (y :: x :: l₂) ~ List.filterMap f (x :: y :: l₂)
[PROOFSTEP]
simp [hx, hy, filterMap, swap]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
_p₁ : l₁✝ ~ l₂✝
_p₂ : l₂✝ ~ l₃✝
IH₁ : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
IH₂ : List.filterMap f l₂✝ ~ List.filterMap f l₃✝
⊢ List.filterMap f l₁✝ ~ List.filterMap f l₃✝
[PROOFSTEP]

| trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option β
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
_p₁ : l₁✝ ~ l₂✝
_p₂ : l₂✝ ~ l₃✝
IH₁ : List.filterMap f l₁✝ ~ List.filterMap f l₂✝
IH₂ : List.filterMap f l₂✝ ~ List.filterMap f l₃✝
⊢ List.filterMap f l₁✝ ~ List.filterMap f l₃✝
[PROOFSTEP]
exact IH₁.trans IH₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p✝ : α → Prop
f : (a : α) → p✝ a → β
l₁ l₂ : List α
p : l₁ ~ l₂
H₁ : ∀ (a : α), a ∈ l₁ → p✝ a
H₂ : ∀ (a : α), a ∈ l₂ → p✝ a
⊢ List.pmap f l₁ H₁ ~ List.pmap f l₂ H₂
[PROOFSTEP]
induction p with
| nil => simp
| cons x _p IH => simp [IH, Perm.cons]
| swap x y => simp [swap]
| trans _p₁ p₂ IH₁ IH₂ =>
  refine' IH₁.trans IH₂
  exact fun a m => H₂ a (p₂.subset m)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p✝ : α → Prop
f : (a : α) → p✝ a → β
l₁ l₂ : List α
p : l₁ ~ l₂
H₁ : ∀ (a : α), a ∈ l₁ → p✝ a
H₂ : ∀ (a : α), a ∈ l₂ → p✝ a
⊢ List.pmap f l₁ H₁ ~ List.pmap f l₂ H₂
[PROOFSTEP]
induction p with
| nil => simp
| cons x _p IH => simp [IH, Perm.cons]
| swap x y => simp [swap]
| trans _p₁ p₂ IH₁ IH₂ =>
  refine' IH₁.trans IH₂
  exact fun a m => H₂ a (p₂.subset m)
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
H₁ H₂ : ∀ (a : α), a ∈ [] → p a
⊢ List.pmap f [] H₁ ~ List.pmap f [] H₂
[PROOFSTEP]

| nil => simp
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
H₁ H₂ : ∀ (a : α), a ∈ [] → p a
⊢ List.pmap f [] H₁ ~ List.pmap f [] H₂
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : ∀ {H₁ : ∀ (a : α), a ∈ l₁✝ → p a} {H₂ : ∀ (a : α), a ∈ l₂✝ → p a}, List.pmap f l₁✝ H₁ ~ List.pmap f l₂✝ H₂
H₁ : ∀ (a : α), a ∈ x :: l₁✝ → p a
H₂ : ∀ (a : α), a ∈ x :: l₂✝ → p a
⊢ List.pmap f (x :: l₁✝) H₁ ~ List.pmap f (x :: l₂✝) H₂
[PROOFSTEP]

| cons x _p IH => simp [IH, Perm.cons]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
x : α
l₁✝ l₂✝ : List α
_p : l₁✝ ~ l₂✝
IH : ∀ {H₁ : ∀ (a : α), a ∈ l₁✝ → p a} {H₂ : ∀ (a : α), a ∈ l₂✝ → p a}, List.pmap f l₁✝ H₁ ~ List.pmap f l₂✝ H₂
H₁ : ∀ (a : α), a ∈ x :: l₁✝ → p a
H₂ : ∀ (a : α), a ∈ x :: l₂✝ → p a
⊢ List.pmap f (x :: l₁✝) H₁ ~ List.pmap f (x :: l₂✝) H₂
[PROOFSTEP]
simp [IH, Perm.cons]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
x y : α
l✝ : List α
H₁ : ∀ (a : α), a ∈ y :: x :: l✝ → p a
H₂ : ∀ (a : α), a ∈ x :: y :: l✝ → p a
⊢ List.pmap f (y :: x :: l✝) H₁ ~ List.pmap f (x :: y :: l✝) H₂
[PROOFSTEP]

| swap x y => simp [swap]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ : List α
x y : α
l✝ : List α
H₁ : ∀ (a : α), a ∈ y :: x :: l✝ → p a
H₂ : ∀ (a : α), a ∈ x :: y :: l✝ → p a
⊢ List.pmap f (y :: x :: l✝) H₁ ~ List.pmap f (x :: y :: l✝) H₂
[PROOFSTEP]
simp [swap]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
_p₁ : l₁✝ ~ l₂✝
p₂ : l₂✝ ~ l₃✝
IH₁ : ∀ {H₁ : ∀ (a : α), a ∈ l₁✝ → p a} {H₂ : ∀ (a : α), a ∈ l₂✝ → p a}, List.pmap f l₁✝ H₁ ~ List.pmap f l₂✝ H₂
IH₂ : ∀ {H₁ : ∀ (a : α), a ∈ l₂✝ → p a} {H₂ : ∀ (a : α), a ∈ l₃✝ → p a}, List.pmap f l₂✝ H₁ ~ List.pmap f l₃✝ H₂
H₁ : ∀ (a : α), a ∈ l₁✝ → p a
H₂ : ∀ (a : α), a ∈ l₃✝ → p a
⊢ List.pmap f l₁✝ H₁ ~ List.pmap f l₃✝ H₂
[PROOFSTEP]

| trans _p₁ p₂ IH₁ IH₂ =>
  refine' IH₁.trans IH₂
  exact fun a m => H₂ a (p₂.subset m)
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
_p₁ : l₁✝ ~ l₂✝
p₂ : l₂✝ ~ l₃✝
IH₁ : ∀ {H₁ : ∀ (a : α), a ∈ l₁✝ → p a} {H₂ : ∀ (a : α), a ∈ l₂✝ → p a}, List.pmap f l₁✝ H₁ ~ List.pmap f l₂✝ H₂
IH₂ : ∀ {H₁ : ∀ (a : α), a ∈ l₂✝ → p a} {H₂ : ∀ (a : α), a ∈ l₃✝ → p a}, List.pmap f l₂✝ H₁ ~ List.pmap f l₃✝ H₂
H₁ : ∀ (a : α), a ∈ l₁✝ → p a
H₂ : ∀ (a : α), a ∈ l₃✝ → p a
⊢ List.pmap f l₁✝ H₁ ~ List.pmap f l₃✝ H₂
[PROOFSTEP]
refine' IH₁.trans IH₂
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
p : α → Prop
f : (a : α) → p a → β
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
_p₁ : l₁✝ ~ l₂✝
p₂ : l₂✝ ~ l₃✝
IH₁ : ∀ {H₁ : ∀ (a : α), a ∈ l₁✝ → p a} {H₂ : ∀ (a : α), a ∈ l₂✝ → p a}, List.pmap f l₁✝ H₁ ~ List.pmap f l₂✝ H₂
IH₂ : ∀ {H₁ : ∀ (a : α), a ∈ l₂✝ → p a} {H₂ : ∀ (a : α), a ∈ l₃✝ → p a}, List.pmap f l₂✝ H₁ ~ List.pmap f l₃✝ H₂
H₁ : ∀ (a : α), a ∈ l₁✝ → p a
H₂ : ∀ (a : α), a ∈ l₃✝ → p a
⊢ ∀ (a : α), a ∈ l₂✝ → p a
[PROOFSTEP]
exact fun a m => H₂ a (p₂.subset m)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Bool
l₁ l₂ : List α
s : l₁ ~ l₂
⊢ List.filter p l₁ ~ List.filter p l₂
[PROOFSTEP]
rw [← filterMap_eq_filter]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Bool
l₁ l₂ : List α
s : l₁ ~ l₂
⊢ List.filterMap (Option.guard fun x => p x = true) l₁ ~ List.filterMap (Option.guard fun x => p x = true) l₂
[PROOFSTEP]
apply s.filterMap _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
[PROOFSTEP]
induction' l with x l ih
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
⊢ filter p [] ++ filter (fun x => decide ¬p x = true) [] ~ []
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
⊢ filter p (x :: l) ++ filter (fun x => decide ¬p x = true) (x :: l) ~ x :: l
[PROOFSTEP]
by_cases h : p x
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
h : p x = true
⊢ filter p (x :: l) ++ filter (fun x => decide ¬p x = true) (x :: l) ~ x :: l
[PROOFSTEP]
simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
h : p x = true
⊢ x :: (filter p l ++ filter (fun x => decide ¬p x = true) l) ~ x :: l
[PROOFSTEP]
exact ih.cons x
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
h : ¬p x = true
⊢ filter p (x :: l) ++ filter (fun x => decide ¬p x = true) (x :: l) ~ x :: l
[PROOFSTEP]
simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
h : ¬p x = true
⊢ filter p l ++ x :: filter (fun x => decide ¬p x = true) l ~ x :: l
[PROOFSTEP]
refine' Perm.trans _ (ih.cons x)
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
x : α
l : List α
ih : filter p l ++ filter (fun x => decide ¬p x = true) l ~ l
h : ¬p x = true
⊢ filter p l ++ x :: filter (fun x => decide ¬p x = true) l ~
    x :: (filter p l ++ filter (fun x => decide ¬p x = true) l)
[PROOFSTEP]
exact perm_append_comm.trans (perm_append_comm.cons _)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l₂' : List α
s : l₁ <+ l₂
p : l₂ ~ l₂'
⊢ ∃ l₁' x, l₁' <+ l₂'
[PROOFSTEP]
induction p generalizing l₁ with
| nil => exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
| cons x _ IH =>
  cases' s with _ _ _ s l₁ _ _ s
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨l₁', p', s'.cons _⟩
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
| swap x y _ =>
  cases' s with _ _ _ s l₁ _ _ s <;> cases' s with _ _ _ s l₁ _ _ s
  · exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
  · exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
  · exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
  · exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
| trans _ _ IH₁ IH₂ =>
  exact
    let ⟨m₁, pm, sm⟩ := IH₁ s
    let ⟨r₁, pr, sr⟩ := IH₂ sm
    ⟨r₁, pr.trans pm, sr⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l₂' : List α
s : l₁ <+ l₂
p : l₂ ~ l₂'
⊢ ∃ l₁' x, l₁' <+ l₂'
[PROOFSTEP]
induction p generalizing l₁ with
| nil => exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
| cons x _ IH =>
  cases' s with _ _ _ s l₁ _ _ s
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨l₁', p', s'.cons _⟩
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
| swap x y _ =>
  cases' s with _ _ _ s l₁ _ _ s <;> cases' s with _ _ _ s l₁ _ _ s
  · exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
  · exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
  · exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
  · exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
| trans _ _ IH₁ IH₂ =>
  exact
    let ⟨m₁, pm, sm⟩ := IH₁ s
    let ⟨r₁, pr, sr⟩ := IH₂ sm
    ⟨r₁, pr.trans pm, sr⟩
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' l₁ : List α
s : l₁ <+ []
⊢ ∃ l₁' x, l₁' <+ []
[PROOFSTEP]

| nil => exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' l₁ : List α
s : l₁ <+ []
⊢ ∃ l₁' x, l₁' <+ []
[PROOFSTEP]
exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
IH : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
l₁ : List α
s : l₁ <+ x :: l₁✝
⊢ ∃ l₁' x_1, l₁' <+ x :: l₂✝
[PROOFSTEP]

| cons x _ IH =>
  cases' s with _ _ _ s l₁ _ _ s
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨l₁', p', s'.cons _⟩
  ·
    exact
      let ⟨l₁', p', s'⟩ := IH s
      ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
IH : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
l₁ : List α
s : l₁ <+ x :: l₁✝
⊢ ∃ l₁' x_1, l₁' <+ x :: l₂✝
[PROOFSTEP]
cases' s with _ _ _ s l₁ _ _ s
[GOAL]
case cons.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
IH : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
l₁ : List α
s : l₁ <+ l₁✝
⊢ ∃ l₁' x_1, l₁' <+ x :: l₂✝
[PROOFSTEP]
exact
  let ⟨l₁', p', s'⟩ := IH s
  ⟨l₁', p', s'.cons _⟩
[GOAL]
case cons.cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
IH : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
l₁ : List α
s : l₁ <+ l₁✝
⊢ ∃ l₁' x_1, l₁' <+ x :: l₂✝
[PROOFSTEP]
exact
  let ⟨l₁', p', s'⟩ := IH s
  ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ y :: x :: l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]

| swap x y _ =>
  cases' s with _ _ _ s l₁ _ _ s <;> cases' s with _ _ _ s l₁ _ _ s
  · exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
  · exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
  · exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
  · exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ y :: x :: l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
cases' s with _ _ _ s l₁ _ _ s
[GOAL]
case swap.cons
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ x :: l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
cases' s with _ _ _ s l₁ _ _ s
[GOAL]
case swap.cons₂
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ x :: l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
cases' s with _ _ _ s l₁ _ _ s
[GOAL]
case swap.cons.cons
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
[GOAL]
case swap.cons.cons₂
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
[GOAL]
case swap.cons₂.cons
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
[GOAL]
case swap.cons₂.cons₂
α : Type uu
β : Type vv
l₁✝ l₂✝ l₂ l₂' : List α
x y : α
l✝ l₁ : List α
s : l₁ <+ l✝
⊢ ∃ l₁' x_1, l₁' <+ x :: y :: l✝
[PROOFSTEP]
exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
IH₁ : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
IH₂ : ∀ {l₁ : List α}, l₁ <+ l₂✝ → ∃ l₁' x, l₁' <+ l₃✝
l₁ : List α
s : l₁ <+ l₁✝
⊢ ∃ l₁' x, l₁' <+ l₃✝
[PROOFSTEP]

| trans _ _ IH₁ IH₂ =>
  exact
    let ⟨m₁, pm, sm⟩ := IH₁ s
    let ⟨r₁, pr, sr⟩ := IH₂ sm
    ⟨r₁, pr.trans pm, sr⟩
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₂ l₂' l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
IH₁ : ∀ {l₁ : List α}, l₁ <+ l₁✝ → ∃ l₁' x, l₁' <+ l₂✝
IH₂ : ∀ {l₁ : List α}, l₁ <+ l₂✝ → ∃ l₁' x, l₁' <+ l₃✝
l₁ : List α
s : l₁ <+ l₁✝
⊢ ∃ l₁' x, l₁' <+ l₃✝
[PROOFSTEP]
exact
  let ⟨m₁, pm, sm⟩ := IH₁ s
  let ⟨r₁, pr, sr⟩ := IH₂ sm
  ⟨r₁, pr.trans pm, sr⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
h : l₁ ~ l₂
⊢ sizeOf l₁ = sizeOf l₂
[PROOFSTEP]
induction h with
  -- hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
| nil => rfl
| cons _ _ h_sz₁₂ => simp [h_sz₁₂]
| swap => simp [add_left_comm]
| trans _ _ h_sz₁₂ h_sz₂₃ => simp [h_sz₁₂, h_sz₂₃]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
h : l₁ ~ l₂
⊢ sizeOf l₁ = sizeOf l₂
[PROOFSTEP]
induction h with
  -- hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
| nil => rfl
| cons _ _ h_sz₁₂ => simp [h_sz₁₂]
| swap => simp [add_left_comm]
| trans _ _ h_sz₁₂ h_sz₂₃ => simp [h_sz₁₂, h_sz₂₃]
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
⊢ sizeOf [] = sizeOf []
[PROOFSTEP]

| nil => rfl
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
⊢ sizeOf [] = sizeOf []
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
h_sz₁₂ : sizeOf l₁✝ = sizeOf l₂✝
⊢ sizeOf (x✝ :: l₁✝) = sizeOf (x✝ :: l₂✝)
[PROOFSTEP]

| cons _ _ h_sz₁₂ => simp [h_sz₁₂]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
h_sz₁₂ : sizeOf l₁✝ = sizeOf l₂✝
⊢ sizeOf (x✝ :: l₁✝) = sizeOf (x✝ :: l₂✝)
[PROOFSTEP]
simp [h_sz₁₂]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
x✝ y✝ : α
l✝ : List α
⊢ sizeOf (y✝ :: x✝ :: l✝) = sizeOf (x✝ :: y✝ :: l✝)
[PROOFSTEP]

| swap => simp [add_left_comm]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : SizeOf α
l₁ l₂ : List α
x✝ y✝ : α
l✝ : List α
⊢ sizeOf (y✝ :: x✝ :: l✝) = sizeOf (x✝ :: y✝ :: l✝)
[PROOFSTEP]
simp [add_left_comm]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : SizeOf α
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
h_sz₁₂ : sizeOf l₁✝ = sizeOf l₂✝
h_sz₂₃ : sizeOf l₂✝ = sizeOf l₃✝
⊢ sizeOf l₁✝ = sizeOf l₃✝
[PROOFSTEP]

| trans _ _ h_sz₁₂ h_sz₂₃ => simp [h_sz₁₂, h_sz₂₃]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : SizeOf α
l₁ l₂ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
h_sz₁₂ : sizeOf l₁✝ = sizeOf l₂✝
h_sz₂₃ : sizeOf l₂✝ = sizeOf l₃✝
⊢ sizeOf l₁✝ = sizeOf l₃✝
[PROOFSTEP]
simp [h_sz₁₂, h_sz₂₃]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
⊢ Perm ∘r Perm = Perm
[PROOFSTEP]
funext a c
[GOAL]
case h.h
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
a c : List α
⊢ (Perm ∘r Perm) a c = (a ~ c)
[PROOFSTEP]
apply propext
[GOAL]
case h.h.a
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
a c : List α
⊢ (Perm ∘r Perm) a c ↔ a ~ c
[PROOFSTEP]
constructor
[GOAL]
case h.h.a.mp
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
a c : List α
⊢ (Perm ∘r Perm) a c → a ~ c
[PROOFSTEP]
exact fun ⟨b, hab, hba⟩ => Perm.trans hab hba
[GOAL]
case h.h.a.mpr
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
a c : List α
⊢ a ~ c → (Perm ∘r Perm) a c
[PROOFSTEP]
exact fun h => ⟨a, Perm.refl a, h⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
v : List β
hlu : l ~ u
huv : Forall₂ r u v
⊢ (Forall₂ r ∘r Perm) l v
[PROOFSTEP]
induction hlu generalizing v
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
v : List β
huv : Forall₂ r [] v
⊢ (Forall₂ r ∘r Perm) [] v
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
v : List β
huv : Forall₂ r (x✝ :: l₂✝) v
⊢ (Forall₂ r ∘r Perm) (x✝ :: l₁✝) v
case swap
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
x✝ y✝ : α
l✝ : List α
v : List β
huv : Forall₂ r (x✝ :: y✝ :: l✝) v
⊢ (Forall₂ r ∘r Perm) (y✝ :: x✝ :: l✝) v
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
a_ih✝ : ∀ {v : List β}, Forall₂ r l₃✝ v → (Forall₂ r ∘r Perm) l₂✝ v
v : List β
huv : Forall₂ r l₃✝ v
⊢ (Forall₂ r ∘r Perm) l₁✝ v
[PROOFSTEP]
case nil => cases huv; exact ⟨[], Forall₂.nil, Perm.nil⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
v : List β
huv : Forall₂ r [] v
⊢ (Forall₂ r ∘r Perm) [] v
[PROOFSTEP]
case nil => cases huv; exact ⟨[], Forall₂.nil, Perm.nil⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
v : List β
huv : Forall₂ r [] v
⊢ (Forall₂ r ∘r Perm) [] v
[PROOFSTEP]
cases huv
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
⊢ (Forall₂ r ∘r Perm) [] []
[PROOFSTEP]
exact ⟨[], Forall₂.nil, Perm.nil⟩
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
v : List β
huv : Forall₂ r (x✝ :: l₂✝) v
⊢ (Forall₂ r ∘r Perm) (x✝ :: l₁✝) v
case swap
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
x✝ y✝ : α
l✝ : List α
v : List β
huv : Forall₂ r (x✝ :: y✝ :: l✝) v
⊢ (Forall₂ r ∘r Perm) (y✝ :: x✝ :: l✝) v
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
a_ih✝ : ∀ {v : List β}, Forall₂ r l₃✝ v → (Forall₂ r ∘r Perm) l₂✝ v
v : List β
huv : Forall₂ r l₃✝ v
⊢ (Forall₂ r ∘r Perm) l₁✝ v
[PROOFSTEP]
case cons a l u _hlu ih =>
  cases' huv with _ b _ v hab huv'
  rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩
  exact ⟨b :: l₂, Forall₂.cons hab h₁₂, h₂₃.cons _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l✝ u✝ : List α
a : α
l u : List α
_hlu : l ~ u
ih : ∀ {v : List β}, Forall₂ r u v → (Forall₂ r ∘r Perm) l v
v : List β
huv : Forall₂ r (a :: u) v
⊢ (Forall₂ r ∘r Perm) (a :: l) v
[PROOFSTEP]
case cons a l u _hlu ih =>
  cases' huv with _ b _ v hab huv'
  rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩
  exact ⟨b :: l₂, Forall₂.cons hab h₁₂, h₂₃.cons _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l✝ u✝ : List α
a : α
l u : List α
_hlu : l ~ u
ih : ∀ {v : List β}, Forall₂ r u v → (Forall₂ r ∘r Perm) l v
v : List β
huv : Forall₂ r (a :: u) v
⊢ (Forall₂ r ∘r Perm) (a :: l) v
[PROOFSTEP]
cases' huv with _ b _ v hab huv'
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l✝ u✝ : List α
a : α
l u : List α
_hlu : l ~ u
ih : ∀ {v : List β}, Forall₂ r u v → (Forall₂ r ∘r Perm) l v
b : β
v : List β
hab : r a b
huv' : Forall₂ r u v
⊢ (Forall₂ r ∘r Perm) (a :: l) (b :: v)
[PROOFSTEP]
rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩
[GOAL]
case cons.intro.intro
α : Type uu
β : Type vv
l₁ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l✝ u✝ : List α
a : α
l u : List α
_hlu : l ~ u
ih : ∀ {v : List β}, Forall₂ r u v → (Forall₂ r ∘r Perm) l v
b : β
v : List β
hab : r a b
huv' : Forall₂ r u v
l₂ : List β
h₁₂ : Forall₂ r l l₂
h₂₃ : l₂ ~ v
⊢ (Forall₂ r ∘r Perm) (a :: l) (b :: v)
[PROOFSTEP]
exact ⟨b :: l₂, Forall₂.cons hab h₁₂, h₂₃.cons _⟩
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
x✝ y✝ : α
l✝ : List α
v : List β
huv : Forall₂ r (x✝ :: y✝ :: l✝) v
⊢ (Forall₂ r ∘r Perm) (y✝ :: x✝ :: l✝) v
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
a_ih✝ : ∀ {v : List β}, Forall₂ r l₃✝ v → (Forall₂ r ∘r Perm) l₂✝ v
v : List β
huv : Forall₂ r l₃✝ v
⊢ (Forall₂ r ∘r Perm) l₁✝ v
[PROOFSTEP]
case swap a₁ a₂ h₂₃ =>
  cases' huv with _ b₁ _ l₂ h₁ hr₂₃
  cases' hr₂₃ with _ b₂ _ l₂ h₂ h₁₂
  exact ⟨b₂ :: b₁ :: l₂, Forall₂.cons h₂ (Forall₂.cons h₁ h₁₂), Perm.swap _ _ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
a₁ a₂ : α
h₂₃ : List α
v : List β
huv : Forall₂ r (a₁ :: a₂ :: h₂₃) v
⊢ (Forall₂ r ∘r Perm) (a₂ :: a₁ :: h₂₃) v
[PROOFSTEP]
case swap a₁ a₂ h₂₃ =>
  cases' huv with _ b₁ _ l₂ h₁ hr₂₃
  cases' hr₂₃ with _ b₂ _ l₂ h₂ h₁₂
  exact ⟨b₂ :: b₁ :: l₂, Forall₂.cons h₂ (Forall₂.cons h₁ h₁₂), Perm.swap _ _ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
a₁ a₂ : α
h₂₃ : List α
v : List β
huv : Forall₂ r (a₁ :: a₂ :: h₂₃) v
⊢ (Forall₂ r ∘r Perm) (a₂ :: a₁ :: h₂₃) v
[PROOFSTEP]
cases' huv with _ b₁ _ l₂ h₁ hr₂₃
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
a₁ a₂ : α
h₂₃ : List α
b₁ : β
l₂ : List β
h₁ : r a₁ b₁
hr₂₃ : Forall₂ r (a₂ :: h₂₃) l₂
⊢ (Forall₂ r ∘r Perm) (a₂ :: a₁ :: h₂₃) (b₁ :: l₂)
[PROOFSTEP]
cases' hr₂₃ with _ b₂ _ l₂ h₂ h₁₂
[GOAL]
case cons.cons
α : Type uu
β : Type vv
l₁ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u : List α
a₁ a₂ : α
h₂₃ : List α
b₁ : β
h₁ : r a₁ b₁
b₂ : β
l₂ : List β
h₂ : r a₂ b₂
h₁₂ : Forall₂ r h₂₃ l₂
⊢ (Forall₂ r ∘r Perm) (a₂ :: a₁ :: h₂₃) (b₁ :: b₂ :: l₂)
[PROOFSTEP]
exact ⟨b₂ :: b₁ :: l₂, Forall₂.cons h₂ (Forall₂.cons h₁ h₁₂), Perm.swap _ _ _⟩
[GOAL]
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ {v : List β}, Forall₂ r l₂✝ v → (Forall₂ r ∘r Perm) l₁✝ v
a_ih✝ : ∀ {v : List β}, Forall₂ r l₃✝ v → (Forall₂ r ∘r Perm) l₂✝ v
v : List β
huv : Forall₂ r l₃✝ v
⊢ (Forall₂ r ∘r Perm) l₁✝ v
[PROOFSTEP]
case trans la₁ la₂ la₃ _ _ ih₁ ih₂ =>
  rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
  rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
  exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u la₁ la₂ la₃ : List α
a✝¹ : la₁ ~ la₂
a✝ : la₂ ~ la₃
ih₁ : ∀ {v : List β}, Forall₂ r la₂ v → (Forall₂ r ∘r Perm) la₁ v
ih₂ : ∀ {v : List β}, Forall₂ r la₃ v → (Forall₂ r ∘r Perm) la₂ v
v : List β
huv : Forall₂ r la₃ v
⊢ (Forall₂ r ∘r Perm) la₁ v
[PROOFSTEP]
case trans la₁ la₂ la₃ _ _ ih₁ ih₂ =>
  rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
  rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
  exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u la₁ la₂ la₃ : List α
a✝¹ : la₁ ~ la₂
a✝ : la₂ ~ la₃
ih₁ : ∀ {v : List β}, Forall₂ r la₂ v → (Forall₂ r ∘r Perm) la₁ v
ih₂ : ∀ {v : List β}, Forall₂ r la₃ v → (Forall₂ r ∘r Perm) la₂ v
v : List β
huv : Forall₂ r la₃ v
⊢ (Forall₂ r ∘r Perm) la₁ v
[PROOFSTEP]
rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u la₁ la₂ la₃ : List α
a✝¹ : la₁ ~ la₂
a✝ : la₂ ~ la₃
ih₁ : ∀ {v : List β}, Forall₂ r la₂ v → (Forall₂ r ∘r Perm) la₁ v
ih₂ : ∀ {v : List β}, Forall₂ r la₃ v → (Forall₂ r ∘r Perm) la₂ v
v : List β
huv : Forall₂ r la₃ v
lb₂ : List β
hab₂ : Forall₂ r la₂ lb₂
h₂₃ : lb₂ ~ v
⊢ (Forall₂ r ∘r Perm) la₁ v
[PROOFSTEP]
rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
[GOAL]
case intro.intro.intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l u la₁ la₂ la₃ : List α
a✝¹ : la₁ ~ la₂
a✝ : la₂ ~ la₃
ih₁ : ∀ {v : List β}, Forall₂ r la₂ v → (Forall₂ r ∘r Perm) la₁ v
ih₂ : ∀ {v : List β}, Forall₂ r la₃ v → (Forall₂ r ∘r Perm) la₂ v
v : List β
huv : Forall₂ r la₃ v
lb₂ : List β
hab₂ : Forall₂ r la₂ lb₂
h₂₃ : lb₂ ~ v
lb₁ : List β
hab₁ : Forall₂ r la₁ lb₁
h₁₂ : lb₁ ~ lb₂
⊢ (Forall₂ r ∘r Perm) la₁ v
[PROOFSTEP]
exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
⊢ Forall₂ r ∘r Perm = Perm ∘r Forall₂ r
[PROOFSTEP]
funext l₁ l₃
[GOAL]
case h.h
α : Type uu
β : Type vv
l₁✝ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ : List β
⊢ (Forall₂ r ∘r Perm) l₁ l₃ = (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
apply propext
[GOAL]
case h.h.a
α : Type uu
β : Type vv
l₁✝ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ : List β
⊢ (Forall₂ r ∘r Perm) l₁ l₃ ↔ (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
constructor
[GOAL]
case h.h.a.mp
α : Type uu
β : Type vv
l₁✝ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ : List β
⊢ (Forall₂ r ∘r Perm) l₁ l₃ → (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
intro h
[GOAL]
case h.h.a.mp
α : Type uu
β : Type vv
l₁✝ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ : List β
h : (Forall₂ r ∘r Perm) l₁ l₃
⊢ (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
rcases h with ⟨l₂, h₁₂, h₂₃⟩
[GOAL]
case h.h.a.mp.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ l₂ : List β
h₁₂ : Forall₂ r l₁ l₂
h₂₃ : l₂ ~ l₃
⊢ (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
have : Forall₂ (flip r) l₂ l₁ := h₁₂.flip
[GOAL]
case h.h.a.mp.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ l₂ : List β
h₁₂ : Forall₂ r l₁ l₂
h₂₃ : l₂ ~ l₃
this : Forall₂ (flip r) l₂ l₁
⊢ (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
rcases perm_comp_forall₂ h₂₃.symm this with ⟨l', h₁, h₂⟩
[GOAL]
case h.h.a.mp.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ l₂ : List β
h₁₂ : Forall₂ r l₁ l₂
h₂₃ : l₂ ~ l₃
this : Forall₂ (flip r) l₂ l₁
l' : List α
h₁ : Forall₂ (flip r) l₃ l'
h₂ : l' ~ l₁
⊢ (Perm ∘r Forall₂ r) l₁ l₃
[PROOFSTEP]
exact ⟨l', h₂.symm, h₁.flip⟩
[GOAL]
case h.h.a.mpr
α : Type uu
β : Type vv
l₁✝ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
l₁ : List α
l₃ : List β
⊢ (Perm ∘r Forall₂ r) l₁ l₃ → (Forall₂ r ∘r Perm) l₁ l₃
[PROOFSTEP]
exact fun ⟨l₂, h₁₂, h₂₃⟩ => perm_comp_forall₂ h₁₂ h₂₃
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
γ : Type u_1
δ : Type u_2
r : α → β → Prop
p : γ → δ → Prop
hr : RightUnique r
a : List α
b : List β
h₁ : Forall₂ r a b
c : List α
d : List β
h₂ : Forall₂ r c d
h : a ~ c
this : (flip (Forall₂ r) ∘r Perm ∘r Forall₂ r) b d
⊢ ((flip (Forall₂ r) ∘r Forall₂ r) ∘r Perm) b d
[PROOFSTEP]
rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this 
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
⊢ [] <+ l
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
l l' : List α
h : l <+~ l'
⊢ List.filter p l <+~ List.filter p l'
[PROOFSTEP]
obtain ⟨xs, hp, h⟩ := h
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
p : α → Bool
l l' xs : List α
hp : xs ~ l
h : xs <+ l'
⊢ List.filter p l <+~ List.filter p l'
[PROOFSTEP]
exact ⟨_, hp.filter p, h.filter p⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Bool
l₁ l₂ : List α
s : l₁ ~ l₂
⊢ countp p l₁ = countp p l₂
[PROOFSTEP]
rw [countp_eq_length_filter, countp_eq_length_filter]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
p : α → Bool
l₁ l₂ : List α
s : l₁ ~ l₂
⊢ length (List.filter p l₁) = length (List.filter p l₂)
[PROOFSTEP]
exact (s.filter _).length_eq
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
s : l₁ ~ l₂
p p' : α → Bool
hp : ∀ (x : α), x ∈ l₁ → p x = p' x
⊢ countp p l₁ = countp p' l₂
[PROOFSTEP]
rw [← s.countp_eq p']
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
s : l₁ ~ l₂
p p' : α → Bool
hp : ∀ (x : α), x ∈ l₁ → p x = p' x
⊢ countp p l₁ = countp p' l₁
[PROOFSTEP]
clear s
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
p p' : α → Bool
hp : ∀ (x : α), x ∈ l₁ → p x = p' x
⊢ countp p l₁ = countp p' l₁
[PROOFSTEP]
induction' l₁ with y s hs
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
p p' : α → Bool
hp✝ : ∀ (x : α), x ∈ l₁ → p x = p' x
hp : ∀ (x : α), x ∈ [] → p x = p' x
⊢ countp p [] = countp p' []
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
p p' : α → Bool
hp✝ : ∀ (x : α), x ∈ l₁ → p x = p' x
y : α
s : List α
hs : (∀ (x : α), x ∈ s → p x = p' x) → countp p s = countp p' s
hp : ∀ (x : α), x ∈ y :: s → p x = p' x
⊢ countp p (y :: s) = countp p' (y :: s)
[PROOFSTEP]
simp only [mem_cons, forall_eq_or_imp] at hp 
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
p p' : α → Bool
hp✝ : ∀ (x : α), x ∈ l₁ → p x = p' x
y : α
s : List α
hs : (∀ (x : α), x ∈ s → p x = p' x) → countp p s = countp p' s
hp : p y = p' y ∧ ∀ (a : α), a ∈ s → p a = p' a
⊢ countp p (y :: s) = countp p' (y :: s)
[PROOFSTEP]
simp only [countp_cons, hs hp.2, hp.1]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
p q : α → Bool
⊢ countp p l = countp p (filter q l) + countp p (filter (fun a => decide ¬q a = true) l)
[PROOFSTEP]
rw [← countp_append]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
p q : α → Bool
⊢ countp p l = countp p (filter q l ++ filter (fun a => decide ¬q a = true) l)
[PROOFSTEP]
exact Perm.countp_eq _ (filter_append_perm _ _).symm
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : β → α → β
l₁ l₂ : List α
p : l₁ ~ l₂
x y : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r :
  (∀ (x : α), x ∈ t₁ → ∀ (y : α), y ∈ t₁ → ∀ (z : β), f (f z x) y = f (f z y) x) →
    ∀ (b : β), foldl f b t₁ = foldl f b t₂
H : ∀ (x_1 : α), x_1 ∈ y :: x :: t₁ → ∀ (y_1 : α), y_1 ∈ y :: x :: t₁ → ∀ (z : β), f (f z x_1) y_1 = f (f z y_1) x_1
b : β
⊢ foldl f b (y :: x :: t₁) = foldl f b (x :: y :: t₂)
[PROOFSTEP]
simp only [foldl]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : β → α → β
l₁ l₂ : List α
p : l₁ ~ l₂
x y : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r :
  (∀ (x : α), x ∈ t₁ → ∀ (y : α), y ∈ t₁ → ∀ (z : β), f (f z x) y = f (f z y) x) →
    ∀ (b : β), foldl f b t₁ = foldl f b t₂
H : ∀ (x_1 : α), x_1 ∈ y :: x :: t₁ → ∀ (y_1 : α), y_1 ∈ y :: x :: t₁ → ∀ (z : β), f (f z x_1) y_1 = f (f z y_1) x_1
b : β
⊢ foldl f (f (f b y) x) t₁ = foldl f (f (f b x) y) t₂
[PROOFSTEP]
rw [H x (.tail _ <| .head _) y (.head _)]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : β → α → β
l₁ l₂ : List α
p : l₁ ~ l₂
x y : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r :
  (∀ (x : α), x ∈ t₁ → ∀ (y : α), y ∈ t₁ → ∀ (z : β), f (f z x) y = f (f z y) x) →
    ∀ (b : β), foldl f b t₁ = foldl f b t₂
H : ∀ (x_1 : α), x_1 ∈ y :: x :: t₁ → ∀ (y_1 : α), y_1 ∈ y :: x :: t₁ → ∀ (z : β), f (f z x_1) y_1 = f (f z y_1) x_1
b : β
⊢ foldl f (f (f b y) x) t₁ = foldl f (f (f b y) x) t₂
[PROOFSTEP]
exact r (fun x hx y hy => H _ (.tail _ <| .tail _ hx) _ (.tail _ <| .tail _ hy)) _
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → β → β
l₁ l₂ : List α
lcomm : LeftCommutative f
p : l₁ ~ l₂
x : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r : ∀ (b : β), foldr f b t₁ = foldr f b t₂
b : β
⊢ foldr f b (x :: t₁) = foldr f b (x :: t₂)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → β → β
l₁ l₂ : List α
lcomm : LeftCommutative f
p : l₁ ~ l₂
x : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r : ∀ (b : β), foldr f b t₁ = foldr f b t₂
b : β
⊢ f x (foldr f b t₁) = f x (foldr f b t₂)
[PROOFSTEP]
rw [r b]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → β → β
l₁ l₂ : List α
lcomm : LeftCommutative f
p : l₁ ~ l₂
x y : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r : ∀ (b : β), foldr f b t₁ = foldr f b t₂
b : β
⊢ foldr f b (y :: x :: t₁) = foldr f b (x :: y :: t₂)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → β → β
l₁ l₂ : List α
lcomm : LeftCommutative f
p : l₁ ~ l₂
x y : α
t₁ t₂ : List α
_p : t₁ ~ t₂
r : ∀ (b : β), foldr f b t₁ = foldr f b t₂
b : β
⊢ f y (f x (foldr f b t₁)) = f x (f y (foldr f b t₂))
[PROOFSTEP]
rw [lcomm, r b]
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
hl : l ~ l'
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
⊢ HEq (List.rec b f l) (List.rec b f l')
[PROOFSTEP]
induction hl
[GOAL]
case nil
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
⊢ HEq (List.rec b f []) (List.rec b f [])
case cons
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
⊢ HEq (List.rec b f (x✝ :: l₁✝)) (List.rec b f (x✝ :: l₂✝))
case swap
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
x✝ y✝ : α
l✝ : List α
⊢ HEq (List.rec b f (y✝ :: x✝ :: l✝)) (List.rec b f (x✝ :: y✝ :: l✝))
case trans
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
a_ih✝ : HEq (List.rec b f l₂✝) (List.rec b f l₃✝)
⊢ HEq (List.rec b f l₁✝) (List.rec b f l₃✝)
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
⊢ HEq (List.rec b f []) (List.rec b f [])
[PROOFSTEP]
case nil => rfl
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
⊢ HEq (List.rec b f []) (List.rec b f [])
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
⊢ HEq (List.rec b f (x✝ :: l₁✝)) (List.rec b f (x✝ :: l₂✝))
case swap
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
x✝ y✝ : α
l✝ : List α
⊢ HEq (List.rec b f (y✝ :: x✝ :: l✝)) (List.rec b f (x✝ :: y✝ :: l✝))
case trans
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
a_ih✝ : HEq (List.rec b f l₂✝) (List.rec b f l₃✝)
⊢ HEq (List.rec b f l₁✝) (List.rec b f l₃✝)
[PROOFSTEP]
case cons a l l' h ih => exact f_congr h ih
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l✝ l'✝ : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
a : α
l l' : List α
h : l ~ l'
ih : HEq (List.rec b f l) (List.rec b f l')
⊢ HEq (List.rec b f (a :: l)) (List.rec b f (a :: l'))
[PROOFSTEP]
case cons a l l' h ih => exact f_congr h ih
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l✝ l'✝ : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
a : α
l l' : List α
h : l ~ l'
ih : HEq (List.rec b f l) (List.rec b f l')
⊢ HEq (List.rec b f (a :: l)) (List.rec b f (a :: l'))
[PROOFSTEP]
exact f_congr h ih
[GOAL]
case swap
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
x✝ y✝ : α
l✝ : List α
⊢ HEq (List.rec b f (y✝ :: x✝ :: l✝)) (List.rec b f (x✝ :: y✝ :: l✝))
case trans
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
a_ih✝ : HEq (List.rec b f l₂✝) (List.rec b f l₃✝)
⊢ HEq (List.rec b f l₁✝) (List.rec b f l₃✝)
[PROOFSTEP]
case swap a a' l => exact f_swap
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l✝ l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
a a' : α
l : List α
⊢ HEq (List.rec b f (a' :: a :: l)) (List.rec b f (a :: a' :: l))
[PROOFSTEP]
case swap a a' l => exact f_swap
[GOAL]
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l✝ l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
a a' : α
l : List α
⊢ HEq (List.rec b f (a' :: a :: l)) (List.rec b f (a :: a' :: l))
[PROOFSTEP]
exact f_swap
[GOAL]
case trans
α : Type uu
β✝ : Type vv
l₁ l₂ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : HEq (List.rec b f l₁✝) (List.rec b f l₂✝)
a_ih✝ : HEq (List.rec b f l₂✝) (List.rec b f l₃✝)
⊢ HEq (List.rec b f l₁✝) (List.rec b f l₃✝)
[PROOFSTEP]
case trans l₁ l₂ l₃ _h₁ _h₂ ih₁ ih₂ => exact HEq.trans ih₁ ih₂
[GOAL]
α : Type uu
β✝ : Type vv
l₁✝ l₂✝ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁ l₂ l₃ : List α
_h₁ : l₁ ~ l₂
_h₂ : l₂ ~ l₃
ih₁ : HEq (List.rec b f l₁) (List.rec b f l₂)
ih₂ : HEq (List.rec b f l₂) (List.rec b f l₃)
⊢ HEq (List.rec b f l₁) (List.rec b f l₃)
[PROOFSTEP]
case trans l₁ l₂ l₃ _h₁ _h₂ ih₁ ih₂ => exact HEq.trans ih₁ ih₂
[GOAL]
α : Type uu
β✝ : Type vv
l₁✝ l₂✝ : List α
β : List α → Sort u_1
f : (a : α) → (l : List α) → β l → β (a :: l)
b : β []
l l' : List α
f_congr : ∀ {a : α} {l l' : List α} {b : β l} {b' : β l'}, l ~ l' → HEq b b' → HEq (f a l b) (f a l' b')
f_swap : ∀ {a a' : α} {l : List α} {b : β l}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))
l₁ l₂ l₃ : List α
_h₁ : l₁ ~ l₂
_h₂ : l₂ ~ l₃
ih₁ : HEq (List.rec b f l₁) (List.rec b f l₂)
ih₂ : HEq (List.rec b f l₂) (List.rec b f l₃)
⊢ HEq (List.rec b f l₁) (List.rec b f l₃)
[PROOFSTEP]
exact HEq.trans ih₁ ih₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ prod l₁ = prod l₂
[PROOFSTEP]
refine h.foldl_eq' ?_ _
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ ∀ (x : α), x ∈ l₁ → ∀ (y : α), y ∈ l₁ → ∀ (z : α), z * x * y = z * y * x
[PROOFSTEP]
apply Pairwise.forall_of_forall
[GOAL]
case H
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ Symmetric fun x y => ∀ (z : α), z * x * y = z * y * x
[PROOFSTEP]
intro x y h z
[GOAL]
case H
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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
[PROOFSTEP]
exact (h z).symm
[GOAL]
case H₁
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ ∀ (x : α), x ∈ l₁ → ∀ (z : α), z * x * x = z * x * x
[PROOFSTEP]
intros
[GOAL]
case H₁
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
x✝ : α
a✝ : x✝ ∈ l₁
z✝ : α
⊢ z✝ * x✝ * x✝ = z✝ * x✝ * x✝
[PROOFSTEP]
rfl
[GOAL]
case H₂
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ Pairwise (fun x y => ∀ (z : α), z * x * y = z * y * x) l₁
[PROOFSTEP]
apply hc.imp
[GOAL]
case H₂
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
M : Monoid α
l₁ l₂ : List α
h : l₁ ~ l₂
hc : Pairwise Commute l₁
⊢ ∀ {a b : α}, Commute a b → ∀ (z : α), z * a * b = z * b * a
[PROOFSTEP]
intro a b h z
[GOAL]
case H₂
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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
[PROOFSTEP]
rw [mul_assoc z, mul_assoc z, h]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ r₁ r₂ : List α
⊢ l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
generalize e₁ : l₁ ++ a :: r₁ = s₁
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ r₁ r₂ s₁ : List α
e₁ : l₁ ++ a :: r₁ = s₁
⊢ s₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
generalize e₂ : l₂ ++ a :: r₂ = s₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ r₁ r₂ s₁ : List α
e₁ : l₁ ++ a :: r₁ = s₁
s₂ : List α
e₂ : l₂ ++ a :: r₂ = s₂
⊢ s₁ ~ s₂ → l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
intro p
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ r₁ r₂ s₁ : List α
e₁ : l₁ ++ a :: r₁ = s₁
s₂ : List α
e₂ : l₂ ++ a :: r₂ = s₂
p : s₁ ~ s₂
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
revert l₁ l₂ r₁ r₂ e₁ e₂
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
⊢ ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = s₁ → l₂ ++ a :: r₂ = s₂ → l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
clear l₁ l₂ β
[GOAL]
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
⊢ ∀ {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = s₁ → l₂ ++ a :: r₂ = s₂ → l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
show ∀ _ _ _ _, _
[GOAL]
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
⊢ ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = s₁ → x_1 ++ a :: x_3 = s₂ → x ++ x_2 ~ x_1 ++ x_3
[PROOFSTEP]
refine perm_induction_on p ?_ (fun x t₁ t₂ p IH => ?_) (fun x y t₁ t₂ p IH => ?_) fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => ?_
[GOAL]
case refine_1
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
⊢ ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = [] → x_1 ++ a :: x_3 = [] → x ++ x_2 ~ x_1 ++ x_3
[PROOFSTEP]
intro l₁ l₂ r₁ r₂ e₁ e₂
[GOAL]
case refine_2
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ ∀ (x_1 x_2 x_3 x_4 : List α), x_1 ++ a :: x_3 = x :: t₁ → x_2 ++ a :: x_4 = x :: t₂ → x_1 ++ x_3 ~ x_2 ++ x_4
[PROOFSTEP]
intro l₁ l₂ r₁ r₂ e₁ e₂
[GOAL]
case refine_3
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ ∀ (x_1 x_2 x_3 x_4 : List α),
    x_1 ++ a :: x_3 = y :: x :: t₁ → x_2 ++ a :: x_4 = x :: y :: t₂ → x_1 ++ x_3 ~ x_2 ++ x_4
[PROOFSTEP]
intro l₁ l₂ r₁ r₂ e₁ e₂
[GOAL]
case refine_4
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₁ t₂ t₃ : List α
p₁ : t₁ ~ t₂
p₂ : t₂ ~ t₃
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = t₃ → x ++ x_2 ~ x_1 ++ x_3
⊢ ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₃ → x ++ x_2 ~ x_1 ++ x_3
[PROOFSTEP]
intro l₁ l₂ r₁ r₂ e₁ e₂
[GOAL]
case refine_1
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = []
e₂ : l₂ ++ a :: r₂ = []
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
apply (not_mem_nil a).elim
[GOAL]
case refine_1
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = []
e₂ : l₂ ++ a :: r₂ = []
⊢ a ∈ []
[PROOFSTEP]
rw [← e₁]
[GOAL]
case refine_1
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = []
e₂ : l₂ ++ a :: r₂ = []
⊢ a ∈ l₁ ++ a :: r₁
[PROOFSTEP]
simp
[GOAL]
case refine_2
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = x :: t₁
e₂ : l₂ ++ a :: r₂ = x :: t₂
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
cases' l₁ with y l₁
[GOAL]
case refine_2.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₂ r₁ r₂ : List α
e₂ : l₂ ++ a :: r₂ = x :: t₂
e₁ : [] ++ a :: r₁ = x :: t₁
⊢ [] ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
cases' l₂ with z l₂
[GOAL]
case refine_2.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₂ r₁ r₂ : List α
e₂ : l₂ ++ a :: r₂ = x :: t₂
y : α
l₁ : List α
e₁ : y :: l₁ ++ a :: r₁ = x :: t₁
⊢ y :: l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
cases' l₂ with z l₂
[GOAL]
case refine_2.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : [] ++ a :: r₁ = x :: t₁
e₂ : [] ++ a :: r₂ = x :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_2.nil.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : [] ++ a :: r₁ = x :: t₁
z : α
l₂ : List α
e₂ : z :: l₂ ++ a :: r₂ = x :: t₂
⊢ [] ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_2.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
e₁ : y :: l₁ ++ a :: r₁ = x :: t₁
e₂ : [] ++ a :: r₂ = x :: t₂
⊢ y :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_2.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
e₁ : y :: l₁ ++ a :: r₁ = x :: t₁
z : α
l₂ : List α
e₂ : z :: l₂ ++ a :: r₂ = x :: t₂
⊢ y :: l₁ ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_2.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : a :: r₁ = x :: t₁
e₂ : a :: r₂ = x :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_2.nil.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : a :: r₁ = x :: t₁
z : α
l₂ : List α
e₂ : z :: (l₂ ++ a :: r₂) = x :: t₂
⊢ [] ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_2.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
e₁ : y :: (l₁ ++ a :: r₁) = x :: t₁
e₂ : a :: r₂ = x :: t₂
⊢ y :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_2.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
e₁ : y :: (l₁ ++ a :: r₁) = x :: t₁
z : α
l₂ : List α
e₂ : z :: (l₂ ++ a :: r₂) = x :: t₂
⊢ y :: l₁ ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_2.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
head_eq✝¹ : a = x
tail_eq✝¹ : r₁ = t₁
head_eq✝ : a = x
tail_eq✝ : r₂ = t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
subst x
[GOAL]
case refine_2.nil.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
z : α
l₂ : List α
head_eq✝¹ : a = x
tail_eq✝¹ : r₁ = t₁
head_eq✝ : z = x
tail_eq✝ : l₂ ++ a :: r₂ = t₂
⊢ [] ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
subst x
[GOAL]
case refine_2.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
head_eq✝¹ : y = x
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝ : a = x
tail_eq✝ : r₂ = t₂
⊢ y :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
subst x
[GOAL]
case refine_2.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
z : α
l₂ : List α
head_eq✝¹ : y = x
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝ : z = x
tail_eq✝ : l₂ ++ a :: r₂ = t₂
⊢ y :: l₁ ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
subst x
[GOAL]
case refine_2.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
tail_eq✝¹ : r₁ = t₁
tail_eq✝ : r₂ = t₂
head_eq✝ : a = a
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs t₁ t₂
[GOAL]
case refine_2.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
r₁ r₂ : List α
head_eq✝ : a = a
p : r₁ ~ r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = r₁ → x_1 ++ a :: x_3 = r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
exact p
[GOAL]
case refine_2.nil.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
z : α
l₂ : List α
tail_eq✝¹ : r₁ = t₁
tail_eq✝ : l₂ ++ a :: r₂ = t₂
head_eq✝ : z = a
⊢ [] ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
substs z t₁ t₂
[GOAL]
case refine_2.nil.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
r₁ r₂ l₂ : List α
p : r₁ ~ l₂ ++ a :: r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = r₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [] ++ r₁ ~ a :: l₂ ++ r₂
[PROOFSTEP]
exact p.trans perm_middle
[GOAL]
case refine_2.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
tail_eq✝ : r₂ = t₂
head_eq✝ : a = y
⊢ y :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs y t₁ t₂
[GOAL]
case refine_2.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
r₁ r₂ l₁ : List α
p : l₁ ++ a :: r₁ ~ r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ a :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
exact perm_middle.symm.trans p
[GOAL]
case refine_2.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
l₁ : List α
z : α
l₂ : List α
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
tail_eq✝ : l₂ ++ a :: r₂ = t₂
head_eq✝ : z = y
⊢ y :: l₁ ++ r₁ ~ z :: l₂ ++ r₂
[PROOFSTEP]
substs z t₁ t₂
[GOAL]
case refine_2.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
r₁ r₂ : List α
y : α
l₁ l₂ : List α
p : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ y :: l₁ ++ r₁ ~ y :: l₂ ++ r₂
[PROOFSTEP]
exact (IH _ _ _ _ rfl rfl).cons y
[GOAL]
case refine_3
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = y :: x :: t₁
e₂ : l₂ ++ a :: r₂ = x :: y :: t₂
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩)
[GOAL]
case refine_3.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₂ r₁ r₂ : List α
e₂ : l₂ ++ a :: r₂ = x :: y :: t₂
e₁ : [] ++ a :: r₁ = y :: x :: t₁
⊢ [] ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩)
[GOAL]
case refine_3.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₂ r₁ r₂ : List α
e₂ : l₂ ++ a :: r₂ = x :: y✝ :: t₂
y : α
e₁ : [y] ++ a :: r₁ = y✝ :: x :: t₁
⊢ [y] ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩)
[GOAL]
case refine_3.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
l₂ r₁ r₂ : List α
e₂ : l₂ ++ a :: r₂ = x :: y✝ :: t₂
y z : α
l₁ : List α
e₁ : y :: z :: l₁ ++ a :: r₁ = y✝ :: x :: t₁
⊢ y :: z :: l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩)
[GOAL]
case refine_3.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : [] ++ a :: r₁ = y :: x :: t₁
e₂ : [] ++ a :: r₂ = x :: y :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : [] ++ a :: r₁ = y :: x :: t₁
u : α
e₂ : [u] ++ a :: r₂ = x :: y :: t₂
⊢ [] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : [] ++ a :: r₁ = y :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: l₂ ++ a :: r₂ = x :: y :: t₂
⊢ [] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : [y] ++ a :: r₁ = y✝ :: x :: t₁
e₂ : [] ++ a :: r₂ = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : [y] ++ a :: r₁ = y✝ :: x :: t₁
u : α
e₂ : [u] ++ a :: r₂ = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : [y] ++ a :: r₁ = y✝ :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: l₂ ++ a :: r₂ = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: l₁ ++ a :: r₁ = y✝ :: x :: t₁
e₂ : [] ++ a :: r₂ = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: l₁ ++ a :: r₁ = y✝ :: x :: t₁
u : α
e₂ : [u] ++ a :: r₂ = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.cons.cons.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: l₁ ++ a :: r₁ = y✝ :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: l₂ ++ a :: r₂ = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
dsimp at e₁ e₂ 
[GOAL]
case refine_3.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : a :: r₁ = y :: x :: t₁
e₂ : a :: r₂ = x :: y :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : a :: r₁ = y :: x :: t₁
u : α
e₂ : u :: a :: r₂ = x :: y :: t₂
⊢ [] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
e₁ : a :: r₁ = y :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: (l₂ ++ a :: r₂) = x :: y :: t₂
⊢ [] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : y :: a :: r₁ = y✝ :: x :: t₁
e₂ : a :: r₂ = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : y :: a :: r₁ = y✝ :: x :: t₁
u : α
e₂ : u :: a :: r₂ = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
e₁ : y :: a :: r₁ = y✝ :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: (l₂ ++ a :: r₂) = x :: y✝ :: t₂
⊢ [y] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: (l₁ ++ a :: r₁) = y✝ :: x :: t₁
e₂ : a :: r₂ = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: (l₁ ++ a :: r₁) = y✝ :: x :: t₁
u : α
e₂ : u :: a :: r₂ = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.cons.cons.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
e₁ : y :: z :: (l₁ ++ a :: r₁) = y✝ :: x :: t₁
u v : α
l₂ : List α
e₂ : u :: v :: (l₂ ++ a :: r₂) = x :: y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
injections
[GOAL]
case refine_3.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
head_eq✝¹ : a = y
tail_eq✝¹ : r₁ = x :: t₁
head_eq✝ : a = x
tail_eq✝ : r₂ = y :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u : α
head_eq✝² : a = y
tail_eq✝¹ : r₁ = x :: t₁
head_eq✝¹ : u = x
head_eq✝ : a = y
tail_eq✝ : r₂ = t₂
⊢ [] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u v : α
l₂ : List α
head_eq✝² : a = y
tail_eq✝¹ : r₁ = x :: t₁
head_eq✝¹ : u = x
head_eq✝ : v = y
tail_eq✝ : l₂ ++ a :: r₂ = t₂
⊢ [] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y : α
head_eq✝² : y = y✝
head_eq✝¹ : a = x
tail_eq✝¹ : r₁ = t₁
head_eq✝ : a = x
tail_eq✝ : r₂ = y✝ :: t₂
⊢ [y] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y u : α
head_eq✝³ : y = y✝
head_eq✝² : a = x
tail_eq✝¹ : r₁ = t₁
head_eq✝¹ : u = x
head_eq✝ : a = y✝
tail_eq✝ : r₂ = t₂
⊢ [y] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y u v : α
l₂ : List α
head_eq✝³ : y = y✝
head_eq✝² : a = x
tail_eq✝¹ : r₁ = t₁
head_eq✝¹ : u = x
head_eq✝ : v = y✝
tail_eq✝ : l₂ ++ a :: r₂ = t₂
⊢ [y] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
head_eq✝² : y = y✝
head_eq✝¹ : z = x
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝ : a = x
tail_eq✝ : r₂ = y✝ :: t₂
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
u : α
head_eq✝³ : y = y✝
head_eq✝² : z = x
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝¹ : u = x
head_eq✝ : a = y✝
tail_eq✝ : r₂ = t₂
⊢ y :: z :: l₁ ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.cons.cons.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
x y✝ : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
y z : α
l₁ : List α
u v : α
l₂ : List α
head_eq✝³ : y = y✝
head_eq✝² : z = x
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝¹ : u = x
head_eq✝ : v = y✝
tail_eq✝ : l₂ ++ a :: r₂ = t₂
⊢ y :: z :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs x y
[GOAL]
case refine_3.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
tail_eq✝¹ : r₁ = a :: t₁
tail_eq✝ : r₂ = a :: t₂
⊢ [] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs r₁ r₂
[GOAL]
case refine_3.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [] ++ a :: t₁ ~ [] ++ a :: t₂
[PROOFSTEP]
exact p.cons a
[GOAL]
case refine_3.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u : α
tail_eq✝¹ : r₂ = t₂
tail_eq✝ : r₁ = u :: t₁
head_eq✝ : a = a
⊢ [] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs r₁ r₂
[GOAL]
case refine_3.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
u : α
head_eq✝ : a = a
⊢ [] ++ u :: t₁ ~ [u] ++ t₂
[PROOFSTEP]
exact p.cons u
[GOAL]
case refine_3.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u v : α
l₂ : List α
tail_eq✝¹ : l₂ ++ a :: r₂ = t₂
tail_eq✝ : r₁ = u :: t₁
head_eq✝ : v = a
⊢ [] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs r₁ v t₂
[GOAL]
case refine_3.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ r₂ : List α
u : α
l₂ : List α
p : t₁ ~ l₂ ++ a :: r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [] ++ u :: t₁ ~ u :: a :: l₂ ++ r₂
[PROOFSTEP]
exact (p.trans perm_middle).cons u
[GOAL]
case refine_3.cons.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
tail_eq✝¹ : r₁ = t₁
tail_eq✝ : r₂ = y :: t₂
head_eq✝ : a = a
⊢ [y] ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs r₁ r₂
[GOAL]
case refine_3.cons.nil.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
head_eq✝ : a = a
⊢ [y] ++ t₁ ~ [] ++ y :: t₂
[PROOFSTEP]
exact p.cons y
[GOAL]
case refine_3.cons.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u : α
tail_eq✝¹ : r₁ = t₁
head_eq✝¹ : a = y
tail_eq✝ : r₂ = t₂
head_eq✝ : u = a
⊢ [y] ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs r₁ r₂ y u
[GOAL]
case refine_3.cons.nil.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [a] ++ t₁ ~ [a] ++ t₂
[PROOFSTEP]
exact p.cons a
[GOAL]
case refine_3.cons.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
u v : α
l₂ : List α
tail_eq✝¹ : r₁ = t₁
head_eq✝¹ : v = y
tail_eq✝ : l₂ ++ a :: r₂ = t₂
head_eq✝ : u = a
⊢ [y] ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs r₁ u v t₂
[GOAL]
case refine_3.cons.nil.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ r₂ l₂ : List α
p : t₁ ~ l₂ ++ a :: r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ [y] ++ t₁ ~ a :: y :: l₂ ++ r₂
[PROOFSTEP]
exact ((p.trans perm_middle).cons y).trans (swap _ _ _)
[GOAL]
case refine_3.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
z : α
l₁ : List α
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
tail_eq✝ : r₂ = y :: t₂
head_eq✝ : a = z
⊢ y :: z :: l₁ ++ r₁ ~ [] ++ r₂
[PROOFSTEP]
substs r₂ z t₁
[GOAL]
case refine_3.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₂ r₁ l₁ : List α
p : l₁ ++ a :: r₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ y :: a :: l₁ ++ r₁ ~ [] ++ y :: t₂
[PROOFSTEP]
exact (perm_middle.symm.trans p).cons y
[GOAL]
case refine_3.cons.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
z : α
l₁ : List α
u : α
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝¹ : a = y
tail_eq✝ : r₂ = t₂
head_eq✝ : u = z
⊢ y :: z :: l₁ ++ r₁ ~ [u] ++ r₂
[PROOFSTEP]
substs r₂ y z t₁
[GOAL]
case refine_3.cons.cons.cons.nil
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
t₂ r₁ l₁ : List α
u : α
p : l₁ ++ a :: r₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ a :: u :: l₁ ++ r₁ ~ [u] ++ t₂
[PROOFSTEP]
exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
[GOAL]
case refine_3.cons.cons.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
t₁ t₂ : List α
p : t₁ ~ t₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
r₁ r₂ : List α
z : α
l₁ : List α
u v : α
l₂ : List α
tail_eq✝¹ : l₁ ++ a :: r₁ = t₁
head_eq✝¹ : v = y
tail_eq✝ : l₂ ++ a :: r₂ = t₂
head_eq✝ : u = z
⊢ y :: z :: l₁ ++ r₁ ~ u :: v :: l₂ ++ r₂
[PROOFSTEP]
substs u v t₁ t₂
[GOAL]
case refine_3.cons.cons.cons.cons
α : Type uu
a : α
s₁ s₂ : List α
p✝ : s₁ ~ s₂
y : α
r₁ r₂ : List α
z : α
l₁ l₂ : List α
p : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ y :: z :: l₁ ++ r₁ ~ z :: y :: l₂ ++ r₂
[PROOFSTEP]
exact (IH _ _ _ _ rfl rfl).swap' _ _
[GOAL]
case refine_4
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₁ t₂ t₃ : List α
p₁ : t₁ ~ t₂
p₂ : t₂ ~ t₃
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = t₃ → x ++ x_2 ~ x_1 ++ x_3
l₁ l₂ r₁ r₂ : List α
e₁ : l₁ ++ a :: r₁ = t₁
e₂ : l₂ ++ a :: r₂ = t₃
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
substs t₁ t₃
[GOAL]
case refine_4
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₂ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ t₂
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
p₂ : t₂ ~ l₂ ++ a :: r₂
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
have : a ∈ t₂ := p₁.subset (by simp)
[GOAL]
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₂ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ t₂
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
p₂ : t₂ ~ l₂ ++ a :: r₂
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
⊢ a ∈ l₁ ++ a :: r₁
[PROOFSTEP]
simp
[GOAL]
case refine_4
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₂ l₁ l₂ r₁ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ t₂
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
p₂ : t₂ ~ l₂ ++ a :: r₂
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
this : a ∈ t₂
⊢ l₁ ++ r₁ ~ l₂ ++ r₂
[PROOFSTEP]
rcases mem_split this with ⟨l₂, r₂, e₂⟩
[GOAL]
case refine_4.intro.intro
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
t₂ l₁ l₂✝ r₁ r₂✝ : List α
p₁ : l₁ ++ a :: r₁ ~ t₂
IH₁ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = t₂ → x ++ x_2 ~ x_1 ++ x_3
p₂ : t₂ ~ l₂✝ ++ a :: r₂✝
IH₂ : ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = t₂ → x_1 ++ a :: x_3 = l₂✝ ++ a :: r₂✝ → x ++ x_2 ~ x_1 ++ x_3
this : a ∈ t₂
l₂ r₂ : List α
e₂ : t₂ = l₂ ++ a :: r₂
⊢ l₁ ++ r₁ ~ l₂✝ ++ r₂✝
[PROOFSTEP]
subst t₂
[GOAL]
case refine_4.intro.intro
α : Type uu
a : α
s₁ s₂ : List α
p : s₁ ~ s₂
l₁ l₂✝ r₁ r₂✝ l₂ r₂ : List α
p₁ : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂
IH₁ :
  ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₁ ++ a :: r₁ → x_1 ++ a :: x_3 = l₂ ++ a :: r₂ → x ++ x_2 ~ x_1 ++ x_3
p₂ : l₂ ++ a :: r₂ ~ l₂✝ ++ a :: r₂✝
IH₂ :
  ∀ (x x_1 x_2 x_3 : List α), x ++ a :: x_2 = l₂ ++ a :: r₂ → x_1 ++ a :: x_3 = l₂✝ ++ a :: r₂✝ → x ++ x_2 ~ x_1 ++ x_3
this : a ∈ l₂ ++ a :: r₂
⊢ l₁ ++ r₁ ~ l₂✝ ++ r₂✝
[PROOFSTEP]
exact (IH₁ _ _ _ _ rfl rfl).trans (IH₂ _ _ _ _ rfl rfl)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
o₁ o₂ : Option α
⊢ Option.toList o₁ ~ Option.toList o₂ ↔ o₁ = o₂
[PROOFSTEP]
refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
o₁ o₂ : Option α
p : Option.toList o₁ ~ Option.toList o₂
⊢ o₁ = o₂
[PROOFSTEP]
cases' o₁ with a
[GOAL]
case none
α : Type uu
β : Type vv
l₁ l₂ : List α
o₂ : Option α
p : Option.toList none ~ Option.toList o₂
⊢ none = o₂
[PROOFSTEP]
cases' o₂ with b
[GOAL]
case some
α : Type uu
β : Type vv
l₁ l₂ : List α
o₂ : Option α
a : α
p : Option.toList (some a) ~ Option.toList o₂
⊢ some a = o₂
[PROOFSTEP]
cases' o₂ with b
[GOAL]
case none.none
α : Type uu
β : Type vv
l₁ l₂ : List α
p : Option.toList none ~ Option.toList none
⊢ none = none
[PROOFSTEP]
rfl
[GOAL]
case none.some
α : Type uu
β : Type vv
l₁ l₂ : List α
b : α
p : Option.toList none ~ Option.toList (some b)
⊢ none = some b
[PROOFSTEP]
cases p.length_eq
[GOAL]
case some.none
α : Type uu
β : Type vv
l₁ l₂ : List α
a : α
p : Option.toList (some a) ~ Option.toList none
⊢ some a = none
[PROOFSTEP]
cases p.length_eq
[GOAL]
case some.some
α : Type uu
β : Type vv
l₁ l₂ : List α
a b : α
p : Option.toList (some a) ~ Option.toList (some b)
⊢ some a = some b
[PROOFSTEP]
exact Option.mem_toList.1 (p.symm.subset <| by simp)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b : α
p : Option.toList (some a) ~ Option.toList (some b)
⊢ b ∈ Option.toList (some b)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
x✝ : a :: l₁ <+~ a :: l₂
l : List α
p : l ~ a :: l₁
s : l <+ a :: l₂
⊢ l₁ <+~ l₂
[PROOFSTEP]
cases' s with _ _ _ s' u _ _ s'
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
x✝ : a :: l₁ <+~ a :: l₂
l : List α
p : l ~ a :: l₁
s' : l <+ l₂
⊢ l₁ <+~ l₂
[PROOFSTEP]
exact (p.subperm_left.2 <| (sublist_cons _ _).subperm).trans s'.subperm
[GOAL]
case cons₂
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
x✝ : a :: l₁ <+~ a :: l₂
u : List α
p : a :: u ~ a :: l₁
s' : u <+ l₂
⊢ l₁ <+~ l₂
[PROOFSTEP]
exact ⟨u, p.cons_inv, s'⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
d₁ : Nodup l₁
h₁ : ¬a ∈ l₁
h₂ : a ∈ l₂
s : l₁ <+~ l₂
⊢ a :: l₁ <+~ l₂
[PROOFSTEP]
rcases s with ⟨l, p, s⟩
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₁ l₂ : List α
d₁ : Nodup l₁
h₁ : ¬a ∈ l₁
h₂ : a ∈ l₂
l : List α
p : l ~ l₁
s : l <+ l₂
⊢ a :: l₁ <+~ l₂
[PROOFSTEP]
induction s generalizing l₁
[GOAL]
case intro.intro.slnil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : ¬a ∈ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []
case intro.intro.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
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 uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
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₂✝
[PROOFSTEP]
case slnil => cases h₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : ¬a ∈ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []
[PROOFSTEP]
case slnil => cases h₂
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
a : α
l₂ l l₁ : List α
d₁ : Nodup l₁
h₁ : ¬a ∈ l₁
h₂ : a ∈ []
p : [] ~ l₁
⊢ a :: l₁ <+~ []
[PROOFSTEP]
cases h₂
[GOAL]
case intro.intro.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
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 uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
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₂✝
[PROOFSTEP]
case cons r₁ r₂ b s' ih =>
  simp 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 _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
case cons r₁ r₂ b s' ih =>
  simp 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 _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
simp at h₂ 
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
cases' h₂ with e m
[GOAL]
case inl
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
subst b
[GOAL]
case inl
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
[GOAL]
case inr
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
[GOAL]
case inr.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
exact ⟨t, p', s'.cons _⟩
[GOAL]
case intro.intro.cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
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₂✝
[PROOFSTEP]
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₂ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
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₂ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
have am : a ∈ r₂ := by
  simp only [find?, mem_cons] at h₂ 
  exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
simp only [find?, mem_cons] at h₂ 
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
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₂
[PROOFSTEP]
rcases mem_split bm with ⟨t₁, t₂, rfl⟩
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂✝ : List α
a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → ¬a ∈ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
h₂ : a ∈ b :: r₂
am : a ∈ r₂
t₁ t₂ : List α
d₁ : Nodup (t₁ ++ b :: t₂)
h₁ : ¬a ∈ t₁ ++ b :: t₂
p : b :: r₁ ~ t₁ ++ b :: t₂
bm : b ∈ t₁ ++ b :: t₂
⊢ a :: (t₁ ++ b :: t₂) <+~ b :: r₂
[PROOFSTEP]
have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂✝ : List α
a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → ¬a ∈ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
h₂ : a ∈ b :: r₂
am : a ∈ r₂
t₁ t₂ : List α
d₁ : Nodup (t₁ ++ b :: t₂)
h₁ : ¬a ∈ t₁ ++ b :: t₂
p : b :: r₁ ~ t₁ ++ b :: t₂
bm : b ∈ t₁ ++ b :: t₂
⊢ t₁ ++ t₂ <+ t₁ ++ b :: t₂
[PROOFSTEP]
simp
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂✝ : List α
a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → ¬a ∈ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
h₂ : a ∈ b :: r₂
am : a ∈ r₂
t₁ t₂ : List α
d₁ : Nodup (t₁ ++ b :: t₂)
h₁ : ¬a ∈ t₁ ++ b :: t₂
p : b :: r₁ ~ t₁ ++ b :: t₂
bm : b ∈ t₁ ++ b :: t₂
st : t₁ ++ t₂ <+ t₁ ++ b :: t₂
⊢ a :: (t₁ ++ b :: t₂) <+~ b :: r₂
[PROOFSTEP]
rcases ih (d₁.sublist st) (mt (fun x => st.subset x) h₁) am (Perm.cons_inv <| p.trans perm_middle) with ⟨t, p', s'⟩
[GOAL]
case intro.intro.intro.intro
α : Type uu
β : Type vv
l₁ l₂✝ : List α
a : α
l₂ l r₁ r₂ : List α
b : α
a✝ : r₁ <+ r₂
ih : ∀ {l₁ : List α}, Nodup l₁ → ¬a ∈ l₁ → a ∈ r₂ → r₁ ~ l₁ → a :: l₁ <+~ r₂
h₂ : a ∈ b :: r₂
am : a ∈ r₂
t₁ t₂ : List α
d₁ : Nodup (t₁ ++ b :: t₂)
h₁ : ¬a ∈ t₁ ++ b :: t₂
p : b :: r₁ ~ t₁ ++ b :: t₂
bm : b ∈ t₁ ++ b :: t₂
st : t₁ ++ t₂ <+ t₁ ++ b :: t₂
t : List α
p' : t ~ a :: (t₁ ++ t₂)
s' : t <+ r₂
⊢ a :: (t₁ ++ b :: t₂) <+~ b :: r₂
[PROOFSTEP]
exact ⟨b :: t, (p'.cons b).trans <| (swap _ _ _).trans (perm_middle.symm.cons a), s'.cons₂ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l : List α
p : l ~ l₁
s : l <+ l₂
h : length l₁ < length l₂
⊢ ∃ a, a :: l₁ <+~ l₂
[PROOFSTEP]
suffices length l < length l₂ → ∃ a : α, a :: l <+~ l₂ from
  (this <| p.symm.length_eq ▸ h).imp fun a => (p.cons a).subperm_right.1
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l : List α
p : l ~ l₁
s : l <+ l₂
h : length l₁ < length l₂
⊢ length l < length l₂ → ∃ a, a :: l <+~ l₂
[PROOFSTEP]
clear h p l₁
[GOAL]
α : Type uu
β : Type vv
l₁ l₂✝ l₂ l : List α
s : l <+ l₂
⊢ length l < length l₂ → ∃ a, a :: l <+~ l₂
[PROOFSTEP]
induction' s with l₁ l₂ a s IH _ _ b _ IH
[GOAL]
case slnil
α : Type uu
β : Type vv
l₁ l₂✝ l₂ l : List α
⊢ length [] < length [] → ∃ a, [a] <+~ []
[PROOFSTEP]
intro h
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ l₂✝ l l₁ l₂ : List α
a : α
s : l₁ <+ l₂
IH : length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
⊢ length l₁ < length (a :: l₂) → ∃ a_2, a_2 :: l₁ <+~ a :: l₂
[PROOFSTEP]
intro h
[GOAL]
case cons₂
α : Type uu
β : Type vv
l₁ l₂✝¹ l₂ l l₁✝ l₂✝ : List α
b : α
a✝ : l₁✝ <+ l₂✝
IH : length l₁✝ < length l₂✝ → ∃ a, a :: l₁✝ <+~ l₂✝
⊢ length (b :: l₁✝) < length (b :: l₂✝) → ∃ a, a :: b :: l₁✝ <+~ b :: l₂✝
[PROOFSTEP]
intro h
[GOAL]
case slnil
α : Type uu
β : Type vv
l₁ l₂✝ l₂ l : List α
h : length [] < length []
⊢ ∃ a, [a] <+~ []
[PROOFSTEP]
cases h
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ l₂✝ l l₁ l₂ : List α
a : α
s : l₁ <+ l₂
IH : length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
h : length l₁ < length (a :: l₂)
⊢ ∃ a_1, a_1 :: l₁ <+~ a :: l₂
[PROOFSTEP]
cases' lt_or_eq_of_le (Nat.le_of_lt_succ h : length l₁ ≤ length l₂) with h h
[GOAL]
case cons.inl
α : Type uu
β : Type vv
l₁✝ l₂✝¹ l₂✝ l l₁ l₂ : List α
a : α
s : l₁ <+ l₂
IH : length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
h✝ : length l₁ < length (a :: l₂)
h : length l₁ < length l₂
⊢ ∃ a_1, a_1 :: l₁ <+~ a :: l₂
[PROOFSTEP]
exact (IH h).imp fun a s => s.trans (sublist_cons _ _).subperm
[GOAL]
case cons.inr
α : Type uu
β : Type vv
l₁✝ l₂✝¹ l₂✝ l l₁ l₂ : List α
a : α
s : l₁ <+ l₂
IH : length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
h✝ : length l₁ < length (a :: l₂)
h : length l₁ = length l₂
⊢ ∃ a_1, a_1 :: l₁ <+~ a :: l₂
[PROOFSTEP]
exact ⟨a, s.eq_of_length h ▸ Subperm.refl _⟩
[GOAL]
case cons₂
α : Type uu
β : Type vv
l₁ l₂✝¹ l₂ l l₁✝ l₂✝ : List α
b : α
a✝ : l₁✝ <+ l₂✝
IH : length l₁✝ < length l₂✝ → ∃ a, a :: l₁✝ <+~ l₂✝
h : length (b :: l₁✝) < length (b :: l₂✝)
⊢ ∃ a, a :: b :: l₁✝ <+~ b :: l₂✝
[PROOFSTEP]
exact (IH <| Nat.lt_of_succ_lt_succ h).imp fun a s => (swap _ _ _).subperm_right.1 <| (subperm_cons _).2 s
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
d : Nodup l₁
H : l₁ ⊆ l₂
⊢ l₁ <+~ l₂
[PROOFSTEP]
induction' d with a l₁' h d IH
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
H✝ : l₁ ⊆ l₂
H : [] ⊆ l₂
⊢ [] <+~ l₂
[PROOFSTEP]
exact ⟨nil, Perm.nil, nil_sublist _⟩
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
H✝ : l₁ ⊆ l₂
a : α
l₁' : List α
h : ∀ (a' : α), a' ∈ l₁' → a ≠ a'
d : Pairwise (fun x x_1 => x ≠ x_1) l₁'
IH : l₁' ⊆ l₂ → l₁' <+~ l₂
H : a :: l₁' ⊆ l₂
⊢ a :: l₁' <+~ l₂
[PROOFSTEP]
cases' forall_mem_cons.1 H with H₁ H₂
[GOAL]
case cons.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
H✝ : l₁ ⊆ l₂
a : α
l₁' : List α
h : ∀ (a' : α), a' ∈ l₁' → a ≠ a'
d : Pairwise (fun x x_1 => x ≠ x_1) l₁'
IH : l₁' ⊆ l₂ → l₁' <+~ l₂
H : a :: l₁' ⊆ l₂
H₁ : a ∈ l₂
H₂ : ∀ (x : α), x ∈ l₁' → x ∈ l₂
⊢ a :: l₁' <+~ l₂
[PROOFSTEP]
simp at h 
[GOAL]
case cons.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
H✝ : l₁ ⊆ l₂
a : α
l₁' : List α
d : Pairwise (fun x x_1 => x ≠ x_1) l₁'
IH : l₁' ⊆ l₂ → l₁' <+~ l₂
H : a :: l₁' ⊆ l₂
H₁ : a ∈ l₂
H₂ : ∀ (x : α), x ∈ l₁' → x ∈ l₂
h : ¬a ∈ l₁'
⊢ a :: l₁' <+~ l₂
[PROOFSTEP]
exact cons_subperm_of_mem d h H₁ (IH H₂)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l : List α
d : Nodup l
s₁ : l₁ <+ l
s₂ : l₂ <+ l
h : l₁ ~ l₂
⊢ l₁ = l₂
[PROOFSTEP]
induction' s₂ with l₂ l a s₂ IH l₂ l a _ IH generalizing l₁
[GOAL]
case slnil
α : Type uu
β : Type vv
l₁✝¹ l₂✝ l₁✝ l₂ l : List α
d✝ : Nodup l
s₁✝ : l₁✝ <+ l
h✝ : l₁✝ ~ l₂
l₁ : List α
d : Nodup []
s₁ : l₁ <+ []
h : l₁ ~ []
⊢ l₁ = []
[PROOFSTEP]
exact h.eq_nil
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
s₂ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
d : Nodup (a :: l)
s₁ : l₁ <+ a :: l
h : l₁ ~ l₂
⊢ l₁ = l₂
[PROOFSTEP]
simp at d 
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
s₂ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
s₁ : l₁ <+ a :: l
h : l₁ ~ l₂
d : ¬a ∈ l ∧ Nodup l
⊢ l₁ = l₂
[PROOFSTEP]
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
[GOAL]
case cons.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
s₂ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
h : l₁ ~ l₂
d : ¬a ∈ l ∧ Nodup l
s₁ : l₁ <+ l
⊢ l₁ = l₂
[PROOFSTEP]
exact IH d.2 s₁ h
[GOAL]
case cons.cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
s₂ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
d : ¬a ∈ l ∧ Nodup l
l₁ : List α
h : a :: l₁ ~ l₂
s₁ : l₁ <+ l
⊢ a :: l₁ = l₂
[PROOFSTEP]
apply d.1.elim
[GOAL]
case cons.cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
s₂ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
d : ¬a ∈ l ∧ Nodup l
l₁ : List α
h : a :: l₁ ~ l₂
s₁ : l₁ <+ l
⊢ a ∈ l
[PROOFSTEP]
exact Subperm.subset ⟨_, h.symm, s₂⟩ (mem_cons_self _ _)
[GOAL]
case cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
a✝ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
d : Nodup (a :: l)
s₁ : l₁ <+ a :: l
h : l₁ ~ a :: l₂
⊢ l₁ = a :: l₂
[PROOFSTEP]
simp at d 
[GOAL]
case cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
a✝ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
s₁ : l₁ <+ a :: l
h : l₁ ~ a :: l₂
d : ¬a ∈ l ∧ Nodup l
⊢ l₁ = a :: l₂
[PROOFSTEP]
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
[GOAL]
case cons₂.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
a✝ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
h : l₁ ~ a :: l₂
d : ¬a ∈ l ∧ Nodup l
s₁ : l₁ <+ l
⊢ l₁ = a :: l₂
[PROOFSTEP]
apply d.1.elim
[GOAL]
case cons₂.cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
a✝ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
l₁ : List α
h : l₁ ~ a :: l₂
d : ¬a ∈ l ∧ Nodup l
s₁ : l₁ <+ l
⊢ a ∈ l
[PROOFSTEP]
exact Subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
[GOAL]
case cons₂.cons₂
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ l₁✝ l₂✝ l✝ : List α
d✝ : Nodup l✝
s₁✝ : l₁✝ <+ l✝
h✝ : l₁✝ ~ l₂✝
l₂ l : List α
a : α
a✝ : l₂ <+ l
IH : ∀ {l₁ : List α}, Nodup l → l₁ <+ l → l₁ ~ l₂ → l₁ = l₂
d : ¬a ∈ l ∧ Nodup l
l₁ : List α
h : a :: l₁ ~ a :: l₂
s₁ : l₁ <+ l
⊢ a :: l₁ = a :: l₂
[PROOFSTEP]
rw [IH d.2 s₁ h.cons_inv]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ l₁ l₂ l : List α
d : Nodup l
s₁ : l₁ <+ l
s₂ : l₂ <+ l
h : l₁ = l₂
⊢ l₁ ~ l₂
[PROOFSTEP]
rw [h]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
h₁ : ¬a ∈ l₁
⊢ List.erase l₁ a ~ List.erase l₂ a
[PROOFSTEP]
have h₂ : a ∉ l₂ := mt p.mem_iff.2 h₁
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
h₁ : ¬a ∈ l₁
h₂ : ¬a ∈ l₂
⊢ List.erase l₁ a ~ List.erase l₂ a
[PROOFSTEP]
rw [erase_of_not_mem h₁, erase_of_not_mem h₂]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
h₁ : ¬a ∈ l₁
h₂ : ¬a ∈ l₂
⊢ l₁ ~ l₂
[PROOFSTEP]
exact p
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
⊢ l <+~ a :: List.erase l a
[PROOFSTEP]
by_cases h : a ∈ l
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
h : a ∈ l
⊢ l <+~ a :: List.erase l a
[PROOFSTEP]
exact (perm_cons_erase h).subperm
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
h : ¬a ∈ l
⊢ l <+~ a :: List.erase l a
[PROOFSTEP]
rw [erase_of_not_mem h]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
h : ¬a ∈ l
⊢ l <+~ a :: l
[PROOFSTEP]
exact (sublist_cons _ _).subperm
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t : List α
h : l₁ ~ l₂
⊢ List.diff l₁ t ~ List.diff l₂ t
[PROOFSTEP]
induction t generalizing l₁ l₂ h
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : l₁ ~ l₂
⊢ List.diff l₁ [] ~ List.diff l₂ []
[PROOFSTEP]
simp [*, Perm.erase]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {l₁ l₂ : List α}, l₁ ~ l₂ → List.diff l₁ tail✝ ~ List.diff l₂ tail✝
l₁ l₂ : List α
h : l₁ ~ l₂
⊢ List.diff l₁ (head✝ :: tail✝) ~ List.diff l₂ (head✝ :: tail✝)
[PROOFSTEP]
simp [*, Perm.erase]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l t₁ t₂ : List α
h : t₁ ~ t₂
⊢ List.diff l t₁ = List.diff l t₂
[PROOFSTEP]
induction h generalizing l
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ l : List α
⊢ List.diff l [] = List.diff l []
[PROOFSTEP]
first
| simp [*, Perm.erase, erase_comm]
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ l : List α
⊢ List.diff l [] = List.diff l []
[PROOFSTEP]
simp [*, Perm.erase, erase_comm]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (l : List α), List.diff l l₁✝ = List.diff l l₂✝
l : List α
⊢ List.diff l (x✝ :: l₁✝) = List.diff l (x✝ :: l₂✝)
[PROOFSTEP]
first
| simp [*, Perm.erase, erase_comm]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
x✝ : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (l : List α), List.diff l l₁✝ = List.diff l l₂✝
l : List α
⊢ List.diff l (x✝ :: l₁✝) = List.diff l (x✝ :: l₂✝)
[PROOFSTEP]
simp [*, Perm.erase, erase_comm]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
x✝ y✝ : α
l✝ l : List α
⊢ List.diff l (y✝ :: x✝ :: l✝) = List.diff l (x✝ :: y✝ :: l✝)
[PROOFSTEP]
first
| simp [*, Perm.erase, erase_comm]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
x✝ y✝ : α
l✝ l : List α
⊢ List.diff l (y✝ :: x✝ :: l✝) = List.diff l (x✝ :: y✝ :: l✝)
[PROOFSTEP]
simp [*, Perm.erase, erase_comm]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ (l : List α), List.diff l l₁✝ = List.diff l l₂✝
a_ih✝ : ∀ (l : List α), List.diff l l₂✝ = List.diff l l₃✝
l : List α
⊢ List.diff l l₁✝ = List.diff l l₃✝
[PROOFSTEP]
first
| simp [*, Perm.erase, erase_comm]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
a_ih✝¹ : ∀ (l : List α), List.diff l l₁✝ = List.diff l l₂✝
a_ih✝ : ∀ (l : List α), List.diff l l₂✝ = List.diff l l₃✝
l : List α
⊢ List.diff l l₁✝ = List.diff l l₃✝
[PROOFSTEP]
simp [*, Perm.erase, erase_comm]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : l₁ <+~ l₂
t : List α
⊢ List.diff l₁ t <+~ List.diff l₂ t
[PROOFSTEP]
induction t generalizing l₁ l₂ h
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : l₁ <+~ l₂
⊢ List.diff l₁ [] <+~ List.diff l₂ []
[PROOFSTEP]
simp [*, Subperm.erase]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {l₁ l₂ : List α}, l₁ <+~ l₂ → List.diff l₁ tail✝ <+~ List.diff l₂ tail✝
l₁ l₂ : List α
h : l₁ <+~ l₂
⊢ List.diff l₁ (head✝ :: tail✝) <+~ List.diff l₂ (head✝ :: tail✝)
[PROOFSTEP]
simp [*, Subperm.erase]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a b : α
l : List α
⊢ List.erase (a :: l) b <+~ a :: List.erase l b
[PROOFSTEP]
by_cases h : a = b
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a b : α
l : List α
h : a = b
⊢ List.erase (a :: l) b <+~ a :: List.erase l b
[PROOFSTEP]
subst b
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
⊢ List.erase (a :: l) a <+~ a :: List.erase l a
[PROOFSTEP]
rw [erase_cons_head]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
l : List α
⊢ l <+~ a :: List.erase l a
[PROOFSTEP]
apply subperm_cons_erase
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
a b : α
l : List α
h : ¬a = b
⊢ List.erase (a :: l) b <+~ a :: List.erase l b
[PROOFSTEP]
rw [erase_cons_tail _ h]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂ : List α
inst✝ : DecidableEq α
a : α
l₁ : List α
⊢ ∃ x, a :: l₁ <+ a :: List.diff l₁ []
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ : List α
b : α
l₂ : List α
⊢ List.diff (a :: l₁) (b :: l₂) <+~ a :: List.diff l₁ (b :: l₂)
[PROOFSTEP]
simp only [diff_cons]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ : List α
b : α
l₂ : List α
⊢ List.diff (List.erase (a :: l₁) b) l₂ <+~ a :: List.diff (List.erase l₁ b) l₂
[PROOFSTEP]
refine' ((erase_cons_subperm_cons_erase a b l₁).diff_right l₂).trans _
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ : List α
b : α
l₂ : List α
⊢ List.diff (a :: List.erase l₁ b) l₂ <+~ a :: List.diff (List.erase l₁ b) l₂
[PROOFSTEP]
apply subperm_cons_diff
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t : List α
h : l₁ ~ l₂
⊢ List.bagInter l₁ t ~ List.bagInter l₂ t
[PROOFSTEP]
induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ t : List α
⊢ List.bagInter [] t ~ List.bagInter [] t
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (t : List α), List.bagInter l₁✝ t ~ List.bagInter l₂✝ t
t : List α
⊢ List.bagInter (x :: l₁✝) t ~ List.bagInter (x :: l₂✝) t
[PROOFSTEP]
by_cases x ∈ t
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (t : List α), List.bagInter l₁✝ t ~ List.bagInter l₂✝ t
t : List α
⊢ List.bagInter (x :: l₁✝) t ~ List.bagInter (x :: l₂✝) t
[PROOFSTEP]
by_cases x ∈ t
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (t : List α), List.bagInter l₁✝ t ~ List.bagInter l₂✝ t
t : List α
h : x ∈ t
⊢ List.bagInter (x :: l₁✝) t ~ List.bagInter (x :: l₂✝) t
[PROOFSTEP]
simp [*, Perm.cons]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
a_ih✝ : ∀ (t : List α), List.bagInter l₁✝ t ~ List.bagInter l₂✝ t
t : List α
h : ¬x ∈ t
⊢ List.bagInter (x :: l₁✝) t ~ List.bagInter (x :: l₂✝) t
[PROOFSTEP]
simp [*, Perm.cons]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
by_cases h : x = y
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : x = y
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
simp [h]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
by_cases xt : x ∈ t
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : x ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
by_cases yt : y ∈ t
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : ¬x ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
by_cases yt : y ∈ t
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : x ∈ t
yt : y ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (Ne.symm h), erase_comm, swap]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : x ∈ t
yt : ¬y ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
simp [xt, yt, mt mem_of_mem_erase, Perm.cons]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : ¬x ∈ t
yt : y ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
simp [xt, yt, mt mem_of_mem_erase, Perm.cons]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ : List α
x y : α
l✝ t : List α
h : ¬x = y
xt : ¬x ∈ t
yt : ¬y ∈ t
⊢ List.bagInter (y :: x :: l✝) t ~ List.bagInter (x :: y :: l✝) t
[PROOFSTEP]
simp [xt, yt]
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t✝ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih_1 : ∀ (t : List α), List.bagInter l₁✝ t ~ List.bagInter l₂✝ t
ih_2 : ∀ (t : List α), List.bagInter l₂✝ t ~ List.bagInter l₃✝ t
t : List α
⊢ List.bagInter l₁✝ t ~ List.bagInter l₃✝ t
[PROOFSTEP]
exact (ih_1 _).trans (ih_2 _)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l t₁ t₂ : List α
p : t₁ ~ t₂
⊢ List.bagInter l t₁ = List.bagInter l t₂
[PROOFSTEP]
induction' l with a l IH generalizing t₁ t₂ p
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁✝ t₂✝ : List α
p✝ : t₁✝ ~ t₂✝
t₁ t₂ : List α
p : t₁ ~ t₂
⊢ List.bagInter [] t₁ = List.bagInter [] t₂
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁✝ t₂✝ : List α
p✝ : t₁✝ ~ t₂✝
a : α
l : List α
IH : ∀ {t₁ t₂ : List α}, t₁ ~ t₂ → List.bagInter l t₁ = List.bagInter l t₂
t₁ t₂ : List α
p : t₁ ~ t₂
⊢ List.bagInter (a :: l) t₁ = List.bagInter (a :: l) t₂
[PROOFSTEP]
by_cases h : a ∈ t₁
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁✝ t₂✝ : List α
p✝ : t₁✝ ~ t₂✝
a : α
l : List α
IH : ∀ {t₁ t₂ : List α}, t₁ ~ t₂ → List.bagInter l t₁ = List.bagInter l t₂
t₁ t₂ : List α
p : t₁ ~ t₂
h : a ∈ t₁
⊢ List.bagInter (a :: l) t₁ = List.bagInter (a :: l) t₂
[PROOFSTEP]
simp [h, p.subset h, IH (p.erase _)]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁✝ t₂✝ : List α
p✝ : t₁✝ ~ t₂✝
a : α
l : List α
IH : ∀ {t₁ t₂ : List α}, t₁ ~ t₂ → List.bagInter l t₁ = List.bagInter l t₂
t₁ t₂ : List α
p : t₁ ~ t₂
h : ¬a ∈ t₁
⊢ List.bagInter (a :: l) t₁ = List.bagInter (a :: l) t₂
[PROOFSTEP]
simp [h, mt p.mem_iff.2 h, IH p]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
H : ∀ (a : α), count a l₁ = count a l₂
⊢ l₁ ~ l₂
[PROOFSTEP]
induction' l₁ with a l₁ IH generalizing l₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁ = count a l₂✝
l₂ : List α
H : ∀ (a : α), count a [] = count a l₂
⊢ [] ~ l₂
[PROOFSTEP]
cases' l₂ with b l₂
[GOAL]
case nil.nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
H✝ : ∀ (a : α), count a l₁ = count a l₂
H : ∀ (a : α), count a [] = count a []
⊢ [] ~ []
[PROOFSTEP]
rfl
[GOAL]
case nil.cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁ = count a l₂✝
b : α
l₂ : List α
H : ∀ (a : α), count a [] = count a (b :: l₂)
⊢ [] ~ b :: l₂
[PROOFSTEP]
specialize H b
[GOAL]
case nil.cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁ = count a l₂✝
b : α
l₂ : List α
H : count b [] = count b (b :: l₂)
⊢ [] ~ b :: l₂
[PROOFSTEP]
simp at H 
[GOAL]
case nil.cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁ = count a l₂✝
b : α
l₂ : List α
H : 0 = count b l₂ + 1
⊢ [] ~ b :: l₂
[PROOFSTEP]
contradiction
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
H : ∀ (a_1 : α), count a_1 (a :: l₁) = count a_1 l₂
⊢ a :: l₁ ~ l₂
[PROOFSTEP]
have : a ∈ l₂ := count_pos.1 (by rw [← H]; simp)
[GOAL]
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
H : ∀ (a_1 : α), count a_1 (a :: l₁) = count a_1 l₂
⊢ 0 < count a l₂
[PROOFSTEP]
rw [← H]
[GOAL]
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
H : ∀ (a_1 : α), count a_1 (a :: l₁) = count a_1 l₂
⊢ 0 < count a (a :: l₁)
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
H : ∀ (a_1 : α), count a_1 (a :: l₁) = count a_1 l₂
this : a ∈ l₂
⊢ a :: l₁ ~ l₂
[PROOFSTEP]
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
H : ∀ (a_1 : α), count a_1 (a :: l₁) = count a_1 l₂
this : a ∈ l₂
b : α
⊢ count b l₁ = count b (List.erase l₂ a)
[PROOFSTEP]
specialize H b
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
this : a ∈ l₂
b : α
H : count b (a :: l₁) = count b l₂
⊢ count b l₁ = count b (List.erase l₂ a)
[PROOFSTEP]
rw [(perm_cons_erase this).count_eq] at H 
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
this : a ∈ l₂
b : α
H : count b (a :: l₁) = count b (a :: List.erase l₂ a)
⊢ count b l₁ = count b (List.erase l₂ a)
[PROOFSTEP]
by_cases h : b = a
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
this : a ∈ l₂
b : α
H : count b (a :: l₁) = count b (a :: List.erase l₂ a)
h : b = a
⊢ count b l₁ = count b (List.erase l₂ a)
[PROOFSTEP]
simpa [h] using H
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁✝ l₂✝ : List α
H✝ : ∀ (a : α), count a l₁✝ = count a l₂✝
a : α
l₁ : List α
IH : ∀ {l₂ : List α}, (∀ (a : α), count a l₁ = count a l₂) → l₁ ~ l₂
l₂ : List α
this : a ∈ l₂
b : α
H : count b (a :: l₁) = count b (a :: List.erase l₂ a)
h : ¬b = a
⊢ count b l₁ = count b (List.erase l₂ a)
[PROOFSTEP]
simpa [h] using H
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
⊢ l ~ replicate m a ++ replicate n b ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b]
[PROOFSTEP]
rw [perm_iff_count, ← Decidable.and_forall_ne a, ← Decidable.and_forall_ne b]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
⊢ (count a l = count a (replicate m a ++ replicate n b) ∧
      (b ≠ a → count b l = count b (replicate m a ++ replicate n b)) ∧
        ∀ (b_1 : α), b_1 ≠ b → b_1 ≠ a → count b_1 l = count b_1 (replicate m a ++ replicate n b)) ↔
    count a l = m ∧ count b l = n ∧ l ⊆ [a, b]
[PROOFSTEP]
suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
this : l ⊆ [a, b] ↔ ∀ (c : α), c ≠ b → c ≠ a → ¬c ∈ l
⊢ (count a l = count a (replicate m a ++ replicate n b) ∧
      (b ≠ a → count b l = count b (replicate m a ++ replicate n b)) ∧
        ∀ (b_1 : α), b_1 ≠ b → b_1 ≠ a → count b_1 l = count b_1 (replicate m a ++ replicate n b)) ↔
    count a l = m ∧ count b l = n ∧ l ⊆ [a, b]
case this
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
⊢ l ⊆ [a, b] ↔ ∀ (c : α), c ≠ b → c ≠ a → ¬c ∈ l
[PROOFSTEP]
{simp (config := { contextual := true }) [count_replicate, h, h.symm, this]
}
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
this : l ⊆ [a, b] ↔ ∀ (c : α), c ≠ b → c ≠ a → ¬c ∈ l
⊢ (count a l = count a (replicate m a ++ replicate n b) ∧
      (b ≠ a → count b l = count b (replicate m a ++ replicate n b)) ∧
        ∀ (b_1 : α), b_1 ≠ b → b_1 ≠ a → count b_1 l = count b_1 (replicate m a ++ replicate n b)) ↔
    count a l = m ∧ count b l = n ∧ l ⊆ [a, b]
[PROOFSTEP]
simp (config := { contextual := true }) [count_replicate, h, h.symm, this]
[GOAL]
case this
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
a b : α
m n : ℕ
h : a ≠ b
⊢ l ⊆ [a, b] ↔ ∀ (c : α), c ≠ b → c ≠ a → ¬c ∈ l
[PROOFSTEP]
simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons, not_mem_nil, or_false, or_comm]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
⊢ l₁ ++ List.diff l₂ l₁ ~ l₂
[PROOFSTEP]
induction' l₁ with hd tl IH generalizing l₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
l₂ : List α
h : ∀ (x : α), x ∈ [] → count x [] ≤ count x l₂
⊢ [] ++ List.diff l₂ [] ~ l₂
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
⊢ hd :: tl ++ List.diff l₂ (hd :: tl) ~ l₂
[PROOFSTEP]
have : hd ∈ l₂ := by
  rw [← count_pos]
  exact lt_of_lt_of_le (count_pos.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
⊢ hd ∈ l₂
[PROOFSTEP]
rw [← count_pos]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
⊢ 0 < count hd l₂
[PROOFSTEP]
exact lt_of_lt_of_le (count_pos.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
this : hd ∈ l₂
⊢ hd :: tl ++ List.diff l₂ (hd :: tl) ~ l₂
[PROOFSTEP]
replace := perm_cons_erase this
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
this : l₂ ~ hd :: List.erase l₂ hd
⊢ hd :: tl ++ List.diff l₂ (hd :: tl) ~ l₂
[PROOFSTEP]
refine' Perm.trans _ this.symm
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
this : l₂ ~ hd :: List.erase l₂ hd
⊢ hd :: tl ++ List.diff l₂ (hd :: tl) ~ hd :: List.erase l₂ hd
[PROOFSTEP]
rw [cons_append, diff_cons, perm_cons]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
this : l₂ ~ hd :: List.erase l₂ hd
⊢ tl ++ List.diff (List.erase l₂ hd) tl ~ List.erase l₂ hd
[PROOFSTEP]
refine' IH fun x hx => _
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
h : ∀ (x : α), x ∈ hd :: tl → count x (hd :: tl) ≤ count x l₂
this : l₂ ~ hd :: List.erase l₂ hd
x : α
hx : x ∈ tl
⊢ count x tl ≤ count x (List.erase l₂ hd)
[PROOFSTEP]
specialize h x (mem_cons_of_mem _ hx)
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
this : l₂ ~ hd :: List.erase l₂ hd
x : α
hx : x ∈ tl
h : count x (hd :: tl) ≤ count x l₂
⊢ count x tl ≤ count x (List.erase l₂ hd)
[PROOFSTEP]
rw [perm_iff_count.mp this] at h 
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
this : l₂ ~ hd :: List.erase l₂ hd
x : α
hx : x ∈ tl
h : count x (hd :: tl) ≤ count x (hd :: List.erase l₂ hd)
⊢ count x tl ≤ count x (List.erase l₂ hd)
[PROOFSTEP]
by_cases hx : x = hd
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
this : l₂ ~ hd :: List.erase l₂ hd
x : α
hx✝ : x ∈ tl
h : count x (hd :: tl) ≤ count x (hd :: List.erase l₂ hd)
hx : x = hd
⊢ count x tl ≤ count x (List.erase l₂ hd)
[PROOFSTEP]
subst hd
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
x : α
hx : x ∈ tl
this : l₂ ~ x :: List.erase l₂ x
h : count x (x :: tl) ≤ count x (x :: List.erase l₂ x)
⊢ count x tl ≤ count x (List.erase l₂ x)
[PROOFSTEP]
simpa [Nat.succ_le_succ_iff] using h
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂✝ : List α
h✝ : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂✝
hd : α
tl : List α
IH : ∀ {l₂ : List α}, (∀ (x : α), x ∈ tl → count x tl ≤ count x l₂) → tl ++ List.diff l₂ tl ~ l₂
l₂ : List α
this : l₂ ~ hd :: List.erase l₂ hd
x : α
hx✝ : x ∈ tl
h : count x (hd :: tl) ≤ count x (hd :: List.erase l₂ hd)
hx : ¬x = hd
⊢ count x tl ≤ count x (List.erase l₂ hd)
[PROOFSTEP]
simpa [hx] using h
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ l₁ <+~ l₂ ↔ ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
[PROOFSTEP]
refine' ⟨fun h x _ => Subperm.count_le h x, fun h => _⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
⊢ l₁ <+~ l₂
[PROOFSTEP]
suffices l₁ <+~ l₂.diff l₁ ++ l₁ by
  refine' this.trans (Perm.subperm _)
  exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
this : l₁ <+~ List.diff l₂ l₁ ++ l₁
⊢ l₁ <+~ l₂
[PROOFSTEP]
refine' this.trans (Perm.subperm _)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
this : l₁ <+~ List.diff l₂ l₁ ++ l₁
⊢ List.diff l₂ l₁ ++ l₁ ~ l₂
[PROOFSTEP]
exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
⊢ l₁ <+~ List.diff l₂ l₁ ++ l₁
[PROOFSTEP]
exact (subperm_append_right l₁).mpr nil_subperm
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
l : List α
a : α
x✝ : [a] <+~ l
s : List α
hla : s ~ [a]
h : s <+ l
⊢ a ∈ l
[PROOFSTEP]
rwa [perm_singleton.mp hla, singleton_sublist] at h 
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h : l₁ <+~ l₂
x : α
hx : count x l₁ < count x l₂
⊢ x :: l₁ <+~ l₂
[PROOFSTEP]
rw [subperm_ext_iff] at h ⊢
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
⊢ ∀ (x_1 : α), x_1 ∈ x :: l₁ → count x_1 (x :: l₁) ≤ count x_1 l₂
[PROOFSTEP]
intro y hy
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
y : α
hy : y ∈ x :: l₁
⊢ count y (x :: l₁) ≤ count y l₂
[PROOFSTEP]
by_cases hy' : y = x
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
y : α
hy : y ∈ x :: l₁
hy' : y = x
⊢ count y (x :: l₁) ≤ count y l₂
[PROOFSTEP]
subst x
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
y : α
hx : count y l₁ < count y l₂
hy : y ∈ y :: l₁
⊢ count y (y :: l₁) ≤ count y l₂
[PROOFSTEP]
simpa using Nat.succ_le_of_lt hx
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
y : α
hy : y ∈ x :: l₁
hy' : ¬y = x
⊢ count y (x :: l₁) ≤ count y l₂
[PROOFSTEP]
rw [count_cons_of_ne hy']
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
y : α
hy : y ∈ x :: l₁
hy' : ¬y = x
⊢ count y l₁ ≤ count y l₂
[PROOFSTEP]
refine' h y _
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
h✝ : l₁ <+~ l₂
h : ∀ (x : α), x ∈ l₁ → count x l₁ ≤ count x l₂
x : α
hx : count x l₁ < count x l₂
y : α
hy : y ∈ x :: l₁
hy' : ¬y = x
⊢ y ∈ l₁
[PROOFSTEP]
simpa [hy'] using hy
[GOAL]
α : Type uu
β : Type vv
l₁ l₂✝ : List α
inst✝ : DecidableEq α
b : α
l₂ : List α
h : [] ~ b :: l₂
⊢ False
[PROOFSTEP]
have := h.nil_eq
[GOAL]
α : Type uu
β : Type vv
l₁ l₂✝ : List α
inst✝ : DecidableEq α
b : α
l₂ : List α
h : [] ~ b :: l₂
this : [] = b :: l₂
⊢ False
[PROOFSTEP]
contradiction
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
p : l₁ ~ l₂
a : α
h : a ∈ l₁
⊢ count a (List.dedup l₁) = count a (List.dedup l₂)
[PROOFSTEP]
simp [nodup_dedup, h, p.subset h]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ : List α
p : l₁ ~ l₂
a : α
h : ¬a ∈ l₁
⊢ count a (List.dedup l₁) = count a (List.dedup l₂)
[PROOFSTEP]
simp [h, mt p.mem_iff.2 h]
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
h : a ∈ l₁
⊢ List.insert a l₁ ~ List.insert a l₂
[PROOFSTEP]
simpa [h, p.subset h] using p
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
h : ¬a ∈ l₁
⊢ List.insert a l₁ ~ List.insert a l₂
[PROOFSTEP]
simpa [h, mt p.mem_iff.2 h] using p.cons a
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
by_cases xl : x ∈ l
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : x ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
by_cases yl : y ∈ l
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
by_cases yl : y ∈ l
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : x ∈ l
yl : y ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
simp [xl, yl]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : x ∈ l
yl : ¬y ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
simp [xl, yl]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : y ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
simp [xl, yl]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : ¬y ∈ l
⊢ List.insert x (List.insert y l) ~ List.insert y (List.insert x l)
[PROOFSTEP]
simp [xl, yl]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : ¬y ∈ l
⊢ List.insert x (y :: l) ~ List.insert y (x :: l)
[PROOFSTEP]
by_cases xy : x = y
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : ¬y ∈ l
xy : x = y
⊢ List.insert x (y :: l) ~ List.insert y (x :: l)
[PROOFSTEP]
simp [xy]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : ¬y ∈ l
xy : ¬x = y
⊢ List.insert x (y :: l) ~ List.insert y (x :: l)
[PROOFSTEP]
simp [List.insert, xl, yl, xy, Ne.symm xy]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x y : α
l : List α
xl : ¬x ∈ l
yl : ¬y ∈ l
xy : ¬x = y
⊢ x :: y :: l ~ y :: x :: l
[PROOFSTEP]
constructor
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h : n ≤ length l
⊢ insertNth n x l ~ x :: l
[PROOFSTEP]
induction' l with _ _ l_ih generalizing n
[GOAL]
case nil
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n✝ : ℕ
h✝ : n✝ ≤ length l
n : ℕ
h : n ≤ length []
⊢ insertNth n x [] ~ [x]
[PROOFSTEP]
cases n
[GOAL]
case nil.zero
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
h : zero ≤ length []
⊢ insertNth zero x [] ~ [x]
case nil.succ
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
n✝ : ℕ
h : succ n✝ ≤ length []
⊢ insertNth (succ n✝) x [] ~ [x]
[PROOFSTEP]
rfl
[GOAL]
case nil.succ
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
n✝ : ℕ
h : succ n✝ ≤ length []
⊢ insertNth (succ n✝) x [] ~ [x]
[PROOFSTEP]
cases h
[GOAL]
case cons
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n✝ : ℕ
h✝ : n✝ ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
n : ℕ
h : n ≤ length (head✝ :: tail✝)
⊢ insertNth n x (head✝ :: tail✝) ~ x :: head✝ :: tail✝
[PROOFSTEP]
cases n
[GOAL]
case cons.zero
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
h : zero ≤ length (head✝ :: tail✝)
⊢ insertNth zero x (head✝ :: tail✝) ~ x :: head✝ :: tail✝
[PROOFSTEP]
simp [insertNth]
[GOAL]
case cons.succ
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
n✝ : ℕ
h : succ n✝ ≤ length (head✝ :: tail✝)
⊢ insertNth (succ n✝) x (head✝ :: tail✝) ~ x :: head✝ :: tail✝
[PROOFSTEP]
simp only [insertNth, modifyNthTail]
[GOAL]
case cons.succ
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
n✝ : ℕ
h : succ n✝ ≤ length (head✝ :: tail✝)
⊢ head✝ :: modifyNthTail (cons x) n✝ tail✝ ~ x :: head✝ :: tail✝
[PROOFSTEP]
refine' Perm.trans (Perm.cons _ (l_ih _)) _
[GOAL]
case cons.succ.refine'_1
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
n✝ : ℕ
h : succ n✝ ≤ length (head✝ :: tail✝)
⊢ n✝ ≤ length tail✝
[PROOFSTEP]
apply Nat.le_of_succ_le_succ h
[GOAL]
case cons.succ.refine'_2
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
inst✝ : DecidableEq α✝
α : Type u_1
x : α
l : List α
n : ℕ
h✝ : n ≤ length l
head✝ : α
tail✝ : List α
l_ih : ∀ {n : ℕ}, n ≤ length tail✝ → insertNth n x tail✝ ~ x :: tail✝
n✝ : ℕ
h : succ n✝ ≤ length (head✝ :: tail✝)
⊢ head✝ :: x :: tail✝ ~ x :: head✝ :: tail✝
[PROOFSTEP]
apply Perm.swap
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
h : l₁ ~ l₂
⊢ l₁ ∪ t₁ ~ l₂ ∪ t₁
[PROOFSTEP]
induction' h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
⊢ [] ∪ t₁ ~ [] ∪ t₁
[PROOFSTEP]
try simp
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
⊢ [] ∪ t₁ ~ [] ∪ t₁
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
a : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
ih : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
⊢ a :: l₁✝ ∪ t₁ ~ a :: l₂✝ ∪ t₁
[PROOFSTEP]
try simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
a : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
ih : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
⊢ a :: l₁✝ ∪ t₁ ~ a :: l₂✝ ∪ t₁
[PROOFSTEP]
simp
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
x✝ y✝ : α
l✝ : List α
⊢ y✝ :: x✝ :: l✝ ∪ t₁ ~ x✝ :: y✝ :: l✝ ∪ t₁
[PROOFSTEP]
try simp
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
x✝ y✝ : α
l✝ : List α
⊢ y✝ :: x✝ :: l✝ ∪ t₁ ~ x✝ :: y✝ :: l✝ ∪ t₁
[PROOFSTEP]
simp
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih_1 : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
ih_2 : l₂✝ ∪ t₁ ~ l₃✝ ∪ t₁
⊢ l₁✝ ∪ t₁ ~ l₃✝ ∪ t₁
[PROOFSTEP]
try simp
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih_1 : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
ih_2 : l₂✝ ∪ t₁ ~ l₃✝ ∪ t₁
⊢ l₁✝ ∪ t₁ ~ l₃✝ ∪ t₁
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
a : α
l₁✝ l₂✝ : List α
a✝ : l₁✝ ~ l₂✝
ih : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
⊢ List.insert a (l₁✝ ∪ t₁) ~ List.insert a (l₂✝ ∪ t₁)
[PROOFSTEP]
exact ih.insert a
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ : List α
x✝ y✝ : α
l✝ : List α
⊢ List.insert y✝ (List.insert x✝ (l✝ ∪ t₁)) ~ List.insert x✝ (List.insert y✝ (l✝ ∪ t₁))
[PROOFSTEP]
apply perm_insert_swap
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
inst✝ : DecidableEq α
l₁ l₂ t₁ l₁✝ l₂✝ l₃✝ : List α
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih_1 : l₁✝ ∪ t₁ ~ l₂✝ ∪ t₁
ih_2 : l₂✝ ∪ t₁ ~ l₃✝ ∪ t₁
⊢ l₁✝ ∪ t₁ ~ l₃✝ ∪ t₁
[PROOFSTEP]
exact ih_1.trans ih_2
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l t₁ t₂ : List α
h : t₁ ~ t₂
⊢ l ∪ t₁ ~ l ∪ t₂
[PROOFSTEP]
induction l
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : t₁ ~ t₂
⊢ [] ∪ t₁ ~ [] ∪ t₂
[PROOFSTEP]
simp [*, Perm.insert]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : t₁ ~ t₂
head✝ : α
tail✝ : List α
tail_ih✝ : tail✝ ∪ t₁ ~ tail✝ ∪ t₂
⊢ head✝ :: tail✝ ∪ t₁ ~ head✝ :: tail✝ ∪ t₂
[PROOFSTEP]
simp [*, Perm.insert]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l t₁ t₂ : List α
p : t₁ ~ t₂
a : α
x✝ : a ∈ l
⊢ decide (a ∈ t₁) = true ↔ decide (a ∈ t₂) = true
[PROOFSTEP]
simpa using p.mem_iff
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l t₁ t₂ : List α
h : Disjoint t₁ t₂
⊢ l ∩ (t₁ ++ t₂) ~ l ∩ t₁ ++ l ∩ t₂
[PROOFSTEP]
induction l
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
⊢ [] ∩ (t₁ ++ t₂) ~ [] ∩ t₁ ++ [] ∩ t₂
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
head✝ : α
tail✝ : List α
tail_ih✝ : tail✝ ∩ (t₁ ++ t₂) ~ tail✝ ∩ t₁ ++ tail✝ ∩ t₂
⊢ (head✝ :: tail✝) ∩ (t₁ ++ t₂) ~ (head✝ :: tail✝) ∩ t₁ ++ (head✝ :: tail✝) ∩ t₂
[PROOFSTEP]
case nil => simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
⊢ [] ∩ (t₁ ++ t₂) ~ [] ∩ t₁ ++ [] ∩ t₂
[PROOFSTEP]
case nil => simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
⊢ [] ∩ (t₁ ++ t₂) ~ [] ∩ t₁ ++ [] ∩ t₂
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
head✝ : α
tail✝ : List α
tail_ih✝ : tail✝ ∩ (t₁ ++ t₂) ~ tail✝ ∩ t₁ ++ tail✝ ∩ t₂
⊢ (head✝ :: tail✝) ∩ (t₁ ++ t₂) ~ (head✝ :: tail✝) ∩ t₁ ++ (head✝ :: tail✝) ∩ t₂
[PROOFSTEP]
case cons x xs l_ih =>
  by_cases h₁ : x ∈ t₁
  · have h₂ : x ∉ t₂ := h h₁
    simp [*]
  by_cases h₂ : x ∈ t₂
  · simp only [*, inter_cons_of_not_mem, false_or_iff, mem_append, inter_cons_of_mem, not_false_iff]
    refine' Perm.trans (Perm.cons _ l_ih) _
    change [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ ([x] ++ xs ∩ t₂)
    rw [← List.append_assoc]
    solve_by_elim [Perm.append_right, perm_append_comm]
  · simp [*]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
case cons x xs l_ih =>
  by_cases h₁ : x ∈ t₁
  · have h₂ : x ∉ t₂ := h h₁
    simp [*]
  by_cases h₂ : x ∈ t₂
  · simp only [*, inter_cons_of_not_mem, false_or_iff, mem_append, inter_cons_of_mem, not_false_iff]
    refine' Perm.trans (Perm.cons _ l_ih) _
    change [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ ([x] ++ xs ∩ t₂)
    rw [← List.append_assoc]
    solve_by_elim [Perm.append_right, perm_append_comm]
  · simp [*]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
by_cases h₁ : x ∈ t₁
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : x ∈ t₁
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
have h₂ : x ∉ t₂ := h h₁
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : x ∈ t₁
h₂ : ¬x ∈ t₂
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
simp [*]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
by_cases h₂ : x ∈ t₂
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : x ∈ t₂
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
simp only [*, inter_cons_of_not_mem, false_or_iff, mem_append, inter_cons_of_mem, not_false_iff]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : x ∈ t₂
⊢ x :: xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ x :: xs ∩ t₂
[PROOFSTEP]
refine' Perm.trans (Perm.cons _ l_ih) _
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : x ∈ t₂
⊢ x :: (xs ∩ t₁ ++ xs ∩ t₂) ~ xs ∩ t₁ ++ x :: xs ∩ t₂
[PROOFSTEP]
change [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ ([x] ++ xs ∩ t₂)
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : x ∈ t₂
⊢ [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ ([x] ++ xs ∩ t₂)
[PROOFSTEP]
rw [← List.append_assoc]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : x ∈ t₂
⊢ [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ [x] ++ xs ∩ t₂
[PROOFSTEP]
solve_by_elim [Perm.append_right, perm_append_comm]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
t₁ t₂ : List α
h : Disjoint t₁ t₂
x : α
xs : List α
l_ih : xs ∩ (t₁ ++ t₂) ~ xs ∩ t₁ ++ xs ∩ t₂
h₁ : ¬x ∈ t₁
h₂ : ¬x ∈ t₂
⊢ (x :: xs) ∩ (t₁ ++ t₂) ~ (x :: xs) ∩ t₁ ++ (x :: xs) ∩ t₂
[PROOFSTEP]
simp [*]
[GOAL]
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
R : α → α → Prop
S : Symmetric R
l₁✝ l₂✝ l₁ l₂ : List α
p : l₁ ~ l₂
d : Pairwise R l₁
⊢ Pairwise R l₂
[PROOFSTEP]
induction' d with a l₁ h _ IH generalizing l₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝¹ l₂✝² : List α
R : α → α → Prop
S : Symmetric R
l₁✝ l₂✝¹ l₁ l₂✝ : List α
p✝ : l₁ ~ l₂✝
l₂ : List α
p : [] ~ l₂
⊢ Pairwise R l₂
[PROOFSTEP]
rw [← p.nil_eq]
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝¹ l₂✝² : List α
R : α → α → Prop
S : Symmetric R
l₁✝ l₂✝¹ l₁ l₂✝ : List α
p✝ : l₁ ~ l₂✝
l₂ : List α
p : [] ~ l₂
⊢ Pairwise R []
[PROOFSTEP]
constructor
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝² l₂✝² : List α
R : α → α → Prop
S : Symmetric R
l₁✝¹ l₂✝¹ l₁✝ l₂✝ : List α
p✝ : l₁✝ ~ l₂✝
a : α
l₁ : List α
h : ∀ (a' : α), a' ∈ l₁ → R a a'
a✝ : Pairwise R l₁
IH : ∀ (l₂ : List α), l₁ ~ l₂ → Pairwise R l₂
l₂ : List α
p : a :: l₁ ~ l₂
⊢ Pairwise R l₂
[PROOFSTEP]
have : a ∈ l₂ := p.subset (mem_cons_self _ _)
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝² l₂✝² : List α
R : α → α → Prop
S : Symmetric R
l₁✝¹ l₂✝¹ l₁✝ l₂✝ : List α
p✝ : l₁✝ ~ l₂✝
a : α
l₁ : List α
h : ∀ (a' : α), a' ∈ l₁ → R a a'
a✝ : Pairwise R l₁
IH : ∀ (l₂ : List α), l₁ ~ l₂ → Pairwise R l₂
l₂ : List α
p : a :: l₁ ~ l₂
this : a ∈ l₂
⊢ Pairwise R l₂
[PROOFSTEP]
rcases mem_split this with ⟨s₂, t₂, rfl⟩
[GOAL]
case cons.intro.intro
α : Type uu
β : Type vv
l₁✝² l₂✝¹ : List α
R : α → α → Prop
S : Symmetric R
l₁✝¹ l₂✝ l₁✝ l₂ : List α
p✝ : l₁✝ ~ l₂
a : α
l₁ : List α
h : ∀ (a' : α), a' ∈ l₁ → R a a'
a✝ : Pairwise R l₁
IH : ∀ (l₂ : List α), l₁ ~ l₂ → Pairwise R l₂
s₂ t₂ : List α
p : a :: l₁ ~ s₂ ++ a :: t₂
this : a ∈ s₂ ++ a :: t₂
⊢ Pairwise R (s₂ ++ a :: t₂)
[PROOFSTEP]
have p' := (p.trans perm_middle).cons_inv
[GOAL]
case cons.intro.intro
α : Type uu
β : Type vv
l₁✝² l₂✝¹ : List α
R : α → α → Prop
S : Symmetric R
l₁✝¹ l₂✝ l₁✝ l₂ : List α
p✝ : l₁✝ ~ l₂
a : α
l₁ : List α
h : ∀ (a' : α), a' ∈ l₁ → R a a'
a✝ : Pairwise R l₁
IH : ∀ (l₂ : List α), l₁ ~ l₂ → Pairwise R l₂
s₂ t₂ : List α
p : a :: l₁ ~ s₂ ++ a :: t₂
this : a ∈ s₂ ++ a :: t₂
p' : l₁ ~ s₂ ++ t₂
⊢ Pairwise R (s₂ ++ a :: t₂)
[PROOFSTEP]
refine' (pairwise_middle S).2 (pairwise_cons.2 ⟨fun b m => _, IH _ p'⟩)
[GOAL]
case cons.intro.intro
α : Type uu
β : Type vv
l₁✝² l₂✝¹ : List α
R : α → α → Prop
S : Symmetric R
l₁✝¹ l₂✝ l₁✝ l₂ : List α
p✝ : l₁✝ ~ l₂
a : α
l₁ : List α
h : ∀ (a' : α), a' ∈ l₁ → R a a'
a✝ : Pairwise R l₁
IH : ∀ (l₂ : List α), l₁ ~ l₂ → Pairwise R l₂
s₂ t₂ : List α
p : a :: l₁ ~ s₂ ++ a :: t₂
this : a ∈ s₂ ++ a :: t₂
p' : l₁ ~ s₂ ++ t₂
b : α
m : b ∈ s₂ ++ t₂
⊢ R a b
[PROOFSTEP]
exact h _ (p'.symm.subset m)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
l₁ l₂ : List (List α)
h : l₁ ~ l₂
x₁ x₂ : List α
xs : List (List α)
⊢ List.join (x₂ :: x₁ :: xs) ~ List.join (x₁ :: x₂ :: xs)
[PROOFSTEP]
simpa only [join, append_assoc] using perm_append_comm.append_right _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
f g : α → List β
h : ∀ (a : α), a ∈ l → f a ~ g a
⊢ Forall₂ (fun x x_1 => x ~ x_1) (List.map f l) (List.map g l)
[PROOFSTEP]
rwa [List.forall₂_map_right_iff, List.forall₂_map_left_iff, List.forall₂_same]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
f g : α → List β
⊢ List.bind l f ++ List.bind l g ~ List.bind l fun x => f x ++ g x
[PROOFSTEP]
induction' l with a l IH
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
f g : α → List β
⊢ List.bind [] f ++ List.bind [] g ~ List.bind [] fun x => f x ++ g x
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
f g : α → List β
a : α
l : List α
IH : List.bind l f ++ List.bind l g ~ List.bind l fun x => f x ++ g x
⊢ List.bind (a :: l) f ++ List.bind (a :: l) g ~ List.bind (a :: l) fun x => f x ++ g x
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
f g : α → List β
a : α
l : List α
IH : List.bind l f ++ List.bind l g ~ List.bind l fun x => f x ++ g x
⊢ f a ++ (List.bind l f ++ (g a ++ List.bind l g)) ~ f a ++ (g a ++ List.bind l fun x => f x ++ g x)
[PROOFSTEP]
refine' (Perm.trans _ (IH.append_left _)).append_left _
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
f g : α → List β
a : α
l : List α
IH : List.bind l f ++ List.bind l g ~ List.bind l fun x => f x ++ g x
⊢ List.bind l f ++ (g a ++ List.bind l g) ~ g a ++ (List.bind l f ++ List.bind l g)
[PROOFSTEP]
rw [← append_assoc, ← append_assoc]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
f g : α → List β
a : α
l : List α
IH : List.bind l f ++ List.bind l g ~ List.bind l fun x => f x ++ g x
⊢ List.bind l f ++ g a ++ List.bind l g ~ g a ++ List.bind l f ++ List.bind l g
[PROOFSTEP]
exact perm_append_comm.append_right _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ l : List α
f : α → β
g : α → List β
⊢ map f l ++ List.bind l g ~ List.bind l fun x => f x :: g x
[PROOFSTEP]
simpa [← map_eq_bind] using bind_append_perm l (fun x => [f x]) g
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
p : l₁ ~ l₂
⊢ lookmap f l₁ ~ lookmap f l₂
[PROOFSTEP]
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ _ IH₁ IH₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) []
⊢ lookmap f [] ~ lookmap f []
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (a :: l₁)
⊢ lookmap f (a :: l₁) ~ lookmap f (a :: l₂)
[PROOFSTEP]
cases h : f a
[GOAL]
case cons.none
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (a :: l₁)
h : f a = none
⊢ lookmap f (a :: l₁) ~ lookmap f (a :: l₂)
[PROOFSTEP]
simp [h]
[GOAL]
case cons.none
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (a :: l₁)
h : f a = none
⊢ lookmap f l₁ ~ lookmap f l₂
[PROOFSTEP]
exact IH (pairwise_cons.1 H).2
[GOAL]
case cons.some
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (a :: l₁)
val✝ : α
h : f a = some val✝
⊢ lookmap f (a :: l₁) ~ lookmap f (a :: l₂)
[PROOFSTEP]
simp [lookmap_cons_some _ _ h, p]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
cases' h₁ : f a with c
[GOAL]
case swap.none
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
h₁ : f a = none
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
cases' h₂ : f b with d
[GOAL]
case swap.some
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
c : α
h₁ : f a = some c
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
cases' h₂ : f b with d
[GOAL]
case swap.none.none
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
h₁ : f a = none
h₂ : f b = none
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
simp [h₁, h₂]
[GOAL]
case swap.none.none
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
h₁ : f a = none
h₂ : f b = none
⊢ b :: a :: lookmap f l ~ a :: b :: lookmap f l
[PROOFSTEP]
apply swap
[GOAL]
case swap.none.some
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
h₁ : f a = none
d : α
h₂ : f b = some d
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
simp [h₁, lookmap_cons_some _ _ h₂]
[GOAL]
case swap.none.some
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
h₁ : f a = none
d : α
h₂ : f b = some d
⊢ d :: a :: l ~ a :: d :: l
[PROOFSTEP]
apply swap
[GOAL]
case swap.some.none
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
c : α
h₁ : f a = some c
h₂ : f b = none
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
simp [lookmap_cons_some _ _ h₁, h₂]
[GOAL]
case swap.some.none
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
c : α
h₁ : f a = some c
h₂ : f b = none
⊢ b :: c :: l ~ c :: b :: l
[PROOFSTEP]
apply swap
[GOAL]
case swap.some.some
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
c : α
h₁ : f a = some c
d : α
h₂ : f b = some d
⊢ lookmap f (b :: a :: l) ~ lookmap f (a :: b :: l)
[PROOFSTEP]
simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂]
[GOAL]
case swap.some.some
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
a b : α
l : List α
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: a :: l)
c : α
h₁ : f a = some c
d : α
h₂ : f b = some d
⊢ d :: a :: l ~ c :: b :: l
[PROOFSTEP]
rcases(pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) _ h₂ _ h₁ with ⟨rfl, rfl⟩
[GOAL]
case swap.some.some.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Option α
l₁ l₂ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
b : α
l : List α
d : α
h₂ : f b = some d
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) (b :: b :: l)
h₁ : f b = some d
⊢ d :: b :: l ~ d :: b :: l
[PROOFSTEP]
exact Perm.refl _
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
l₁ l₂ l₃ : List α
p₁ : l₁ ~ l₂
a✝ : l₂ ~ l₃
IH₁ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
IH₂ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₂ → lookmap f l₂ ~ lookmap f l₃
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
⊢ lookmap f l₁ ~ lookmap f l₃
[PROOFSTEP]
refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Option α
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁✝
l₁ l₂ l₃ : List α
p₁ : l₁ ~ l₂
a✝ : l₂ ~ l₃
IH₁ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁ → lookmap f l₁ ~ lookmap f l₂
IH₂ : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₂ → lookmap f l₂ ~ lookmap f l₃
H : Pairwise (fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d) l₁
⊢ Symmetric fun a b => ∀ (c : α), c ∈ f a → ∀ (d : α), d ∈ f b → a = b ∧ c = d
[PROOFSTEP]
exact fun a b h c h₁ d h₂ => (h d h₂ c h₁).imp Eq.symm Eq.symm
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H : Pairwise (fun a b => f a → f b → False) l₁
p : l₁ ~ l₂
⊢ eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
[PROOFSTEP]
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ _ IH₁ IH₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
H : Pairwise (fun a b => f a → f b → False) []
⊢ eraseP (fun b => decide (f b)) [] ~ eraseP (fun b => decide (f b)) []
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
H : Pairwise (fun a b => f a → f b → False) (a :: l₁)
⊢ eraseP (fun b => decide (f b)) (a :: l₁) ~ eraseP (fun b => decide (f b)) (a :: l₂)
[PROOFSTEP]
by_cases h : f a
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
H : Pairwise (fun a b => f a → f b → False) (a :: l₁)
h : f a
⊢ eraseP (fun b => decide (f b)) (a :: l₁) ~ eraseP (fun b => decide (f b)) (a :: l₂)
[PROOFSTEP]
simp [h, p]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
H : Pairwise (fun a b => f a → f b → False) (a :: l₁)
h : ¬f a
⊢ eraseP (fun b => decide (f b)) (a :: l₁) ~ eraseP (fun b => decide (f b)) (a :: l₂)
[PROOFSTEP]
simp [h]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
a : α
l₁ l₂ : List α
p : l₁ ~ l₂
IH : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
H : Pairwise (fun a b => f a → f b → False) (a :: l₁)
h : ¬f a
⊢ eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
[PROOFSTEP]
exact IH (pairwise_cons.1 H).2
[GOAL]
case swap
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
by_cases h₁ : f a
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : f a
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
by_cases h₂ : f b
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : ¬f a
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
by_cases h₂ : f b
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : f a
h₂ : f b
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
simp [h₁, h₂]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : f a
h₂ : ¬f b
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
simp [h₁, h₂]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : ¬f a
h₂ : f b
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
simp [h₁, h₂]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : ¬f a
h₂ : ¬f b
⊢ eraseP (fun b => decide (f b)) (b :: a :: l) ~ eraseP (fun b => decide (f b)) (a :: b :: l)
[PROOFSTEP]
simp [h₁, h₂]
[GOAL]
case pos
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : f a
h₂ : f b
⊢ a :: l ~ b :: l
[PROOFSTEP]
cases (pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) h₂ h₁
[GOAL]
case neg
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁ l₂ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁
a b : α
l : List α
H : Pairwise (fun a b => f a → f b → False) (b :: a :: l)
h₁ : ¬f a
h₂ : ¬f b
⊢ b :: a :: eraseP (fun b => decide (f b)) l ~ a :: b :: eraseP (fun b => decide (f b)) l
[PROOFSTEP]
apply swap
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
l₁ l₂ l₃ : List α
p₁ : l₁ ~ l₂
a✝ : l₂ ~ l₃
IH₁ : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
IH₂ : Pairwise (fun a b => f a → f b → False) l₂ → eraseP (fun b => decide (f b)) l₂ ~ eraseP (fun b => decide (f b)) l₃
H : Pairwise (fun a b => f a → f b → False) l₁
⊢ eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₃
[PROOFSTEP]
refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
[GOAL]
case trans
α : Type uu
β : Type vv
l₁✝¹ l₂✝¹ : List α
f : α → Prop
inst✝ : DecidablePred f
l₁✝ l₂✝ : List α
H✝ : Pairwise (fun a b => f a → f b → False) l₁✝
l₁ l₂ l₃ : List α
p₁ : l₁ ~ l₂
a✝ : l₂ ~ l₃
IH₁ : Pairwise (fun a b => f a → f b → False) l₁ → eraseP (fun b => decide (f b)) l₁ ~ eraseP (fun b => decide (f b)) l₂
IH₂ : Pairwise (fun a b => f a → f b → False) l₂ → eraseP (fun b => decide (f b)) l₂ ~ eraseP (fun b => decide (f b)) l₃
H : Pairwise (fun a b => f a → f b → False) l₁
⊢ Symmetric fun a b => f a → f b → False
[PROOFSTEP]
exact fun a b h h₁ h₂ => h h₂ h₁
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ take n xs ~ List.inter ys (take n xs)
[PROOFSTEP]
simp only [List.inter]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ take n xs ~ List.filter (fun x => decide (x ∈ take n xs)) ys
[PROOFSTEP]
exact
  Perm.trans
    (show xs.take n ~ xs.filter (· ∈ xs.take n) by conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')])
    (Perm.filter _ h)
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ take n xs ~ List.filter (fun x => decide (x ∈ take n xs)) xs
[PROOFSTEP]
conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
| take n xs
[PROOFSTEP]
rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
| take n xs
[PROOFSTEP]
rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
| take n xs
[PROOFSTEP]
rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
by_cases h'' : n ≤ xs.length
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
let n' := xs.length - n
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
have h₀ : n = xs.length - n' := by rwa [tsub_tsub_cancel_of_le]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
⊢ n = length xs - n'
[PROOFSTEP]
rwa [tsub_tsub_cancel_of_le]
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
have h₁ : n' ≤ xs.length := by apply tsub_le_self
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
⊢ n' ≤ length xs
[PROOFSTEP]
apply tsub_le_self
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
have h₂ : xs.drop n = (xs.reverse.take n').reverse := by rw [reverse_take _ h₁, h₀, reverse_reverse]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
⊢ drop n xs = reverse (take n' (reverse xs))
[PROOFSTEP]
rw [reverse_take _ h₁, h₀, reverse_reverse]
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
rw [h₂]
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ reverse (take n' (reverse xs)) ~ List.inter ys (reverse (take n' (reverse xs)))
[PROOFSTEP]
apply (reverse_perm _).trans
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ take n' (reverse xs) ~ List.inter ys (reverse (take n' (reverse xs)))
[PROOFSTEP]
rw [inter_reverse]
[GOAL]
case pos
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ take n' (reverse xs) ~ List.inter ys (take n' (reverse xs))
[PROOFSTEP]
apply Perm.take_inter _ _ h'
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ reverse xs ~ ys
[PROOFSTEP]
apply (reverse_perm _).trans
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : n ≤ length xs
n' : ℕ := length xs - n
h₀ : n = length xs - n'
h₁ : n' ≤ length xs
h₂ : drop n xs = reverse (take n' (reverse xs))
⊢ xs ~ ys
[PROOFSTEP]
assumption
[GOAL]
case neg
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : ¬n ≤ length xs
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
have : drop n xs = [] := by
  apply eq_nil_of_length_eq_zero
  rw [length_drop, tsub_eq_zero_iff_le]
  apply le_of_not_ge h''
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : ¬n ≤ length xs
⊢ drop n xs = []
[PROOFSTEP]
apply eq_nil_of_length_eq_zero
[GOAL]
case x
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : ¬n ≤ length xs
⊢ length (drop n xs) = 0
[PROOFSTEP]
rw [length_drop, tsub_eq_zero_iff_le]
[GOAL]
case x
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : ¬n ≤ length xs
⊢ length xs ≤ n
[PROOFSTEP]
apply le_of_not_ge h''
[GOAL]
case neg
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n : ℕ
h : xs ~ ys
h' : Nodup ys
h'' : ¬n ≤ length xs
this : drop n xs = []
⊢ drop n xs ~ List.inter ys (drop n xs)
[PROOFSTEP]
simp [this, List.inter]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ dropSlice n m xs ~ ys ∩ dropSlice n m xs
[PROOFSTEP]
simp only [dropSlice_eq]
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
⊢ take n xs ++ drop (n + m) xs ~ ys ∩ (take n xs ++ drop (n + m) xs)
[PROOFSTEP]
have : n ≤ n + m := Nat.le_add_right _ _
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
this : n ≤ n + m
⊢ take n xs ++ drop (n + m) xs ~ ys ∩ (take n xs ++ drop (n + m) xs)
[PROOFSTEP]
have h₂ := h.nodup_iff.2 h'
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
this : n ≤ n + m
h₂ : Nodup xs
⊢ take n xs ++ drop (n + m) xs ~ ys ∩ (take n xs ++ drop (n + m) xs)
[PROOFSTEP]
apply Perm.trans _ (Perm.inter_append _).symm
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
this : n ≤ n + m
h₂ : Nodup xs
⊢ take n xs ++ drop (n + m) xs ~ ys ∩ take n xs ++ ys ∩ drop (n + m) xs
[PROOFSTEP]
exact Perm.append (Perm.take_inter _ h h') (Perm.drop_inter _ h h')
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
xs ys : List α
n m : ℕ
h : xs ~ ys
h' : Nodup ys
this : n ≤ n + m
h₂ : Nodup xs
⊢ Disjoint (take n xs) (drop (n + m) xs)
[PROOFSTEP]
exact disjoint_take_drop h₂ this
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ {ts is l : List α}, l ∈ permutationsAux ts is → l ~ ts ++ is
[PROOFSTEP]
show ∀ (ts is l : List α), l ∈ permutationsAux ts is → l ~ ts ++ is
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (ts is l : List α), l ∈ permutationsAux ts is → l ~ ts ++ is
[PROOFSTEP]
refine' permutationsAux.rec (by simp) _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (is l : List α), l ∈ permutationsAux [] is → l ~ [] ++ is
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (t : α) (ts is : List α),
    (∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is) →
      (∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []) →
        ∀ (l : List α), l ∈ permutationsAux (t :: ts) is → l ~ t :: ts ++ is
[PROOFSTEP]
introv IH1 IH2 m
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l : List α
m : l ∈ permutationsAux (t :: ts) is
⊢ l ~ t :: ts ++ is
[PROOFSTEP]
rw [permutationsAux_cons, permutations, mem_foldr_permutationsAux2] at m 
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l : List α
m :
  l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ is :: permutationsAux is [] ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts
⊢ l ~ t :: ts ++ is
[PROOFSTEP]
rcases m with (m | ⟨l₁, l₂, m, _, e⟩)
[GOAL]
case inl
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l : List α
m : l ∈ permutationsAux ts (t :: is)
⊢ l ~ t :: ts ++ is
[PROOFSTEP]
exact (IH1 _ m).trans perm_middle
[GOAL]
case inr.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l l₁ l₂ : List α
m : l₁ ++ l₂ ∈ is :: permutationsAux is []
left✝ : l₂ ≠ []
e : l = l₁ ++ t :: l₂ ++ ts
⊢ l ~ t :: ts ++ is
[PROOFSTEP]
subst e
[GOAL]
case inr.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
m : l₁ ++ l₂ ∈ is :: permutationsAux is []
left✝ : l₂ ≠ []
⊢ l₁ ++ t :: l₂ ++ ts ~ t :: ts ++ is
[PROOFSTEP]
have p : l₁ ++ l₂ ~ is := by
  simp [permutations] at m 
  cases' m with e m
  · simp [e]
  exact is.append_nil ▸ IH2 _ m
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
m : l₁ ++ l₂ ∈ is :: permutationsAux is []
left✝ : l₂ ≠ []
⊢ l₁ ++ l₂ ~ is
[PROOFSTEP]
simp [permutations] at m 
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
left✝ : l₂ ≠ []
m : l₁ ++ l₂ = is ∨ l₁ ++ l₂ ∈ permutationsAux is []
⊢ l₁ ++ l₂ ~ is
[PROOFSTEP]
cases' m with e m
[GOAL]
case inl
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
left✝ : l₂ ≠ []
e : l₁ ++ l₂ = is
⊢ l₁ ++ l₂ ~ is
[PROOFSTEP]
simp [e]
[GOAL]
case inr
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
left✝ : l₂ ≠ []
m : l₁ ++ l₂ ∈ permutationsAux is []
⊢ l₁ ++ l₂ ~ is
[PROOFSTEP]
exact is.append_nil ▸ IH2 _ m
[GOAL]
case inr.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ∈ permutationsAux ts (t :: is) → l ~ ts ++ t :: is
IH2 : ∀ (l : List α), l ∈ permutationsAux is [] → l ~ is ++ []
l₁ l₂ : List α
m : l₁ ++ l₂ ∈ is :: permutationsAux is []
left✝ : l₂ ≠ []
p : l₁ ++ l₂ ~ is
⊢ l₁ ++ t :: l₂ ++ ts ~ t :: ts ++ is
[PROOFSTEP]
exact ((perm_middle.trans (p.cons _)).append_right _).trans (perm_append_comm.cons _)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (ts is : List α), length (permutationsAux ts is) + (length is)! = (length ts + length is)!
[PROOFSTEP]
refine' permutationsAux.rec (by simp) _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (is : List α), length (permutationsAux [] is) + (length is)! = (length [] + length is)!
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (t : α) (ts is : List α),
    length (permutationsAux ts (t :: is)) + (length (t :: is))! = (length ts + length (t :: is))! →
      length (permutationsAux is []) + (length [])! = (length is + length [])! →
        length (permutationsAux (t :: ts) is) + (length is)! = (length (t :: ts) + length is)!
[PROOFSTEP]
intro t ts is IH1 IH2
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : length (permutationsAux ts (t :: is)) + (length (t :: is))! = (length ts + length (t :: is))!
IH2 : length (permutationsAux is []) + (length [])! = (length is + length [])!
⊢ length (permutationsAux (t :: ts) is) + (length is)! = (length (t :: ts) + length is)!
[PROOFSTEP]
have IH2 : length (permutationsAux is nil) + 1 = is.length ! := by simpa using IH2
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : length (permutationsAux ts (t :: is)) + (length (t :: is))! = (length ts + length (t :: is))!
IH2 : length (permutationsAux is []) + (length [])! = (length is + length [])!
⊢ length (permutationsAux is []) + 1 = (length is)!
[PROOFSTEP]
simpa using IH2
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : length (permutationsAux ts (t :: is)) + (length (t :: is))! = (length ts + length (t :: is))!
IH2✝ : length (permutationsAux is []) + (length [])! = (length is + length [])!
IH2 : length (permutationsAux is []) + 1 = (length is)!
⊢ length (permutationsAux (t :: ts) is) + (length is)! = (length (t :: ts) + length is)!
[PROOFSTEP]
simp [Nat.factorial, Nat.add_succ, mul_comm] at IH1 
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH2✝ : length (permutationsAux is []) + (length [])! = (length is + length [])!
IH2 : length (permutationsAux is []) + 1 = (length is)!
IH1 :
  length (permutationsAux ts (t :: is)) + (length is)! * succ (length is) =
    (length ts + length is)! * succ (length ts + length is)
⊢ length (permutationsAux (t :: ts) is) + (length is)! = (length (t :: ts) + length is)!
[PROOFSTEP]
rw [permutationsAux_cons, length_foldr_permutationsAux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
  permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (_ + 1), ← Nat.succ_eq_add_one, ← IH1,
  add_comm (_ * _), add_assoc, Nat.mul_succ, mul_comm]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ is l : List α
H : l ~ [] ++ is → (∃ ts' x, l = ts' ++ is) ∨ l ∈ permutationsAux is []
⊢ l ~ is → l ∈ permutations is
[PROOFSTEP]
simpa [permutations, perm_nil] using H
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ {ts is l : List α}, l ~ is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts is
[PROOFSTEP]
show ∀ (ts is l : List α), l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (ts is l : List α), l ~ is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts is
[PROOFSTEP]
refine' permutationsAux.rec (by simp) _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (is l : List α), l ~ is ++ [] → (∃ is' x, l = is' ++ []) ∨ l ∈ permutationsAux [] is
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
⊢ ∀ (t : α) (ts is : List α),
    (∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)) →
      (∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []) →
        ∀ (l : List α), l ~ is ++ t :: ts → (∃ is' x, l = is' ++ t :: ts) ∨ l ∈ permutationsAux (t :: ts) is
[PROOFSTEP]
intro t ts is IH1 IH2 l p
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l : List α
p : l ~ is ++ t :: ts
⊢ (∃ is' x, l = is' ++ t :: ts) ∨ l ∈ permutationsAux (t :: ts) is
[PROOFSTEP]
rw [permutationsAux_cons, mem_foldr_permutationsAux2]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l : List α
p : l ~ is ++ t :: ts
⊢ (∃ is' x, l = is' ++ t :: ts) ∨
    l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
[GOAL]
case inl.intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l : List α
p : l ~ is ++ t :: ts
is' : List α
p' : is' ~ t :: is
e : l = is' ++ ts
⊢ (∃ is' x, l = is' ++ t :: ts) ∨
    l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
clear p
[GOAL]
case inl.intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l is' : List α
p' : is' ~ t :: is
e : l = is' ++ ts
⊢ (∃ is' x, l = is' ++ t :: ts) ∨
    l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
subst e
[GOAL]
case inl.intro.intro
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
is' : List α
p' : is' ~ t :: is
⊢ (∃ is'_1 x, is' ++ ts = is'_1 ++ t :: ts) ∨
    is' ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ is' ++ ts = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
[GOAL]
case inl.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
is' : List α
p' : is' ~ t :: is
l₁ l₂ : List α
e : is' = l₁ ++ t :: l₂
⊢ (∃ is'_1 x, is' ++ ts = is'_1 ++ t :: ts) ∨
    is' ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ is' ++ ts = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
subst is'
[GOAL]
case inl.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ l₂ : List α
p' : l₁ ++ t :: l₂ ~ t :: is
⊢ (∃ is' x, l₁ ++ t :: l₂ ++ ts = is' ++ t :: ts) ∨
    l₁ ++ t :: l₂ ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂_1, l₁_1 ++ l₂_1 ∈ permutations is ∧ l₂_1 ≠ [] ∧ l₁ ++ t :: l₂ ++ ts = l₁_1 ++ t :: l₂_1 ++ ts
[PROOFSTEP]
have p := (perm_middle.symm.trans p').cons_inv
[GOAL]
case inl.intro.intro.intro.intro
α : Type uu
β : Type vv
l₁✝ l₂✝ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ l₂ : List α
p' : l₁ ++ t :: l₂ ~ t :: is
p : l₁ ++ l₂ ~ is
⊢ (∃ is' x, l₁ ++ t :: l₂ ++ ts = is' ++ t :: ts) ∨
    l₁ ++ t :: l₂ ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂_1, l₁_1 ++ l₂_1 ∈ permutations is ∧ l₂_1 ≠ [] ∧ l₁ ++ t :: l₂ ++ ts = l₁_1 ++ t :: l₂_1 ++ ts
[PROOFSTEP]
cases' l₂ with a l₂'
[GOAL]
case inl.intro.intro.intro.intro.nil
α : Type uu
β : Type vv
l₁✝ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
p' : l₁ ++ [t] ~ t :: is
p : l₁ ++ [] ~ is
⊢ (∃ is' x, l₁ ++ [t] ++ ts = is' ++ t :: ts) ∨
    l₁ ++ [t] ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂, l₁_1 ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l₁ ++ [t] ++ ts = l₁_1 ++ t :: l₂ ++ ts
[PROOFSTEP]
exact Or.inl ⟨l₁, by simpa using p⟩
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
p' : l₁ ++ [t] ~ t :: is
p : l₁ ++ [] ~ is
⊢ ∃ x, l₁ ++ [t] ++ ts = l₁ ++ t :: ts
[PROOFSTEP]
simpa using p
[GOAL]
case inl.intro.intro.intro.intro.cons
α : Type uu
β : Type vv
l₁✝ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
a : α
l₂' : List α
p' : l₁ ++ t :: a :: l₂' ~ t :: is
p : l₁ ++ a :: l₂' ~ is
⊢ (∃ is' x, l₁ ++ t :: a :: l₂' ++ ts = is' ++ t :: ts) ∨
    l₁ ++ t :: a :: l₂' ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂, l₁_1 ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l₁ ++ t :: a :: l₂' ++ ts = l₁_1 ++ t :: l₂ ++ ts
[PROOFSTEP]
exact Or.inr (Or.inr ⟨l₁, a :: l₂', mem_permutations_of_perm_lemma (IH2 _) p, by simp⟩)
[GOAL]
α : Type uu
β : Type vv
l₁✝ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
a : α
l₂' : List α
p' : l₁ ++ t :: a :: l₂' ~ t :: is
p : l₁ ++ a :: l₂' ~ is
⊢ a :: l₂' ≠ [] ∧ l₁ ++ t :: a :: l₂' ++ ts = l₁ ++ t :: a :: l₂' ++ ts
[PROOFSTEP]
simp
[GOAL]
case inr
α : Type uu
β : Type vv
l₁ l₂ : List α
t : α
ts is : List α
IH1 : ∀ (l : List α), l ~ t :: is ++ ts → (∃ is' x, l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is' x, l = is' ++ is) ∨ l ∈ permutationsAux is []
l : List α
p : l ~ is ++ t :: ts
m : l ∈ permutationsAux ts (t :: is)
⊢ (∃ is' x, l = is' ++ t :: ts) ∨
    l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts
[PROOFSTEP]
exact Or.inr (Or.inl m)
[GOAL]
α✝ : Type uu
β : Type vv
l₁ l₂ : List α✝
α : Type u_1
inst✝ : DecidableEq α
⊢ List.beq = fun a b => decide (a = b)
[PROOFSTEP]
funext l₁ l₂
[GOAL]
case h.h
α✝ : Type uu
β : Type vv
l₁✝ l₂✝ : List α✝
α : Type u_1
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ List.beq l₁ l₂ = decide (l₁ = l₂)
[PROOFSTEP]
show (l₁ == l₂) = _
[GOAL]
case h.h
α✝ : Type uu
β : Type vv
l₁✝ l₂✝ : List α✝
α : Type u_1
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ (l₁ == l₂) = decide (l₁ = l₂)
[PROOFSTEP]
rw [Bool.eq_iff_eq_true_iff, @beq_iff_eq _ (_), decide_eq_true_iff]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b : α
l : List α
⊢ List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
[PROOFSTEP]
induction' l with c l ih
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
a b : α
⊢ List.bind (permutations'Aux a []) (permutations'Aux b) ~ List.bind (permutations'Aux b []) (permutations'Aux a)
[PROOFSTEP]
simp [swap]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ List.bind (permutations'Aux a (c :: l)) (permutations'Aux b) ~
    List.bind (permutations'Aux b (c :: l)) (permutations'Aux a)
[PROOFSTEP]
simp [permutations'Aux]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ (b :: a :: c :: l) ::
      (a :: b :: c :: l) ::
        (map (cons a ∘ cons c) (permutations'Aux b l) ++
          List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b)) ~
    (a :: b :: c :: l) ::
      (b :: a :: c :: l) ::
        (map (cons b ∘ cons c) (permutations'Aux a l) ++
          List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a))
[PROOFSTEP]
apply Perm.swap'
[GOAL]
case cons.p
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a)
[PROOFSTEP]
have :
  ∀ a b,
    (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++ map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) :=
  by
  intros a' b'
  simp only [map_bind, permutations'Aux]
  show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++ map (cons c) (permutations'Aux _ a))) ~ _
  refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
  rw [← map_eq_bind, ← bind_map]
  exact Perm.refl _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
[PROOFSTEP]
intros a' b'
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ List.bind (map (cons c) (permutations'Aux a' l)) (permutations'Aux b') ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))
[PROOFSTEP]
simp only [map_bind, permutations'Aux]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ (List.bind (permutations'Aux a' l) fun a => (b' :: c :: a) :: map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))
[PROOFSTEP]
show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++ map (cons c) (permutations'Aux _ a))) ~ _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ (List.bind (permutations'Aux a' l) fun a => [b' :: c :: a] ++ map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))
[PROOFSTEP]
refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ ((List.bind (permutations'Aux a' l) fun x => [b' :: c :: x]) ++
      List.bind (permutations'Aux a' l) fun a => map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))
[PROOFSTEP]
rw [← map_eq_bind, ← bind_map]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ map (fun x => b' :: c :: x) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) fun a => permutations'Aux b' a) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))
[PROOFSTEP]
exact Perm.refl _
[GOAL]
case cons.p
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a)
[PROOFSTEP]
refine' (((this _ _).append_left _).trans _).trans ((this _ _).append_left _).symm
[GOAL]
case cons.p
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++
      (map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++
      (map (cons a ∘ cons c) (permutations'Aux b l) ++
        map (cons c) (List.bind (permutations'Aux b l) (permutations'Aux a)))
[PROOFSTEP]
rw [← append_assoc, ← append_assoc]
[GOAL]
case cons.p
α : Type uu
β : Type vv
l₁ l₂ : List α
a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ map (cons b ∘ cons c) (permutations'Aux a l) ++
      map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b)) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ map (cons a ∘ cons c) (permutations'Aux b l) ++
      map (cons c) (List.bind (permutations'Aux b l) (permutations'Aux a))
[PROOFSTEP]
exact perm_append_comm.append (ih.map _)
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s t : List α
p : s ~ t
⊢ List.permutations' s ~ List.permutations' t
[PROOFSTEP]
induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ s t : List α
⊢ List.permutations' [] ~ List.permutations' []
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ t✝ : List α
a : α
s t : List α
a✝ : s ~ t
IH : List.permutations' s ~ List.permutations' t
⊢ List.permutations' (a :: s) ~ List.permutations' (a :: t)
[PROOFSTEP]
exact IH.bind_right _
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ s t : List α
a b : α
l : List α
⊢ List.permutations' (b :: a :: l) ~ List.permutations' (a :: b :: l)
[PROOFSTEP]
dsimp [permutations']
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ s t : List α
a b : α
l : List α
⊢ List.bind (List.bind (List.permutations' l) (permutations'Aux a)) (permutations'Aux b) ~
    List.bind (List.bind (List.permutations' l) (permutations'Aux b)) (permutations'Aux a)
[PROOFSTEP]
rw [bind_assoc, bind_assoc]
[GOAL]
case swap
α : Type uu
β : Type vv
l₁ l₂ s t : List α
a b : α
l : List α
⊢ (List.bind (List.permutations' l) fun x => List.bind (permutations'Aux a x) (permutations'Aux b)) ~
    List.bind (List.permutations' l) fun x => List.bind (permutations'Aux b x) (permutations'Aux a)
[PROOFSTEP]
apply Perm.bind_left
[GOAL]
case swap.h
α : Type uu
β : Type vv
l₁ l₂ s t : List α
a b : α
l : List α
⊢ ∀ (a_1 : List α),
    a_1 ∈ List.permutations' l →
      List.bind (permutations'Aux a a_1) (permutations'Aux b) ~ List.bind (permutations'Aux b a_1) (permutations'Aux a)
[PROOFSTEP]
intro l' _
[GOAL]
case swap.h
α : Type uu
β : Type vv
l₁ l₂ s t : List α
a b : α
l l' : List α
a✝ : l' ∈ List.permutations' l
⊢ List.bind (permutations'Aux a l') (permutations'Aux b) ~ List.bind (permutations'Aux b l') (permutations'Aux a)
[PROOFSTEP]
apply perm_permutations'Aux_comm
[GOAL]
case trans
α : Type uu
β : Type vv
l₁ l₂ s✝ t✝ s t u : List α
a✝¹ : s ~ t
a✝ : t ~ u
IH₁ : List.permutations' s ~ List.permutations' t
IH₂ : List.permutations' t ~ List.permutations' u
⊢ List.permutations' s ~ List.permutations' u
[PROOFSTEP]
exact IH₁.trans IH₂
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ ts : List α
⊢ permutations ts ~ permutations' ts
[PROOFSTEP]
obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
[GOAL]
case intro
α : Type uu
β : Type vv
l₁ l₂ ts : List α
n : ℕ
h : length ts < n
⊢ permutations ts ~ permutations' ts
[PROOFSTEP]
induction' n with n IH generalizing ts
[GOAL]
case intro.zero
α : Type uu
β : Type vv
l₁ l₂ ts✝ : List α
n : ℕ
h✝ : length ts✝ < n
ts : List α
h : length ts < zero
⊢ permutations ts ~ permutations' ts
[PROOFSTEP]
cases h
[GOAL]
case intro.succ
α : Type uu
β : Type vv
l₁ l₂ ts✝ : List α
n✝ : ℕ
h✝ : length ts✝ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts : List α
h : length ts < succ n
⊢ permutations ts ~ permutations' ts
[PROOFSTEP]
refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h
[GOAL]
case intro.succ.refine'_1
α : Type uu
β : Type vv
l₁ l₂ ts✝ : List α
n✝ : ℕ
h✝ : length ts✝ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts : List α
h : length ts < succ n
x✝ : length [] < succ n
⊢ permutations [] ~ permutations' []
[PROOFSTEP]
simp [permutations]
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length (ts ++ [t]) < succ n
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])
[PROOFSTEP]
rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h 
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])
[PROOFSTEP]
have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
⊢ length (reverse ts) < n
[PROOFSTEP]
rwa [length_reverse]
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])
[PROOFSTEP]
simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil, permutationsAux_cons, append_nil]
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (map (fun x => x ++ [t]) (permutations ts) ++
      List.bind (permutations (reverse ts)) fun y => (permutationsAux2 t [] [] y id).snd) ~
    permutations' (ts ++ [t])
[PROOFSTEP]
refine'
  (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
    (Perm.trans _ perm_append_comm.permutations')
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun y => (permutationsAux2 t [] [] y id).snd) ++
      map (fun x => x ++ [t]) (permutations' ts) ~
    permutations' ([t] ++ ts)
[PROOFSTEP]
rw [map_eq_bind, singleton_append, permutations']
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ ((List.bind (permutations' ts) fun y => (permutationsAux2 t [] [] y id).snd) ++
      List.bind (permutations' ts) fun x => [x ++ [t]]) ~
    List.bind (permutations' ts) (permutations'Aux t)
[PROOFSTEP]
refine' (bind_append_perm _ _ _).trans _
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun x => (permutationsAux2 t [] [] x id).snd ++ [x ++ [t]]) ~
    List.bind (permutations' ts) (permutations'Aux t)
[PROOFSTEP]
refine' Perm.of_eq _
[GOAL]
case intro.succ.refine'_2
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun x => (permutationsAux2 t [] [] x id).snd ++ [x ++ [t]]) =
    List.bind (permutations' ts) (permutations'Aux t)
[PROOFSTEP]
congr
[GOAL]
case intro.succ.refine'_2.e_b
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (fun x => (permutationsAux2 t [] [] x id).snd ++ [x ++ [t]]) = permutations'Aux t
[PROOFSTEP]
funext _
[GOAL]
case intro.succ.refine'_2.e_b.h
α : Type uu
β : Type vv
l₁ l₂ ts✝¹ : List α
n✝ : ℕ
h✝¹ : length ts✝¹ < n✝
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝¹ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
x✝ : List α
⊢ (permutationsAux2 t [] [] x✝ id).snd ++ [x✝ ++ [t]] = permutations'Aux t x✝
[PROOFSTEP]
rw [permutations'Aux_eq_permutationsAux2, permutationsAux2_append]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
n : ℕ
hn : n < length (permutations'Aux x s)
⊢ nthLe (permutations'Aux x s) n hn = insertNth n x s
[PROOFSTEP]
induction' s with y s IH generalizing n
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
n✝ : ℕ
hn✝ : n✝ < length (permutations'Aux x s)
n : ℕ
hn : n < length (permutations'Aux x [])
⊢ nthLe (permutations'Aux x []) n hn = insertNth n x []
[PROOFSTEP]
simp only [length, zero_add, lt_one_iff] at hn 
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
n✝ : ℕ
hn✝¹ : n✝ < length (permutations'Aux x s)
n : ℕ
hn✝ : n < length (permutations'Aux x [])
hn : n = 0
⊢ nthLe (permutations'Aux x []) n hn✝ = insertNth n x []
[PROOFSTEP]
simp [hn]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
n✝ : ℕ
hn✝ : n✝ < length (permutations'Aux x s✝)
y : α
s : List α
IH : ∀ (n : ℕ) (hn : n < length (permutations'Aux x s)), nthLe (permutations'Aux x s) n hn = insertNth n x s
n : ℕ
hn : n < length (permutations'Aux x (y :: s))
⊢ nthLe (permutations'Aux x (y :: s)) n hn = insertNth n x (y :: s)
[PROOFSTEP]
cases n
[GOAL]
case cons.zero
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
n : ℕ
hn✝ : n < length (permutations'Aux x s✝)
y : α
s : List α
IH : ∀ (n : ℕ) (hn : n < length (permutations'Aux x s)), nthLe (permutations'Aux x s) n hn = insertNth n x s
hn : zero < length (permutations'Aux x (y :: s))
⊢ nthLe (permutations'Aux x (y :: s)) zero hn = insertNth zero x (y :: s)
[PROOFSTEP]
simp [nthLe]
[GOAL]
case cons.succ
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
n : ℕ
hn✝ : n < length (permutations'Aux x s✝)
y : α
s : List α
IH : ∀ (n : ℕ) (hn : n < length (permutations'Aux x s)), nthLe (permutations'Aux x s) n hn = insertNth n x s
n✝ : ℕ
hn : succ n✝ < length (permutations'Aux x (y :: s))
⊢ nthLe (permutations'Aux x (y :: s)) (succ n✝) hn = insertNth (succ n✝) x (y :: s)
[PROOFSTEP]
simpa [nthLe] using IH _ _
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
l : List α
x : α
⊢ count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
[PROOFSTEP]
induction' l with y l IH generalizing x
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ x : α
⊢ count [x] (permutations'Aux x []) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) []) + 1
[PROOFSTEP]
simp [takeWhile, count]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ y : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
⊢ count (x :: y :: l) (permutations'Aux x (y :: l)) =
    length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) (y :: l)) + 1
[PROOFSTEP]
rw [permutations'Aux, DecEq_eq, count_cons_self]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ y : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
⊢ count (x :: y :: l) (map (cons y) (permutations'Aux x l)) + 1 =
    length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) (y :: l)) + 1
[PROOFSTEP]
by_cases hx : x = y
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ y : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
hx : x = y
⊢ count (x :: y :: l) (map (cons y) (permutations'Aux x l)) + 1 =
    length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) (y :: l)) + 1
[PROOFSTEP]
subst hx
[GOAL]
case pos
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
⊢ count (x :: x :: l) (map (cons x) (permutations'Aux x l)) + 1 =
    length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) (x :: l)) + 1
[PROOFSTEP]
simpa [takeWhile, Nat.succ_inj', DecEq_eq] using IH _
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ y : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
hx : ¬x = y
⊢ count (x :: y :: l) (map (cons y) (permutations'Aux x l)) + 1 =
    length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) (y :: l)) + 1
[PROOFSTEP]
rw [takeWhile]
[GOAL]
case neg
α : Type uu
β : Type vv
l₁ l₂ : List α
inst✝ : DecidableEq α
x✝ y : α
l : List α
IH :
  ∀ (x : α),
    count (x :: l) (permutations'Aux x l) = length (takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l) + 1
x : α
hx : ¬x = y
⊢ count (x :: y :: l) (map (cons y) (permutations'Aux x l)) + 1 =
    length
        (match decide ((fun x x_1 => x = x_1) x y) with
        | true => y :: takeWhile (fun b => decide ((fun x x_1 => x = x_1) x b)) l
        | false => []) +
      1
[PROOFSTEP]
simp only [mem_map, cons.injEq, Ne.symm hx, false_and, and_false, exists_false, not_false_iff, count_eq_zero_of_not_mem,
  zero_add, hx, decide_False, length_nil]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
⊢ length (permutations'Aux x s) = length s + 1
[PROOFSTEP]
induction' s with y s IH
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
⊢ length (permutations'Aux x []) = length [] + 1
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ : List α
x y : α
s : List α
IH : length (permutations'Aux x s) = length s + 1
⊢ length (permutations'Aux x (y :: s)) = length (y :: s) + 1
[PROOFSTEP]
simpa using IH
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
⊢ 0 < length (permutations'Aux x s)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
⊢ Function.Injective (permutations'Aux x)
[PROOFSTEP]
intro s t h
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
⊢ s = t
[PROOFSTEP]
apply insertNth_injective s.length x
[GOAL]
case a
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
⊢ insertNth (length s) x s = insertNth (length s) x t
[PROOFSTEP]
have hl : s.length = t.length := by simpa using congr_arg length h
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
⊢ length s = length t
[PROOFSTEP]
simpa using congr_arg length h
[GOAL]
case a
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
hl : length s = length t
⊢ insertNth (length s) x s = insertNth (length s) x t
[PROOFSTEP]
rw [← nthLe_permutations'Aux s x s.length (by simp), ← nthLe_permutations'Aux t x s.length (by simp [hl])]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
hl : length s = length t
⊢ length s < length (permutations'Aux x s)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
hl : length s = length t
⊢ length s < length (permutations'Aux x t)
[PROOFSTEP]
simp [hl]
[GOAL]
case a
α : Type uu
β : Type vv
l₁ l₂ : List α
x : α
s t : List α
h : permutations'Aux x s = permutations'Aux x t
hl : length s = length t
⊢ nthLe (permutations'Aux x s) (length s) (_ : length s < length (permutations'Aux x s)) =
    nthLe (permutations'Aux x t) (length s) (_ : length s < length (permutations'Aux x t))
[PROOFSTEP]
simp [h, hl]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
hx : ¬x ∈ s
⊢ Nodup (permutations'Aux x s)
[PROOFSTEP]
induction' s with y s IH
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
hx✝ : ¬x ∈ s
hx : ¬x ∈ []
⊢ Nodup (permutations'Aux x [])
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x ∈ y :: s
⊢ Nodup (permutations'Aux x (y :: s))
[PROOFSTEP]
simp only [not_or, mem_cons] at hx 
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x = y ∧ ¬x ∈ s
⊢ Nodup (permutations'Aux x (y :: s))
[PROOFSTEP]
simp only [permutations'Aux, nodup_cons, mem_map, cons.injEq, exists_eq_right_right, not_and]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x = y ∧ ¬x ∈ s
⊢ (y :: s ∈ permutations'Aux x s → ¬y = x) ∧ Nodup (map (cons y) (permutations'Aux x s))
[PROOFSTEP]
refine' ⟨fun _ => Ne.symm hx.left, _⟩
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x = y ∧ ¬x ∈ s
⊢ Nodup (map (cons y) (permutations'Aux x s))
[PROOFSTEP]
rw [nodup_map_iff]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x = y ∧ ¬x ∈ s
⊢ Nodup (permutations'Aux x s)
[PROOFSTEP]
exact IH hx.right
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s✝ : List α
x : α
hx✝ : ¬x ∈ s✝
y : α
s : List α
IH : ¬x ∈ s → Nodup (permutations'Aux x s)
hx : ¬x = y ∧ ¬x ∈ s
⊢ Function.Injective (cons y)
[PROOFSTEP]
simp
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
⊢ Nodup (permutations'Aux x s) ↔ ¬x ∈ s
[PROOFSTEP]
refine' ⟨fun h => _, nodup_permutations'Aux_of_not_mem _ _⟩
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h : Nodup (permutations'Aux x s)
⊢ ¬x ∈ s
[PROOFSTEP]
intro H
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h : Nodup (permutations'Aux x s)
H : x ∈ s
⊢ False
[PROOFSTEP]
obtain ⟨k, hk, hk'⟩ := nthLe_of_mem H
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h : Nodup (permutations'Aux x s)
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ False
[PROOFSTEP]
rw [nodup_iff_nthLe_inj] at h 
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ False
[PROOFSTEP]
suffices k = k + 1 by simp at this 
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
this : k = k + 1
⊢ False
[PROOFSTEP]
simp at this 
[GOAL]
case intro.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ k = k + 1
[PROOFSTEP]
refine' h k (k + 1) _ _ _
[GOAL]
case intro.intro.refine'_1
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ k < length (permutations'Aux x s)
[PROOFSTEP]
simpa [Nat.lt_succ_iff] using hk.le
[GOAL]
case intro.intro.refine'_2
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ k + 1 < length (permutations'Aux x s)
[PROOFSTEP]
simpa using hk
[GOAL]
case intro.intro.refine'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ nthLe (permutations'Aux x s) k (_ : k < length (permutations'Aux x s)) =
    nthLe (permutations'Aux x s) (k + 1) (_ : k + 1 < length (permutations'Aux x s))
[PROOFSTEP]
rw [nthLe_permutations'Aux, nthLe_permutations'Aux]
[GOAL]
case intro.intro.refine'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ insertNth k x s = insertNth (k + 1) x s
[PROOFSTEP]
have hl : length (insertNth k x s) = length (insertNth (k + 1) x s) := by
  rw [length_insertNth _ _ hk.le, length_insertNth _ _ (Nat.succ_le_of_lt hk)]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
⊢ length (insertNth k x s) = length (insertNth (k + 1) x s)
[PROOFSTEP]
rw [length_insertNth _ _ hk.le, length_insertNth _ _ (Nat.succ_le_of_lt hk)]
[GOAL]
case intro.intro.refine'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
⊢ insertNth k x s = insertNth (k + 1) x s
[PROOFSTEP]
refine' ext_nthLe hl fun n hn hn' => _
[GOAL]
case intro.intro.refine'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
n : ℕ
hn : n < length (insertNth k x s)
hn' : n < length (insertNth (k + 1) x s)
⊢ nthLe (insertNth k x s) n hn = nthLe (insertNth (k + 1) x s) n hn'
[PROOFSTEP]
rcases lt_trichotomy n k with (H | rfl | H)
[GOAL]
case intro.intro.refine'_3.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
n : ℕ
hn : n < length (insertNth k x s)
hn' : n < length (insertNth (k + 1) x s)
H : n < k
⊢ nthLe (insertNth k x s) n hn = nthLe (insertNth (k + 1) x s) n hn'
[PROOFSTEP]
rw [nthLe_insertNth_of_lt _ _ _ _ H (H.trans hk), nthLe_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))]
[GOAL]
case intro.intro.refine'_3.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H : x ∈ s
n : ℕ
hk : n < length s
hk' : nthLe s n hk = x
hl : length (insertNth n x s) = length (insertNth (n + 1) x s)
hn : n < length (insertNth n x s)
hn' : n < length (insertNth (n + 1) x s)
⊢ nthLe (insertNth n x s) n hn = nthLe (insertNth (n + 1) x s) n hn'
[PROOFSTEP]
rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk, hk']
[GOAL]
case intro.intro.refine'_3.inr.inr
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
n : ℕ
hn : n < length (insertNth k x s)
hn' : n < length (insertNth (k + 1) x s)
H : k < n
⊢ nthLe (insertNth k x s) n hn = nthLe (insertNth (k + 1) x s) n hn'
[PROOFSTEP]
rcases(Nat.succ_le_of_lt H).eq_or_lt with (rfl | H')
[GOAL]
case intro.intro.refine'_3.inr.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
hn : succ k < length (insertNth k x s)
hn' : succ k < length (insertNth (k + 1) x s)
H : k < succ k
⊢ nthLe (insertNth k x s) (succ k) hn = nthLe (insertNth (k + 1) x s) (succ k) hn'
[PROOFSTEP]
rw [nthLe_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)]
[GOAL]
case intro.intro.refine'_3.inr.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
hn : succ k < length (insertNth k x s)
hn' : succ k < length (insertNth (k + 1) x s)
H : k < succ k
⊢ nthLe (insertNth k x s) (succ k) hn = x
[PROOFSTEP]
convert hk' using 1
[GOAL]
case h.e'_2
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
hn : succ k < length (insertNth k x s)
hn' : succ k < length (insertNth (k + 1) x s)
H : k < succ k
⊢ nthLe (insertNth k x s) (succ k) hn = nthLe s k hk
[PROOFSTEP]
exact nthLe_insertNth_add_succ _ _ _ 0 _
[GOAL]
case intro.intro.refine'_3.inr.inr.inr
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
n : ℕ
hn : n < length (insertNth k x s)
hn' : n < length (insertNth (k + 1) x s)
H : k < n
H' : succ k < n
⊢ nthLe (insertNth k x s) n hn = nthLe (insertNth (k + 1) x s) n hn'
[PROOFSTEP]
obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H'
[GOAL]
case intro.intro.refine'_3.inr.inr.inr.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn : succ k + m + 1 < length (insertNth k x s)
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ nthLe (insertNth k x s) (succ k + m + 1) hn = nthLe (insertNth (k + 1) x s) (succ k + m + 1) hn'
[PROOFSTEP]
erw [length_insertNth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn 
[GOAL]
case intro.intro.refine'_3.inr.inr.inr.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ nthLe (insertNth k x s) (succ k + m + 1) hn✝ = nthLe (insertNth (k + 1) x s) (succ k + m + 1) hn'
[PROOFSTEP]
rw [nthLe_insertNth_add_succ]
[GOAL]
case intro.intro.refine'_3.inr.inr.inr.intro
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ nthLe (insertNth k x s) (succ k + m + 1) hn✝ = nthLe s (k + 1 + m) ?intro.intro.refine'_3.inr.inr.inr.intro.hk'
case intro.intro.refine'_3.inr.inr.inr.intro.hk'
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ k + 1 + m < length s
[PROOFSTEP]
convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ k + succ m < length s
[PROOFSTEP]
simpa using hn
[GOAL]
case h.e'_2.h.e'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ succ k + m + 1 = k + succ m + 1
[PROOFSTEP]
simp [Nat.add_succ, Nat.succ_add]
[GOAL]
case h.e'_3.h.e'_3
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ k + 1 + m = k + succ m
[PROOFSTEP]
simp [add_left_comm, add_comm]
[GOAL]
case intro.intro.refine'_3.inr.inr.inr.intro.hk'
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
h :
  ∀ (i j : ℕ) (h₁ : i < length (permutations'Aux x s)) (h₂ : j < length (permutations'Aux x s)),
    nthLe (permutations'Aux x s) i h₁ = nthLe (permutations'Aux x s) j h₂ → i = j
H✝ : x ∈ s
k : ℕ
hk : k < length s
hk' : nthLe s k hk = x
hl : length (insertNth k x s) = length (insertNth (k + 1) x s)
m : ℕ
hn✝ : succ k + m + 1 < length (insertNth k x s)
hn : succ (k + m) < length s
hn' : succ k + m + 1 < length (insertNth (k + 1) x s)
H : k < succ k + m + 1
H' : succ k < succ k + m + 1
⊢ k + 1 + m < length s
[PROOFSTEP]
simpa [Nat.succ_add] using hn
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
hs : Nodup s
⊢ Nodup (permutations s)
[PROOFSTEP]
rw [(permutations_perm_permutations' s).nodup_iff]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
hs : Nodup s
⊢ Nodup (permutations' s)
[PROOFSTEP]
induction' hs with x l h h' IH
[GOAL]
case nil
α : Type uu
β : Type vv
l₁ l₂ s : List α
⊢ Nodup (permutations' [])
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
⊢ Nodup (permutations' (x :: l))
[PROOFSTEP]
rw [permutations']
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
⊢ Nodup (List.bind (permutations' l) (permutations'Aux x))
[PROOFSTEP]
rw [nodup_bind]
[GOAL]
case cons
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
⊢ (∀ (x_1 : List α), x_1 ∈ permutations' l → Nodup (permutations'Aux x x_1)) ∧
    Pairwise (fun a b => Disjoint (permutations'Aux x a) (permutations'Aux x b)) (permutations' l)
[PROOFSTEP]
constructor
[GOAL]
case cons.left
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
⊢ ∀ (x_1 : List α), x_1 ∈ permutations' l → Nodup (permutations'Aux x x_1)
[PROOFSTEP]
intro ys hy
[GOAL]
case cons.left
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
ys : List α
hy : ys ∈ permutations' l
⊢ Nodup (permutations'Aux x ys)
[PROOFSTEP]
rw [mem_permutations'] at hy 
[GOAL]
case cons.left
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
ys : List α
hy : ys ~ l
⊢ Nodup (permutations'Aux x ys)
[PROOFSTEP]
rw [nodup_permutations'Aux_iff, hy.mem_iff]
[GOAL]
case cons.left
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
ys : List α
hy : ys ~ l
⊢ ¬x ∈ l
[PROOFSTEP]
exact fun H => h x H rfl
[GOAL]
case cons.right
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
⊢ Pairwise (fun a b => Disjoint (permutations'Aux x a) (permutations'Aux x b)) (permutations' l)
[PROOFSTEP]
refine' IH.pairwise_of_forall_ne fun as ha bs hb H => _
[GOAL]
case cons.right
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ∈ permutations' l
bs : List α
hb : bs ∈ permutations' l
H : as ≠ bs
⊢ Disjoint (permutations'Aux x as) (permutations'Aux x bs)
[PROOFSTEP]
rw [disjoint_iff_ne]
[GOAL]
case cons.right
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ∈ permutations' l
bs : List α
hb : bs ∈ permutations' l
H : as ≠ bs
⊢ ∀ (a : List α), a ∈ permutations'Aux x as → ∀ (b : List α), b ∈ permutations'Aux x bs → a ≠ b
[PROOFSTEP]
rintro a ha' b hb' rfl
[GOAL]
case cons.right
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ∈ permutations' l
bs : List α
hb : bs ∈ permutations' l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
⊢ False
[PROOFSTEP]
obtain ⟨⟨n, hn⟩, hn'⟩ := get_of_mem ha'
[GOAL]
case cons.right.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ∈ permutations' l
bs : List α
hb : bs ∈ permutations' l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn : n < length (permutations'Aux x as)
hn' : get (permutations'Aux x as) { val := n, isLt := hn } = a
⊢ False
[PROOFSTEP]
obtain ⟨⟨m, hm⟩, hm'⟩ := get_of_mem hb'
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ∈ permutations' l
bs : List α
hb : bs ∈ permutations' l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn : n < length (permutations'Aux x as)
hn' : get (permutations'Aux x as) { val := n, isLt := hn } = a
m : ℕ
hm : m < length (permutations'Aux x bs)
hm' : get (permutations'Aux x bs) { val := m, isLt := hm } = a
⊢ False
[PROOFSTEP]
rw [mem_permutations'] at ha hb 
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn : n < length (permutations'Aux x as)
hn' : get (permutations'Aux x as) { val := n, isLt := hn } = a
m : ℕ
hm : m < length (permutations'Aux x bs)
hm' : get (permutations'Aux x bs) { val := m, isLt := hm } = a
⊢ False
[PROOFSTEP]
have hl : as.length = bs.length := (ha.trans hb.symm).length_eq
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn : n < length (permutations'Aux x as)
hn' : get (permutations'Aux x as) { val := n, isLt := hn } = a
m : ℕ
hm : m < length (permutations'Aux x bs)
hm' : get (permutations'Aux x bs) { val := m, isLt := hm } = a
hl : length as = length bs
⊢ False
[PROOFSTEP]
simp only [Nat.lt_succ_iff, length_permutations'Aux] at hn hm 
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : get (permutations'Aux x as) { val := n, isLt := hn✝ } = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : get (permutations'Aux x bs) { val := m, isLt := hm✝ } = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
⊢ False
[PROOFSTEP]
rw [← nthLe, nthLe_permutations'Aux] at hn' hm' 
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
⊢ False
[PROOFSTEP]
have hx : nthLe (insertNth n x as) m (by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff, hl]) = x := by
  simp [hn', ← hm', hm]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
⊢ m < length (insertNth n x as)
[PROOFSTEP]
rwa [length_insertNth _ _ hn, Nat.lt_succ_iff, hl]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
⊢ nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
[PROOFSTEP]
simp [hn', ← hm', hm]
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
⊢ False
[PROOFSTEP]
have hx' : nthLe (insertNth m x bs) n (by rwa [length_insertNth _ _ hm, Nat.lt_succ_iff, ← hl]) = x := by
  simp [hm', ← hn', hn]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
⊢ n < length (insertNth m x bs)
[PROOFSTEP]
rwa [length_insertNth _ _ hm, Nat.lt_succ_iff, ← hl]
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
⊢ nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
[PROOFSTEP]
simp [hm', ← hn', hn]
[GOAL]
case cons.right.intro.mk.intro.mk
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
⊢ False
[PROOFSTEP]
rcases lt_trichotomy n m with (ht | ht | ht)
[GOAL]
case cons.right.intro.mk.intro.mk.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n < m
⊢ False
[PROOFSTEP]
suffices x ∈ bs by exact h x (hb.subset this) rfl
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n < m
this : x ∈ bs
⊢ False
[PROOFSTEP]
exact h x (hb.subset this) rfl
[GOAL]
case cons.right.intro.mk.intro.mk.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n < m
⊢ x ∈ bs
[PROOFSTEP]
rw [← hx', nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hm)]
[GOAL]
case cons.right.intro.mk.intro.mk.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n < m
⊢ nthLe bs n (_ : n < length bs) ∈ bs
[PROOFSTEP]
exact nthLe_mem _ _ _
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n = m
⊢ False
[PROOFSTEP]
simp only [ht] at hm' hn' 
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n = m
hn' : insertNth m x as = a
⊢ False
[PROOFSTEP]
rw [← hm'] at hn' 
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inl
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : n = m
hn' : insertNth m x as = insertNth m x bs
⊢ False
[PROOFSTEP]
exact H (insertNth_injective _ _ hn')
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inr
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : m < n
⊢ False
[PROOFSTEP]
suffices x ∈ as by exact h x (ha.subset this) rfl
[GOAL]
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : m < n
this : x ∈ as
⊢ False
[PROOFSTEP]
exact h x (ha.subset this) rfl
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inr
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : m < n
⊢ x ∈ as
[PROOFSTEP]
rw [← hx, nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hn)]
[GOAL]
case cons.right.intro.mk.intro.mk.inr.inr
α : Type uu
β : Type vv
l₁ l₂ s : List α
x : α
l : List α
h : ∀ (a' : α), a' ∈ l → x ≠ a'
h' : Pairwise (fun x x_1 => x ≠ x_1) l
IH : Nodup (permutations' l)
as : List α
ha : as ~ l
bs : List α
hb : bs ~ l
H : as ≠ bs
a : List α
ha' : a ∈ permutations'Aux x as
hb' : a ∈ permutations'Aux x bs
n : ℕ
hn✝ : n < length (permutations'Aux x as)
hn' : insertNth n x as = a
m : ℕ
hm✝ : m < length (permutations'Aux x bs)
hm' : insertNth m x bs = a
hl : length as = length bs
hn : n ≤ length as
hm : m ≤ length bs
hx : nthLe (insertNth n x as) m (_ : m < length (insertNth n x as)) = x
hx' : nthLe (insertNth m x bs) n (_ : n < length (insertNth m x bs)) = x
ht : m < n
⊢ nthLe as m (_ : m < length as) ∈ as
[PROOFSTEP]
exact nthLe_mem _ _ _
