Theorem: List.Nodup.sym2
File: Mathlib/Data/List/Sym.lean

tactic: induction xs with
| nil => simp only [List.sym2, nodup_nil]
| cons x xs ih =>
  rw [List.sym2]
  specialize ih h.of_cons
  rw [nodup_cons] at h
  refine Nodup.append (Nodup.cons ?notmem (h.2.map ?inj)) ih ?disj
  case disj =>
    intro z hz hz'
    simp only [mem_cons, mem_map] at hz
    obtain ⟨_, (rfl | _), rfl⟩ := hz
      <;> simp [left_mem_of_mk_mem_sym2 hz'] at h
  case notmem =>
    intro h'
    simp only [h.1, mem_map, Sym2.eq_iff, true_and, or_self, exists_eq_right] at h'
  case inj =>
    intro a b
    simp only [Sym2.eq_iff, true_and]
    rintro (rfl | ⟨rfl, rfl⟩) <;> rfl
state_before: α : Type u_1
xs : List α
h : xs.Nodup
⊢ xs.sym2.Nodup
state_after: no goals

tactic: simp only [List.sym2, nodup_nil]
state_before: case nil
α : Type u_1
h : [].Nodup
⊢ [].sym2.Nodup
state_after: no goals

tactic: rw [List.sym2]
state_before: case cons
α : Type u_1
x : α
xs : List α
ih : xs.Nodup → xs.sym2.Nodup
h : (x :: xs).Nodup
⊢ (x :: xs).sym2.Nodup
state_after: case cons
α : Type u_1
x : α
xs : List α
ih : xs.Nodup → xs.sym2.Nodup
h : (x :: xs).Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup

tactic: specialize ih h.of_cons
state_before: case cons
α : Type u_1
x : α
xs : List α
ih : xs.Nodup → xs.sym2.Nodup
h : (x :: xs).Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup
state_after: case cons
α : Type u_1
x : α
xs : List α
h : (x :: xs).Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup

tactic: rw [nodup_cons] at h
state_before: case cons
α : Type u_1
x : α
xs : List α
h : (x :: xs).Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup
state_after: case cons
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup

tactic: refine Nodup.append (Nodup.cons ?notmem (h.2.map ?inj)) ih ?disj
state_before: case cons
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs) ++ xs.sym2).Nodup
state_after: case notmem
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (fun y => s(x, y)) x ∉ map (fun y => s(x, y)) xs

case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)

case disj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs)).Disjoint xs.sym2

tactic: case disj =>
  intro z hz hz'
  simp only [mem_cons, mem_map] at hz
  obtain ⟨_, (rfl | _), rfl⟩ := hz
    <;> simp [left_mem_of_mk_mem_sym2 hz'] at h
state_before: case notmem
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (fun y => s(x, y)) x ∉ map (fun y => s(x, y)) xs

case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)

case disj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs)).Disjoint xs.sym2
state_after: case notmem
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (fun y => s(x, y)) x ∉ map (fun y => s(x, y)) xs

case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)

tactic: case notmem =>
  intro h'
  simp only [h.1, mem_map, Sym2.eq_iff, true_and, or_self, exists_eq_right] at h'
state_before: case notmem
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (fun y => s(x, y)) x ∉ map (fun y => s(x, y)) xs

case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)
state_after: case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)

tactic: case inj =>
  intro a b
  simp only [Sym2.eq_iff, true_and]
  rintro (rfl | ⟨rfl, rfl⟩) <;> rfl
state_before: case inj
α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)
state_after: no goals

tactic: intro z hz hz'
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (map (fun y => s(x, y)) (x :: xs)).Disjoint xs.sym2
state_after: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
z : Sym2 α
hz : z ∈ map (fun y => s(x, y)) (x :: xs)
hz' : z ∈ xs.sym2
⊢ False

tactic: simp only [mem_cons, mem_map] at hz
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
z : Sym2 α
hz : z ∈ map (fun y => s(x, y)) (x :: xs)
hz' : z ∈ xs.sym2
⊢ False
state_after: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
z : Sym2 α
hz' : z ∈ xs.sym2
hz : ∃ a, (a = x ∨ a ∈ xs) ∧ s(x, a) = z
⊢ False

tactic: obtain ⟨_, (rfl | _), rfl⟩ := hz
  <;> simp [left_mem_of_mk_mem_sym2 hz'] at h
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
z : Sym2 α
hz' : z ∈ xs.sym2
hz : ∃ a, (a = x ∨ a ∈ xs) ∧ s(x, a) = z
⊢ False
state_after: no goals

tactic: intro h'
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ (fun y => s(x, y)) x ∉ map (fun y => s(x, y)) xs
state_after: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
h' : (fun y => s(x, y)) x ∈ map (fun y => s(x, y)) xs
⊢ False

tactic: simp only [h.1, mem_map, Sym2.eq_iff, true_and, or_self, exists_eq_right] at h'
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
h' : (fun y => s(x, y)) x ∈ map (fun y => s(x, y)) xs
⊢ False
state_after: no goals

tactic: intro a b
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
⊢ Function.Injective fun y => s(x, y)
state_after: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
a b : α
⊢ (fun y => s(x, y)) a = (fun y => s(x, y)) b → a = b

tactic: simp only [Sym2.eq_iff, true_and]
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
a b : α
⊢ (fun y => s(x, y)) a = (fun y => s(x, y)) b → a = b
state_after: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
a b : α
⊢ a = b ∨ x = b ∧ a = x → a = b

tactic: rintro (rfl | ⟨rfl, rfl⟩) <;> rfl
state_before: α : Type u_1
x : α
xs : List α
h : x ∉ xs ∧ xs.Nodup
ih : xs.sym2.Nodup
a b : α
⊢ a = b ∨ x = b ∧ a = x → a = b
state_after: no goals