Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑ Ctrl+↓ to navigate,
Ctrl+🖱️ to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2021 Yakov Pechersky. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yakov Pechersky, Chris Hughes
! This file was ported from Lean 3 source module data.list.duplicate
! leanprover-community/mathlib commit f694c7dead66f5d4c80f446c796a5aad14707f0e
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.List.Nodup
/-!
# List duplicates
## Main definitions
* `List.Duplicate x l : Prop` is an inductive property that holds when `x` is a duplicate in `l`
## Implementation details
In this file, `x ∈+ l` notation is shorthand for `List.Duplicate x l`.
-/
variable { α : Type _ }
namespace List
/-- Property that an element `x : α` of `l : List α` can be found in the list more than once. -/
inductive Duplicate ( x : α ) : List α → Prop
| cons_mem { l : List α } : x ∈ l → Duplicate x ( x :: l )
| cons_duplicate { y : α } { l : List α } : Duplicate x l → Duplicate x ( y :: l )
#align list.duplicate List.Duplicate
-- mathport name: «expr ∈+ »
local infixl :50 " ∈+ " => List.Duplicate
variable { l : List α } { x : α }
theorem Mem.duplicate_cons_self : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈ l → x ∈+ x :: l Mem.duplicate_cons_self ( h : x ∈ l ) : x ∈+ x :: l :=
Duplicate.cons_mem : ∀ {α : Type ?u.9087} {x : α } {l : List α }, x ∈ l → x ∈+ x :: l Duplicate.cons_mem h
#align list.mem.duplicate_cons_self List.Mem.duplicate_cons_self : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈ l → x ∈+ x :: l List.Mem.duplicate_cons_self
theorem Duplicate.duplicate_cons : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), x ∈+ y :: l Duplicate.duplicate_cons ( h : x ∈+ l ) ( y : α ) : x ∈+ y :: l :=
Duplicate.cons_duplicate : ∀ {α : Type ?u.9125} {x y : α } {l : List α }, x ∈+ l → x ∈+ y :: l Duplicate.cons_duplicate h
#align list.duplicate.duplicate_cons List.Duplicate.duplicate_cons : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), x ∈+ y :: l List.Duplicate.duplicate_cons
theorem Duplicate.mem : x ∈+ l → x ∈ l Duplicate.mem ( h : x ∈+ l ) : x ∈ l := by
induction' h with l' _ y l' _ hm
· exact mem_cons_self : ∀ {α : Type ?u.9236} (a : α ) (l : List α ), a ∈ a :: l mem_cons_self _ _
· exact mem_cons_of_mem : ∀ {α : Type ?u.9249} (y : α ) {a : α } {l : List α }, a ∈ l → a ∈ y :: l mem_cons_of_mem _ hm
#align list.duplicate.mem List.Duplicate.mem : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → x ∈ l List.Duplicate.mem
theorem Duplicate.mem_cons_self : x ∈+ x :: l → x ∈ l Duplicate.mem_cons_self ( h : x ∈+ x :: l ) : x ∈ l := by
cases' h with _ h _ _ h
· exact h
· exact h . mem : ∀ {α : Type ?u.9475} {l : List α } {x : α }, x ∈+ l → x ∈ l mem
#align list.duplicate.mem_cons_self List.Duplicate.mem_cons_self : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ x :: l → x ∈ l List.Duplicate.mem_cons_self
@[ simp ]
theorem duplicate_cons_self_iff : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ x :: l ↔ x ∈ l duplicate_cons_self_iff : x ∈+ x :: l ↔ x ∈ l :=
⟨ Duplicate.mem_cons_self : ∀ {α : Type ?u.9555} {l : List α } {x : α }, x ∈+ x :: l → x ∈ l Duplicate.mem_cons_self, Mem.duplicate_cons_self : ∀ {α : Type ?u.9569} {l : List α } {x : α }, x ∈ l → x ∈+ x :: l Mem.duplicate_cons_self⟩
#align list.duplicate_cons_self_iff List.duplicate_cons_self_iff : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ x :: l ↔ x ∈ l List.duplicate_cons_self_iff
theorem Duplicate.ne_nil : x ∈+ l → l ≠ [] Duplicate.ne_nil ( h : x ∈+ l ) : l ≠ [] := fun H => ( mem_nil_iff : ∀ {α : Type ?u.9628} (a : α ), a ∈ [] ↔ False mem_nil_iff x ). mp : ∀ {a b : Prop }, (a ↔ b ) → a → b mp ( H ▸ h . mem : ∀ {α : Type ?u.9634} {l : List α } {x : α }, x ∈+ l → x ∈ l mem)
#align list.duplicate.ne_nil List.Duplicate.ne_nil : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → l ≠ [] List.Duplicate.ne_nil
@[ simp ]
theorem not_duplicate_nil : ∀ {α : Type u_1} (x : α ), ¬ x ∈+ [] not_duplicate_nil ( x : α ) : ¬ x ∈+ [] := fun H => H . ne_nil : ∀ {α : Type ?u.9683} {l : List α } {x : α }, x ∈+ l → l ≠ [] ne_nil rfl : ∀ {α : Sort ?u.9696} {a : α }, a = a rfl
#align list.not_duplicate_nil List.not_duplicate_nil : ∀ {α : Type u_1} (x : α ), ¬ x ∈+ [] List.not_duplicate_nil
theorem Duplicate.ne_singleton : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), l ≠ [y ] Duplicate.ne_singleton ( h : x ∈+ l ) ( y : α ) : l ≠ [ y ] := by
induction' h with l' h z l' h _
· simp [ ne_nil_of_mem : ∀ {α : Type ?u.9799} {a : α } {l : List α }, a ∈ l → l ≠ [] ne_nil_of_mem h ]
· simp [ ne_nil_of_mem : ∀ {α : Type ?u.9942} {a : α } {l : List α }, a ∈ l → l ≠ [] ne_nil_of_mem h . mem : ∀ {α : Type ?u.9946} {l : List α } {x : α }, x ∈+ l → x ∈ l mem]
#align list.duplicate.ne_singleton List.Duplicate.ne_singleton : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), l ≠ [y ] List.Duplicate.ne_singleton
@[ simp ]
theorem not_duplicate_singleton : ∀ {α : Type u_1} (x y : α ), ¬ x ∈+ [y ] not_duplicate_singleton ( x y : α ) : ¬ x ∈+ [ y ] := fun H => H . ne_singleton : ∀ {α : Type ?u.10067} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), l ≠ [y ] ne_singleton _ rfl : ∀ {α : Sort ?u.10082} {a : α }, a = a rfl
#align list.not_duplicate_singleton List.not_duplicate_singleton : ∀ {α : Type u_1} (x y : α ), ¬ x ∈+ [y ] List.not_duplicate_singleton
theorem Duplicate.elim_nil : ∀ {α : Type u_1} {x : α }, x ∈+ [] → False Duplicate.elim_nil ( h : x ∈+ [] ) : False :=
not_duplicate_nil : ∀ {α : Type ?u.10132} (x : α ), ¬ x ∈+ [] not_duplicate_nil x h
#align list.duplicate.elim_nil List.Duplicate.elim_nil : ∀ {α : Type u_1} {x : α }, x ∈+ [] → False List.Duplicate.elim_nil
theorem Duplicate.elim_singleton : ∀ {α : Type u_1} {x y : α }, x ∈+ [y ] → False Duplicate.elim_singleton { y : α } ( h : x ∈+ [ y ]) : False :=
not_duplicate_singleton : ∀ {α : Type ?u.10163} (x y : α ), ¬ x ∈+ [y ] not_duplicate_singleton x y h
#align list.duplicate.elim_singleton List.Duplicate.elim_singleton : ∀ {α : Type u_1} {x y : α }, x ∈+ [y ] → False List.Duplicate.elim_singleton
theorem duplicate_cons_iff : ∀ {y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l duplicate_cons_iff { y : α } : x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l := by
refine' ⟨ fun h => _ , fun h => _ ⟩
· cases' h with _ hm _ _ hm refine'_1.cons_mem refine'_1.cons_duplicate
· refine'_1.cons_mem refine'_1.cons_duplicate exact Or.inl : ∀ {a b : Prop }, a → a ∨ b Or.inl ⟨ rfl : ∀ {α : Sort ?u.10423} {a : α }, a = a rfl, hm ⟩
· exact Or.inr : ∀ {a b : Prop }, b → a ∨ b Or.inr hm
· rcases h with (⟨rfl | h⟩ | h) : ?m.10226
(⟨ rfl | h ⟩ | h (⟨rfl | h⟩ | h) : ?m.10226
)refine'_2.inl.intro.refl refine'_2.inr
· refine'_2.inl.intro.refl refine'_2.inr simpa
· exact h . cons_duplicate : ∀ {α : Type ?u.10944} {x y : α } {l : List α }, x ∈+ l → x ∈+ y :: l cons_duplicate
#align list.duplicate_cons_iff List.duplicate_cons_iff : ∀ {α : Type u_1} {l : List α } {x y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l List.duplicate_cons_iff
theorem Duplicate.of_duplicate_cons : ∀ {y : α }, x ∈+ y :: l → x ≠ y → x ∈+ l Duplicate.of_duplicate_cons { y : α } ( h : x ∈+ y :: l ) ( hx : x ≠ y ) : x ∈+ l := by
simpa [ duplicate_cons_iff : ∀ {α : Type ?u.11044} {l : List α } {x y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l duplicate_cons_iff, hx . symm : ∀ {α : Sort ?u.11069} {a b : α }, a ≠ b → b ≠ a symm] using h
#align list.duplicate.of_duplicate_cons List.Duplicate.of_duplicate_cons : ∀ {α : Type u_1} {l : List α } {x y : α }, x ∈+ y :: l → x ≠ y → x ∈+ l List.Duplicate.of_duplicate_cons
theorem duplicate_cons_iff_of_ne : ∀ {y : α }, x ≠ y → (x ∈+ y :: l ↔ x ∈+ l ) duplicate_cons_iff_of_ne { y : α } ( hne : x ≠ y ) : x ∈+ y :: l ↔ x ∈+ l := by
simp [ duplicate_cons_iff : ∀ {α : Type ?u.11574} {l : List α } {x y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l duplicate_cons_iff, hne . symm : ∀ {α : Sort ?u.11599} {a b : α }, a ≠ b → b ≠ a symm]
#align list.duplicate_cons_iff_of_ne List.duplicate_cons_iff_of_ne : ∀ {α : Type u_1} {l : List α } {x y : α }, x ≠ y → (x ∈+ y :: l ↔ x ∈+ l ) List.duplicate_cons_iff_of_ne
theorem Duplicate.mono_sublist : ∀ {α : Type u_1} {l : List α } {x : α } {l' : List α }, x ∈+ l → l <+ l' → x ∈+ l' Duplicate.mono_sublist { l' : List α } ( hx : x ∈+ l ) ( h : l <+ l' ) : x ∈+ l' := by
induction' h with l₁ l₂ y _ IH l₁ l₂ y h IH
· exact hx
· exact ( IH hx ). duplicate_cons : ∀ {α : Type ?u.12177} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), x ∈+ y :: l duplicate_cons _
· rw [ duplicate_cons_iff : ∀ {α : Type ?u.12193} {l : List α } {x y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l duplicate_cons_iff] at hx ⊢
rcases hx with (⟨rfl, hx⟩ | hx) : y = x ∧ x ∈ l₁ ∨ x ∈+ l₁ (⟨rfl, hx⟩ : y = x ∧ x ∈ l₁ ⟨rfl ⟨rfl, hx⟩ : y = x ∧ x ∈ l₁ , hx : unknown free variable '_uniq.12279'
hx ⟨rfl, hx⟩ : y = x ∧ x ∈ l₁ ⟩⟨rfl, hx⟩ | hx : y = x ∧ x ∈ l₁ ∨ x ∈+ l₁ | hx (⟨rfl, hx⟩ | hx) : y = x ∧ x ∈ l₁ ∨ x ∈+ l₁ )
· simp [ h . subset : ∀ {α : Type ?u.12302} {l₁ l₂ : List α }, l₁ <+ l₂ → l₁ ⊆ l₂ subset hx ]
· simp [ IH hx ]
#align list.duplicate.mono_sublist List.Duplicate.mono_sublist : ∀ {α : Type u_1} {l : List α } {x : α } {l' : List α }, x ∈+ l → l <+ l' → x ∈+ l' List.Duplicate.mono_sublist
/-- The contrapositive of `List.nodup_iff_sublist`. -/
theorem duplicate_iff_sublist : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l ↔ [x , x ] <+ l duplicate_iff_sublist : x ∈+ l ↔ [ x , x ] <+ l := by
induction' l with y l IH
· simp
· by_cases hx : x = y
· simp [ hx , cons_sublist_cons_iff , singleton_sublist : ∀ {α : Type ?u.13393} {a : α } {l : List α }, [a ] <+ l ↔ a ∈ l singleton_sublist]
· rw [ duplicate_cons_iff_of_ne : ∀ {α : Type ?u.14200} {l : List α } {x y : α }, x ≠ y → (x ∈+ y :: l ↔ x ∈+ l ) duplicate_cons_iff_of_ne hx , IH ]
refine' ⟨ sublist_cons_of_sublist : ∀ {α : Type ?u.14234} (a : α ) {l₁ l₂ : List α }, l₁ <+ l₂ → l₁ <+ a :: l₂ sublist_cons_of_sublist y , fun h => _ ⟩
cases h
· assumption
· contradiction
#align list.duplicate_iff_sublist List.duplicate_iff_sublist : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l ↔ [x , x ] <+ l List.duplicate_iff_sublist
theorem nodup_iff_forall_not_duplicate : Nodup l ↔ ∀ (x : α ), ¬ x ∈+ l nodup_iff_forall_not_duplicate : Nodup l ↔ ∀ x : α , ¬ x ∈+ l := by
simp_rw [ nodup_iff_sublist , (∀ (a : α ), ¬ [a , a ] <+ l ) ↔ ∀ (x : α ), ¬ x ∈+ l duplicate_iff_sublist : ∀ {α : Type ?u.14754} {l : List α } {x : α }, x ∈+ l ↔ [x , x ] <+ l duplicate_iff_sublist]
#align list.nodup_iff_forall_not_duplicate List.nodup_iff_forall_not_duplicate : ∀ {α : Type u_1} {l : List α }, Nodup l ↔ ∀ (x : α ), ¬ x ∈+ l List.nodup_iff_forall_not_duplicate
theorem exists_duplicate_iff_not_nodup : ∀ {α : Type u_1} {l : List α }, (∃ x , x ∈+ l ) ↔ ¬ Nodup l exists_duplicate_iff_not_nodup : (∃ x : α , x ∈+ l ) ↔ ¬ Nodup l := by
simp [ nodup_iff_forall_not_duplicate : ∀ {α : Type ?u.14869} {l : List α }, Nodup l ↔ ∀ (x : α ), ¬ x ∈+ l nodup_iff_forall_not_duplicate]
#align list.exists_duplicate_iff_not_nodup List.exists_duplicate_iff_not_nodup : ∀ {α : Type u_1} {l : List α }, (∃ x , x ∈+ l ) ↔ ¬ Nodup l List.exists_duplicate_iff_not_nodup
theorem Duplicate.not_nodup ( h : x ∈+ l ) : ¬ Nodup l := fun H =>
nodup_iff_forall_not_duplicate : ∀ {α : Type ?u.16259} {l : List α }, Nodup l ↔ ∀ (x : α ), ¬ x ∈+ l nodup_iff_forall_not_duplicate. mp : ∀ {a b : Prop }, (a ↔ b ) → a → b mp H _ h
#align list.duplicate.not_nodup List.Duplicate.not_nodup : ∀ {α : Type u_1} {l : List α } {x : α }, x ∈+ l → ¬ Nodup l List.Duplicate.not_nodup
theorem duplicate_iff_two_le_count [ DecidableEq : Sort ?u.16290 → Sort (max1?u.16290) DecidableEq α ] : x ∈+ l ↔ 2 ≤ count : {α : Type ?u.16317} → [inst : BEq α ] → α → List α → ℕ count x l := by
simp [ duplicate_iff_sublist : ∀ {α : Type ?u.16376} {l : List α } {x : α }, x ∈+ l ↔ [x , x ] <+ l duplicate_iff_sublist, le_count_iff_replicate_sublist ]
#align list.duplicate_iff_two_le_count List.duplicate_iff_two_le_count
instance decidableDuplicate [ DecidableEq : Sort ?u.17733 → Sort (max1?u.17733) DecidableEq α ] ( x : α ) : ∀ l : List α , Decidable ( x ∈+ l )
| [] => isFalse ( not_duplicate_nil : ∀ {α : Type ?u.17772} (x : α ), ¬ x ∈+ [] not_duplicate_nil x )
| y :: l =>
match decidableDuplicate x l with
| isTrue h => isTrue ( h . duplicate_cons : ∀ {α : Type ?u.17844} {l : List α } {x : α }, x ∈+ l → ∀ (y : α ), x ∈+ y :: l duplicate_cons y )
| isFalse h =>
if hx : y = x ∧ x ∈ l then isTrue ( hx . left : ∀ {a b : Prop }, a ∧ b → a left. symm : ∀ {α : Sort ?u.17948} {a b : α }, a = b → b = a symm ▸ List.Mem.duplicate_cons_self : ∀ {α : Type ?u.17959} {l : List α } {x : α }, x ∈ l → x ∈+ x :: l List.Mem.duplicate_cons_self hx . right : ∀ {a b : Prop }, a ∧ b → b right)
else isFalse ( by simpa [ duplicate_cons_iff : ∀ {α : Type ?u.18137} {l : List α } {x y : α }, x ∈+ y :: l ↔ y = x ∧ x ∈ l ∨ x ∈+ l duplicate_cons_iff, h ] using hx )
#align list.decidable_duplicate List.decidableDuplicate
end List