Module docstring
{"# List duplicates
Main definitions
List.Duplicate x l : Propis an inductive property that holds whenxis a duplicate inl
Implementation details
In this file, x ∈+ l notation is shorthand for List.Duplicate x l.
"}
{"# List duplicates
List.Duplicate x l : Prop is an inductive property that holds when x is a duplicate in lIn this file, x ∈+ l notation is shorthand for List.Duplicate x l.
"}
List.Duplicate
inductive
(x : α) : List α → Prop
List.Mem.duplicate_cons_self
theorem
(h : x ∈ l) : x ∈+ x :: l
theorem Mem.duplicate_cons_self (h : x ∈ l) : x ∈+ x :: l :=
Duplicate.cons_mem h
List.Duplicate.duplicate_cons
theorem
(h : x ∈+ l) (y : α) : x ∈+ y :: l
theorem Duplicate.duplicate_cons (h : x ∈+ l) (y : α) : x ∈+ y :: l :=
Duplicate.cons_duplicate h
List.Duplicate.mem
theorem
(h : x ∈+ l) : x ∈ l
theorem Duplicate.mem (h : x ∈+ l) : x ∈ l := by
induction h with
| cons_mem => exact mem_cons_self
| cons_duplicate _ hm => exact mem_cons_of_mem _ hm
List.Duplicate.mem_cons_self
theorem
(h : x ∈+ x :: l) : x ∈ l
theorem Duplicate.mem_cons_self (h : x ∈+ x :: l) : x ∈ l := by
obtain h | h := h
· exact h
· exact h.mem
List.duplicate_cons_self_iff
theorem
: x ∈+ x :: l ↔ x ∈ l
@[simp]
theorem duplicate_cons_self_iff : x ∈+ x :: lx ∈+ x :: l ↔ x ∈ l :=
⟨Duplicate.mem_cons_self, Mem.duplicate_cons_self⟩
List.Duplicate.ne_nil
theorem
(h : x ∈+ l) : l ≠ []
theorem Duplicate.ne_nil (h : x ∈+ l) : l ≠ [] := fun H => (mem_nil_iff x).mp (H ▸ h.mem)
List.not_duplicate_nil
theorem
(x : α) : ¬x ∈+ []
@[simp]
theorem not_duplicate_nil (x : α) : ¬x ∈+ [] := fun H => H.ne_nil rfl
List.Duplicate.ne_singleton
theorem
(h : x ∈+ l) (y : α) : l ≠ [y]
theorem Duplicate.ne_singleton (h : x ∈+ l) (y : α) : l ≠ [y] := by
induction h with
| cons_mem h => simp [ne_nil_of_mem h]
| cons_duplicate h => simp [ne_nil_of_mem h.mem]
List.not_duplicate_singleton
theorem
(x y : α) : ¬x ∈+ [y]
@[simp]
theorem not_duplicate_singleton (x y : α) : ¬x ∈+ [y] := fun H => H.ne_singleton _ rfl
List.Duplicate.elim_nil
theorem
(h : x ∈+ []) : False
theorem Duplicate.elim_nil (h : x ∈+ []) : False :=
not_duplicate_nil x h
List.Duplicate.elim_singleton
theorem
{y : α} (h : x ∈+ [y]) : False
theorem Duplicate.elim_singleton {y : α} (h : x ∈+ [y]) : False :=
not_duplicate_singleton x y h
List.duplicate_cons_iff
theorem
{y : α} : x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l
theorem duplicate_cons_iff {y : α} : x ∈+ y :: lx ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l := by
refine ⟨fun h => ?_, fun h => ?_⟩
· obtain hm | hm := h
· exact Or.inl ⟨rfl, hm⟩
· exact Or.inr hm
· rcases h with (⟨rfl | h⟩ | h)
· simpa
· exact h.cons_duplicate
List.Duplicate.of_duplicate_cons
theorem
{y : α} (h : x ∈+ y :: l) (hx : x ≠ y) : x ∈+ l
theorem Duplicate.of_duplicate_cons {y : α} (h : x ∈+ y :: l) (hx : x ≠ y) : x ∈+ l := by
simpa [duplicate_cons_iff, hx.symm] using h
List.duplicate_cons_iff_of_ne
theorem
{y : α} (hne : x ≠ y) : x ∈+ y :: l ↔ x ∈+ l
theorem duplicate_cons_iff_of_ne {y : α} (hne : x ≠ y) : x ∈+ y :: lx ∈+ y :: l ↔ x ∈+ l := by
simp [duplicate_cons_iff, hne.symm]
List.Duplicate.mono_sublist
theorem
{l' : List α} (hx : x ∈+ l) (h : l <+ l') : x ∈+ l'
theorem Duplicate.mono_sublist {l' : List α} (hx : x ∈+ l) (h : l <+ l') : x ∈+ l' := by
induction h with
| slnil => exact hx
| cons y _ IH => exact (IH hx).duplicate_cons _
| cons₂ y h IH =>
rw [duplicate_cons_iff] at hx ⊢
rcases hx with (⟨rfl, hx⟩ | hx)
· simp [h.subset hx]
· simp [IH hx]
List.duplicate_iff_sublist
theorem
: x ∈+ l ↔ [x, x] <+ l
/-- The contrapositive of `List.nodup_iff_sublist`. -/
theorem duplicate_iff_sublist : x ∈+ lx ∈+ l ↔ [x, x] <+ l := by
induction' l with y l IH
· simp
· by_cases hx : x = y
· simp [hx, cons_sublist_cons, singleton_sublist]
· rw [duplicate_cons_iff_of_ne hx, IH]
refine ⟨sublist_cons_of_sublist y, fun h => ?_⟩
cases h
· assumption
· contradiction
List.nodup_iff_forall_not_duplicate
theorem
: Nodup l ↔ ∀ x : α, ¬x ∈+ l
theorem nodup_iff_forall_not_duplicate : NodupNodup l ↔ ∀ x : α, ¬x ∈+ l := by
simp_rw [nodup_iff_sublist, duplicate_iff_sublist]
List.exists_duplicate_iff_not_nodup
theorem
: (∃ x : α, x ∈+ l) ↔ ¬Nodup l
theorem exists_duplicate_iff_not_nodup : (∃ x : α, x ∈+ l) ↔ ¬Nodup l := by
simp [nodup_iff_forall_not_duplicate]
List.Duplicate.not_nodup
theorem
(h : x ∈+ l) : ¬Nodup l
theorem Duplicate.not_nodup (h : x ∈+ l) : ¬Nodup l := fun H =>
nodup_iff_forall_not_duplicate.mp H _ h
List.duplicate_iff_two_le_count
theorem
[DecidableEq α] : x ∈+ l ↔ 2 ≤ count x l
theorem duplicate_iff_two_le_count [DecidableEq α] : x ∈+ lx ∈+ l ↔ 2 ≤ count x l := by
simp [replicate_succ, duplicate_iff_sublist, le_count_iff_replicate_sublist]
List.decidableDuplicate
instance
[DecidableEq α] (x : α) : ∀ l : List α, Decidable (x ∈+ l)
instance decidableDuplicate [DecidableEq α] (x : α) : ∀ l : List α, Decidable (x ∈+ l)
| [] => isFalse (not_duplicate_nil x)
| y :: l =>
match decidableDuplicate x l with
| isTrue h => isTrue (h.duplicate_cons y)
| isFalse h =>
if hx : y = x ∧ x ∈ l then isTrue (hx.left.symm ▸ List.Mem.duplicate_cons_self hx.right)
else isFalse (by simpa [duplicate_cons_iff, h] using hx)