data.list.nodup
⟷
Mathlib.Data.List.Nodup
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
This PR will split most of the lemmas in data.set.pairwise
which are independent of the data.set.lattice
. It makes a lot of files no longer depend on data.set.lattice
.
mathlib4 PR: https://github.com/leanprover-community/mathlib4/pull/1184
Co-authored-by: Yaël Dillies <yael.dillies@gmail.com>
@@ -6,7 +6,7 @@ Authors: Mario Carneiro, Kenny Lau
import data.list.lattice
import data.list.pairwise
import data.list.forall2
-import data.set.pairwise
+import data.set.pairwise.basic
/-!
# Lists with no duplicates
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
list.replicate
and migrate to it (#18127)
This definition differs from list.repeat
by the order of arguments. The new order is in sync with the Lean 4 version.
@@ -125,14 +125,14 @@ index_of_nth_le $ index_of_lt_length.2 $ nth_le_mem _ _ _
theorem nodup_iff_count_le_one [decidable_eq α] {l : list α} : nodup l ↔ ∀ a, count a l ≤ 1 :=
nodup_iff_sublist.trans $ forall_congr $ λ a,
-have [a, a] <+ l ↔ 1 < count a l, from (@le_count_iff_repeat_sublist _ _ a l 2).symm,
+have [a, a] <+ l ↔ 1 < count a l, from (@le_count_iff_replicate_sublist _ _ a l 2).symm,
(not_congr this).trans not_lt
-theorem nodup_repeat (a : α) : ∀ {n : ℕ}, nodup (repeat a n) ↔ n ≤ 1
+theorem nodup_replicate (a : α) : ∀ {n : ℕ}, nodup (replicate n a) ↔ n ≤ 1
| 0 := by simp [nat.zero_le]
| 1 := by simp
| (n+2) := iff_of_false
- (λ H, nodup_iff_sublist.1 H a ((repeat_sublist_repeat _).2 (nat.le_add_left 2 n)))
+ (λ H, nodup_iff_sublist.1 H a ((replicate_sublist_replicate _).2 (nat.le_add_left 2 n)))
(not_le_of_lt $ nat.le_add_left 2 n)
@[simp] theorem count_eq_one_of_mem [decidable_eq α] {a : α} {l : list α}
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(first ported)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -170,14 +170,14 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iff
-/
-#print List.nthLe_eq_of_ne_imp_not_nodup /-
-theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.length)
- (hm : m < xs.length) (h : xs.nthLe n hn = xs.nthLe m hm) (hne : n ≠ m) : ¬Nodup xs :=
+#print List.not_nodup_of_get_eq_of_ne /-
+theorem not_nodup_of_get_eq_of_ne (xs : List α) (n m : ℕ) (hn : n < xs.length) (hm : m < xs.length)
+ (h : xs.nthLe n hn = xs.nthLe m hm) (hne : n ≠ m) : ¬Nodup xs :=
by
rw [nodup_iff_nth_le_inj]
simp only [exists_prop, exists_and_right, Classical.not_forall]
exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
-#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
+#align list.nth_le_eq_of_ne_imp_not_nodup List.not_nodup_of_get_eq_of_ne
-/
#print List.nthLe_index_of /-
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -265,7 +265,7 @@ theorem nodup_append_comm {l₁ l₂ : List α} : Nodup (l₁ ++ l₂) ↔ Nodup
#print List.nodup_middle /-
theorem nodup_middle {a : α} {l₁ l₂ : List α} : Nodup (l₁ ++ a :: l₂) ↔ Nodup (a :: (l₁ ++ l₂)) :=
by
- simp only [nodup_append, not_or, and_left_comm, and_assoc', nodup_cons, mem_append,
+ simp only [nodup_append, not_or, and_left_comm, and_assoc, nodup_cons, mem_append,
disjoint_cons_right]
#align list.nodup_middle List.nodup_middle
-/
@@ -374,7 +374,7 @@ theorem Nodup.diff [DecidableEq α] : l₁.Nodup → (l₁.diffₓ l₂).Nodup :
#print List.Nodup.mem_erase_iff /-
theorem Nodup.mem_erase_iff [DecidableEq α] (d : Nodup l) : a ∈ l.eraseₓ b ↔ a ≠ b ∧ a ∈ l := by
- rw [d.erase_eq_filter, mem_filter, and_comm']
+ rw [d.erase_eq_filter, mem_filter, and_comm]
#align list.nodup.mem_erase_iff List.Nodup.mem_erase_iff
-/
@@ -396,7 +396,7 @@ theorem nodup_bind {l₁ : List α} {f : α → List β} :
Nodup (l₁.bind f) ↔
(∀ x ∈ l₁, Nodup (f x)) ∧ Pairwise (fun a b : α => Disjoint (f a) (f b)) l₁ :=
by
- simp only [List.bind, nodup_join, pairwise_map, and_comm', and_left_comm, mem_map, exists_imp,
+ simp only [List.bind, nodup_join, pairwise_map, and_comm, and_left_comm, mem_map, exists_imp,
and_imp] <;>
rw [show (∀ (l : List β) (x : α), f x = l → x ∈ l₁ → nodup l) ↔ ∀ x : α, x ∈ l₁ → nodup (f x)
from forall_swap.trans <| forall_congr' fun _ => forall_eq']
@@ -535,7 +535,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : {a | a ∈ l}.Pairwise
rw [List.nodup_cons] at hl
have : ∀ b ∈ l, ¬a = b → r a b ↔ r a b := fun b hb =>
imp_iff_right (ne_of_mem_of_not_mem hb hl.1).symm
- simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm',
+ simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm,
forall₂_congr this]
#align list.nodup.pairwise_coe List.Nodup.pairwise_coe
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -161,7 +161,7 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
· specialize hl h.of_cons
by_cases hx : tl = [x]
· simpa [hx, and_comm, and_or_left] using h
- · rw [← Ne.def, hl] at hx
+ · rw [← Ne.def, hl] at hx
rcases hx with (rfl | ⟨y, hy, hx⟩)
· simp
· have : tl ≠ [] := ne_nil_of_mem hy
@@ -285,7 +285,7 @@ theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : Nodup (map f l))
by
induction' l with hd tl ih
· simp
- · simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
+ · simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
rintro _ (rfl | h₁) _ (rfl | h₂) h₃
· rfl
· apply (d.1 _ h₂ h₃.symm).elim
@@ -499,7 +499,7 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
l.map (Function.update f x y) = if x ∈ l then (l.map f).set (l.indexOfₓ x) y else l.map f :=
by
induction' l with hd tl ihl; · simp
- rw [nodup_cons] at hl
+ rw [nodup_cons] at hl
simp only [mem_cons_iff, map, ihl hl.2]
by_cases H : hd = x
· subst hd
@@ -514,7 +514,7 @@ theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl :
classical
refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
intro x hx
- rw [nodup_iff_count_le_one] at hl
+ rw [nodup_iff_count_le_one] at hl
exact absurd (hl x) hx.not_le
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
-/
@@ -532,7 +532,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : {a | a ∈ l}.Pairwise
by
induction' l with a l ih
· simp
- rw [List.nodup_cons] at hl
+ rw [List.nodup_cons] at hl
have : ∀ b ∈ l, ¬a = b → r a b ↔ r a b := fun b hb =>
imp_iff_right (ne_of_mem_of_not_mem hb hl.1).symm
simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm',
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -510,7 +510,12 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
#print List.Nodup.pairwise_of_forall_ne /-
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
- (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by classical
+ (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
+ classical
+ refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
+ intro x hx
+ rw [nodup_iff_count_le_one] at hl
+ exact absurd (hl x) hx.not_le
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -510,12 +510,7 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
#print List.Nodup.pairwise_of_forall_ne /-
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
- (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
- classical
- refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
- intro x hx
- rw [nodup_iff_count_le_one] at hl
- exact absurd (hl x) hx.not_le
+ (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by classical
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/b1abe23ae96fef89ad30d9f4362c307f72a55010
@@ -175,7 +175,7 @@ theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.len
(hm : m < xs.length) (h : xs.nthLe n hn = xs.nthLe m hm) (hne : n ≠ m) : ¬Nodup xs :=
by
rw [nodup_iff_nth_le_inj]
- simp only [exists_prop, exists_and_right, not_forall]
+ simp only [exists_prop, exists_and_right, Classical.not_forall]
exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,10 +3,10 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
-/
-import Mathbin.Data.List.Lattice
-import Mathbin.Data.List.Pairwise
-import Mathbin.Data.List.Forall2
-import Mathbin.Data.Set.Pairwise.Basic
+import Data.List.Lattice
+import Data.List.Pairwise
+import Data.List.Forall2
+import Data.Set.Pairwise.Basic
#align_import data.list.nodup from "leanprover-community/mathlib"@"c227d107bbada5d0d9d20287e3282c0a7f1651a0"
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -212,7 +212,7 @@ theorem nodup_replicate (a : α) : ∀ {n : ℕ}, Nodup (replicate n a) ↔ n
@[simp]
theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l) (h : a ∈ l) :
count a l = 1 :=
- le_antisymm (nodup_iff_count_le_one.1 d a) (count_pos.2 h)
+ le_antisymm (nodup_iff_count_le_one.1 d a) (count_pos_iff_mem.2 h)
#align list.count_eq_one_of_mem List.count_eq_one_of_mem
-/
@@ -321,7 +321,7 @@ theorem nodup_attach {l : List α} : Nodup (attach l) ↔ Nodup l :=
#align list.nodup_attach List.nodup_attach
-/
-alias nodup_attach ↔ nodup.of_attach nodup.attach
+alias ⟨nodup.of_attach, nodup.attach⟩ := nodup_attach
#align list.nodup.of_attach List.Nodup.of_attach
#align list.nodup.attach List.Nodup.attach
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,17 +2,14 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
-
-! This file was ported from Lean 3 source module data.list.nodup
-! leanprover-community/mathlib commit c227d107bbada5d0d9d20287e3282c0a7f1651a0
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.List.Lattice
import Mathbin.Data.List.Pairwise
import Mathbin.Data.List.Forall2
import Mathbin.Data.Set.Pairwise.Basic
+#align_import data.list.nodup from "leanprover-community/mathlib"@"c227d107bbada5d0d9d20287e3282c0a7f1651a0"
+
/-!
# Lists with no duplicates
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -440,7 +440,7 @@ protected theorem Nodup.filterMap {f : α → Option β} (h : ∀ a a' b, b ∈
-/
#print List.Nodup.concat /-
-protected theorem Nodup.concat (h : a ∉ l) (h' : l.Nodup) : (l.concat a).Nodup := by
+protected theorem Nodup.concat (h : a ∉ l) (h' : l.Nodup) : (l.push a).Nodup := by
rw [concat_eq_append] <;> exact h'.append (nodup_singleton _) (disjoint_singleton.2 h)
#align list.nodup.concat List.Nodup.concat
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -155,6 +155,7 @@ theorem nodup_iff_get?_ne_get? {l : List α} :
#align list.nodup_iff_nth_ne_nth List.nodup_iff_get?_ne_get?
-/
+#print List.Nodup.ne_singleton_iff /-
theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
l ≠ [x] ↔ l = [] ∨ ∃ y ∈ l, y ≠ x :=
by
@@ -170,6 +171,7 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
suffices ∃ (y : α) (H : y ∈ hd :: tl), y ≠ x by simpa [ne_nil_of_mem hy]
exact ⟨y, mem_cons_of_mem _ hy, hx⟩
#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iff
+-/
#print List.nthLe_eq_of_ne_imp_not_nodup /-
theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.length)
@@ -336,9 +338,11 @@ theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H}
#align list.nodup.pmap List.Nodup.pmap
-/
+#print List.Nodup.filter /-
theorem Nodup.filter (p : α → Prop) [DecidablePred p] {l} : Nodup l → Nodup (filter p l) :=
Pairwise.filter p
#align list.nodup.filter List.Nodup.filter
+-/
#print List.nodup_reverse /-
@[simp]
@@ -347,6 +351,7 @@ theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
#align list.nodup_reverse List.nodup_reverse
-/
+#print List.Nodup.erase_eq_filter /-
theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
l.eraseₓ a = filter (· ≠ a) l :=
by
@@ -356,22 +361,31 @@ theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
symm; rw [filter_eq_self]; simpa only [Ne.def, eq_comm] using m; exact not_not_intro rfl
· rw [erase_cons_tail _ h, filter_cons_of_pos, IH]; exact h
#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
+-/
+#print List.Nodup.erase /-
theorem Nodup.erase [DecidableEq α] (a : α) : Nodup l → Nodup (l.eraseₓ a) :=
Nodup.sublist <| erase_sublist _ _
#align list.nodup.erase List.Nodup.erase
+-/
+#print List.Nodup.diff /-
theorem Nodup.diff [DecidableEq α] : l₁.Nodup → (l₁.diffₓ l₂).Nodup :=
Nodup.sublist <| diff_sublist _ _
#align list.nodup.diff List.Nodup.diff
+-/
+#print List.Nodup.mem_erase_iff /-
theorem Nodup.mem_erase_iff [DecidableEq α] (d : Nodup l) : a ∈ l.eraseₓ b ↔ a ≠ b ∧ a ∈ l := by
rw [d.erase_eq_filter, mem_filter, and_comm']
#align list.nodup.mem_erase_iff List.Nodup.mem_erase_iff
+-/
+#print List.Nodup.not_mem_erase /-
theorem Nodup.not_mem_erase [DecidableEq α] (h : Nodup l) : a ∉ l.eraseₓ a := fun H =>
(h.mem_erase_iff.1 H).1 rfl
#align list.nodup.not_mem_erase List.Nodup.not_mem_erase
+-/
#print List.nodup_join /-
theorem nodup_join {L : List (List α)} :
@@ -405,6 +419,7 @@ protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l
#align list.nodup.product List.Nodup.product
-/
+#print List.Nodup.sigma /-
theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a, List (σ a)} (d₁ : Nodup l₁)
(d₂ : ∀ a, Nodup (l₂ a)) : (l₁.Sigma l₂).Nodup :=
nodup_bind.2
@@ -415,6 +430,7 @@ theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a, List (σ a)} (d₁ : Nod
rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩
exact n rfl⟩
#align list.nodup.sigma List.Nodup.sigma
+-/
#print List.Nodup.filterMap /-
protected theorem Nodup.filterMap {f : α → Option β} (h : ∀ a a' b, b ∈ f a → b ∈ f a' → a = a') :
@@ -451,6 +467,7 @@ theorem Nodup.inter [DecidableEq α] (l₂ : List α) : Nodup l₁ → Nodup (l
#align list.nodup.inter List.Nodup.inter
-/
+#print List.Nodup.diff_eq_filter /-
theorem Nodup.diff_eq_filter [DecidableEq α] :
∀ {l₁ l₂ : List α} (hl₁ : l₁.Nodup), l₁.diffₓ l₂ = l₁.filterₓ (· ∉ l₂)
| l₁, [], hl₁ => by simp
@@ -459,10 +476,13 @@ theorem Nodup.diff_eq_filter [DecidableEq α] :
rw [diff_cons, (hl₁.erase _).diff_eq_filter, hl₁.erase_eq_filter, filter_filter]
simp only [mem_cons_iff, not_or, and_comm]
#align list.nodup.diff_eq_filter List.Nodup.diff_eq_filter
+-/
+#print List.Nodup.mem_diff_iff /-
theorem Nodup.mem_diff_iff [DecidableEq α] (hl₁ : l₁.Nodup) : a ∈ l₁.diffₓ l₂ ↔ a ∈ l₁ ∧ a ∉ l₂ :=
by rw [hl₁.diff_eq_filter, mem_filter]
#align list.nodup.mem_diff_iff List.Nodup.mem_diff_iff
+-/
#print List.Nodup.set /-
protected theorem Nodup.set :
@@ -477,6 +497,7 @@ protected theorem Nodup.set :
#align list.nodup.update_nth List.Nodup.set
-/
+#print List.Nodup.map_update /-
theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α → β) (x : α) (y : β) :
l.map (Function.update f x y) = if x ∈ l then (l.map f).set (l.indexOfₓ x) y else l.map f :=
by
@@ -488,6 +509,7 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
simp [update_nth, hl.1]
· simp [Ne.symm H, H, update_nth, ← apply_ite (cons (f hd))]
#align list.nodup.map_update List.Nodup.map_update
+-/
#print List.Nodup.pairwise_of_forall_ne /-
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
mathlib commit https://github.com/leanprover-community/mathlib/commit/5f25c089cb34db4db112556f23c50d12da81b297
@@ -493,23 +493,23 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
(h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
classical
- refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
- intro x hx
- rw [nodup_iff_count_le_one] at hl
- exact absurd (hl x) hx.not_le
+ refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
+ intro x hx
+ rw [nodup_iff_count_le_one] at hl
+ exact absurd (hl x) hx.not_le
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
-/
#print List.Nodup.pairwise_of_set_pairwise /-
theorem Nodup.pairwise_of_set_pairwise {l : List α} {r : α → α → Prop} (hl : l.Nodup)
- (h : { x | x ∈ l }.Pairwise r) : l.Pairwise r :=
+ (h : {x | x ∈ l}.Pairwise r) : l.Pairwise r :=
hl.pairwise_of_forall_ne h
#align list.nodup.pairwise_of_set_pairwise List.Nodup.pairwise_of_set_pairwise
-/
#print List.Nodup.pairwise_coe /-
@[simp]
-theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : { a | a ∈ l }.Pairwise r ↔ l.Pairwise r :=
+theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : {a | a ∈ l}.Pairwise r ↔ l.Pairwise r :=
by
induction' l with a l ih
· simp
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -163,11 +163,11 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
· specialize hl h.of_cons
by_cases hx : tl = [x]
· simpa [hx, and_comm, and_or_left] using h
- · rw [← Ne.def, hl] at hx
+ · rw [← Ne.def, hl] at hx
rcases hx with (rfl | ⟨y, hy, hx⟩)
· simp
· have : tl ≠ [] := ne_nil_of_mem hy
- suffices ∃ (y : α)(H : y ∈ hd :: tl), y ≠ x by simpa [ne_nil_of_mem hy]
+ suffices ∃ (y : α) (H : y ∈ hd :: tl), y ≠ x by simpa [ne_nil_of_mem hy]
exact ⟨y, mem_cons_of_mem _ hy, hx⟩
#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iff
@@ -286,7 +286,7 @@ theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : Nodup (map f l))
by
induction' l with hd tl ih
· simp
- · simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
+ · simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
rintro _ (rfl | h₁) _ (rfl | h₂) h₃
· rfl
· apply (d.1 _ h₂ h₃.symm).elim
@@ -481,7 +481,7 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
l.map (Function.update f x y) = if x ∈ l then (l.map f).set (l.indexOfₓ x) y else l.map f :=
by
induction' l with hd tl ihl; · simp
- rw [nodup_cons] at hl
+ rw [nodup_cons] at hl
simp only [mem_cons_iff, map, ihl hl.2]
by_cases H : hd = x
· subst hd
@@ -495,7 +495,7 @@ theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl :
classical
refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
intro x hx
- rw [nodup_iff_count_le_one] at hl
+ rw [nodup_iff_count_le_one] at hl
exact absurd (hl x) hx.not_le
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
-/
@@ -513,7 +513,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : { a | a ∈ l }.Pairwi
by
induction' l with a l ih
· simp
- rw [List.nodup_cons] at hl
+ rw [List.nodup_cons] at hl
have : ∀ b ∈ l, ¬a = b → r a b ↔ r a b := fun b hb =>
imp_iff_right (ne_of_mem_of_not_mem hb hl.1).symm
simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm',
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -155,12 +155,6 @@ theorem nodup_iff_get?_ne_get? {l : List α} :
#align list.nodup_iff_nth_ne_nth List.nodup_iff_get?_ne_get?
-/
-/- warning: list.nodup.ne_singleton_iff -> List.Nodup.ne_singleton_iff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (x : α), Iff (Ne.{succ u1} (List.{u1} α) l (List.cons.{u1} α x (List.nil.{u1} α))) (Or (Eq.{succ u1} (List.{u1} α) l (List.nil.{u1} α)) (Exists.{succ u1} α (fun (y : α) => Exists.{0} (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) y l) (fun (H : Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) y l) => Ne.{succ u1} α y x)))))
-but is expected to have type
- forall {α : Type.{u1}} {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (x : α), Iff (Ne.{succ u1} (List.{u1} α) l (List.cons.{u1} α x (List.nil.{u1} α))) (Or (Eq.{succ u1} (List.{u1} α) l (List.nil.{u1} α)) (Exists.{succ u1} α (fun (y : α) => And (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) y l) (Ne.{succ u1} α y x)))))
-Case conversion may be inaccurate. Consider using '#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iffₓ'. -/
theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
l ≠ [x] ↔ l = [] ∨ ∃ y ∈ l, y ≠ x :=
by
@@ -342,12 +336,6 @@ theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H}
#align list.nodup.pmap List.Nodup.pmap
-/
-/- warning: list.nodup.filter -> List.Nodup.filter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (List.Nodup.{u1} α (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l))
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) {_inst_1 : List.{u1} α}, (List.Nodup.{u1} α _inst_1) -> (List.Nodup.{u1} α (List.filter.{u1} α p _inst_1))
-Case conversion may be inaccurate. Consider using '#align list.nodup.filter List.Nodup.filterₓ'. -/
theorem Nodup.filter (p : α → Prop) [DecidablePred p] {l} : Nodup l → Nodup (filter p l) :=
Pairwise.filter p
#align list.nodup.filter List.Nodup.filter
@@ -359,12 +347,6 @@ theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
#align list.nodup_reverse List.nodup_reverse
-/
-/- warning: list.nodup.erase_eq_filter -> List.Nodup.erase_eq_filter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (a : α), Eq.{succ u1} (List.{u1} α) (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a) (List.filterₓ.{u1} α (fun (_x : α) => Ne.{succ u1} α _x a) (fun (a_1 : α) => Ne.decidable.{succ u1} α (fun (a : α) (b : α) => _inst_1 a b) a_1 a) l))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (a : α), Eq.{succ u1} (List.{u1} α) (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a) (List.filter.{u1} α (fun (a_1 : α) => Decidable.decide (Ne.{succ u1} α a_1 a) (instDecidableNot (Eq.{succ u1} α a_1 a) (_inst_1 a_1 a))) l))
-Case conversion may be inaccurate. Consider using '#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filterₓ'. -/
theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
l.eraseₓ a = filter (· ≠ a) l :=
by
@@ -375,42 +357,18 @@ theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
· rw [erase_cons_tail _ h, filter_cons_of_pos, IH]; exact h
#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
-/- warning: list.nodup.erase -> List.Nodup.erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l : List.{u1} α} [_inst_1 : DecidableEq.{succ u1} α] (a : α), (List.Nodup.{u1} α l) -> (List.Nodup.{u1} α (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a))
-but is expected to have type
- forall {α : Type.{u1}} {l : List.{u1} α} [_inst_1 : DecidableEq.{succ u1} α] (a : α), (List.Nodup.{u1} α l) -> (List.Nodup.{u1} α (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a))
-Case conversion may be inaccurate. Consider using '#align list.nodup.erase List.Nodup.eraseₓ'. -/
theorem Nodup.erase [DecidableEq α] (a : α) : Nodup l → Nodup (l.eraseₓ a) :=
Nodup.sublist <| erase_sublist _ _
#align list.nodup.erase List.Nodup.erase
-/- warning: list.nodup.diff -> List.Nodup.diff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l₁) -> (List.Nodup.{u1} α (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂))
-but is expected to have type
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l₁) -> (List.Nodup.{u1} α (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂))
-Case conversion may be inaccurate. Consider using '#align list.nodup.diff List.Nodup.diffₓ'. -/
theorem Nodup.diff [DecidableEq α] : l₁.Nodup → (l₁.diffₓ l₂).Nodup :=
Nodup.sublist <| diff_sublist _ _
#align list.nodup.diff List.Nodup.diff
-/- warning: list.nodup.mem_erase_iff -> List.Nodup.mem_erase_iff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l : List.{u1} α} {a : α} {b : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l) -> (Iff (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l b)) (And (Ne.{succ u1} α a b) (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l)))
-but is expected to have type
- forall {α : Type.{u1}} {l : List.{u1} α} {a : α} {b : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l) -> (Iff (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l b)) (And (Ne.{succ u1} α a b) (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l)))
-Case conversion may be inaccurate. Consider using '#align list.nodup.mem_erase_iff List.Nodup.mem_erase_iffₓ'. -/
theorem Nodup.mem_erase_iff [DecidableEq α] (d : Nodup l) : a ∈ l.eraseₓ b ↔ a ≠ b ∧ a ∈ l := by
rw [d.erase_eq_filter, mem_filter, and_comm']
#align list.nodup.mem_erase_iff List.Nodup.mem_erase_iff
-/- warning: list.nodup.not_mem_erase -> List.Nodup.not_mem_erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l) -> (Not (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a)))
-but is expected to have type
- forall {α : Type.{u1}} {l : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l) -> (Not (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a)))
-Case conversion may be inaccurate. Consider using '#align list.nodup.not_mem_erase List.Nodup.not_mem_eraseₓ'. -/
theorem Nodup.not_mem_erase [DecidableEq α] (h : Nodup l) : a ∉ l.eraseₓ a := fun H =>
(h.mem_erase_iff.1 H).1 rfl
#align list.nodup.not_mem_erase List.Nodup.not_mem_erase
@@ -447,12 +405,6 @@ protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l
#align list.nodup.product List.Nodup.product
-/
-/- warning: list.nodup.sigma -> List.Nodup.sigma is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {σ : α -> Type.{u2}} {l₂ : forall (a : α), List.{u2} (σ a)}, (List.Nodup.{u1} α l₁) -> (forall (a : α), List.Nodup.{u2} (σ a) (l₂ a)) -> (List.Nodup.{max u1 u2} (Sigma.{u1, u2} α (fun (a : α) => σ a)) (List.sigma.{u1, u2} α (fun (a : α) => σ a) l₁ l₂))
-but is expected to have type
- forall {α : Type.{u2}} {l₁ : List.{u2} α} {σ : α -> Type.{u1}} {l₂ : forall (a : α), List.{u1} (σ a)}, (List.Nodup.{u2} α l₁) -> (forall (a : α), List.Nodup.{u1} (σ a) (l₂ a)) -> (List.Nodup.{max u2 u1} (Sigma.{u2, u1} α (fun (a : α) => σ a)) (List.sigma.{u2, u1} α (fun (a : α) => σ a) l₁ l₂))
-Case conversion may be inaccurate. Consider using '#align list.nodup.sigma List.Nodup.sigmaₓ'. -/
theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a, List (σ a)} (d₁ : Nodup l₁)
(d₂ : ∀ a, Nodup (l₂ a)) : (l₁.Sigma l₂).Nodup :=
nodup_bind.2
@@ -499,12 +451,6 @@ theorem Nodup.inter [DecidableEq α] (l₂ : List α) : Nodup l₁ → Nodup (l
#align list.nodup.inter List.Nodup.inter
-/
-/- warning: list.nodup.diff_eq_filter -> List.Nodup.diff_eq_filter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Nodup.{u1} α l₁) -> (Eq.{succ u1} (List.{u1} α) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂) (List.filterₓ.{u1} α (fun (_x : α) => Not (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) _x l₂)) (fun (a : α) => Not.decidable (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂) (List.decidableMem.{u1} α (fun (a : α) (b : α) => _inst_1 a b) a l₂)) l₁))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Nodup.{u1} α l₁) -> (Eq.{succ u1} (List.{u1} α) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂) (List.filter.{u1} α (fun (a : α) => Decidable.decide (Not (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂)) (instDecidableNot (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂) (List.instDecidableMemListInstMembershipList.{u1} α (fun (a : α) (b : α) => _inst_1 a b) a l₂))) l₁))
-Case conversion may be inaccurate. Consider using '#align list.nodup.diff_eq_filter List.Nodup.diff_eq_filterₓ'. -/
theorem Nodup.diff_eq_filter [DecidableEq α] :
∀ {l₁ l₂ : List α} (hl₁ : l₁.Nodup), l₁.diffₓ l₂ = l₁.filterₓ (· ∉ l₂)
| l₁, [], hl₁ => by simp
@@ -514,12 +460,6 @@ theorem Nodup.diff_eq_filter [DecidableEq α] :
simp only [mem_cons_iff, not_or, and_comm]
#align list.nodup.diff_eq_filter List.Nodup.diff_eq_filter
-/- warning: list.nodup.mem_diff_iff -> List.Nodup.mem_diff_iff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l₁) -> (Iff (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂)) (And (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₁) (Not (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂))))
-but is expected to have type
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α} {a : α} [_inst_1 : DecidableEq.{succ u1} α], (List.Nodup.{u1} α l₁) -> (Iff (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂)) (And (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₁) (Not (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂))))
-Case conversion may be inaccurate. Consider using '#align list.nodup.mem_diff_iff List.Nodup.mem_diff_iffₓ'. -/
theorem Nodup.mem_diff_iff [DecidableEq α] (hl₁ : l₁.Nodup) : a ∈ l₁.diffₓ l₂ ↔ a ∈ l₁ ∧ a ∉ l₂ :=
by rw [hl₁.diff_eq_filter, mem_filter]
#align list.nodup.mem_diff_iff List.Nodup.mem_diff_iff
@@ -537,12 +477,6 @@ protected theorem Nodup.set :
#align list.nodup.update_nth List.Nodup.set
-/
-/- warning: list.nodup.map_update -> List.Nodup.map_update is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (f : α -> β) (x : α) (y : β), Eq.{succ u2} (List.{u2} β) (List.map.{u1, u2} α β (Function.update.{succ u1, succ u2} α (fun (ᾰ : α) => β) (fun (a : α) (b : α) => _inst_1 a b) f x y) l) (ite.{succ u2} (List.{u2} β) (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) x l) (List.decidableMem.{u1} α (fun (a : α) (b : α) => _inst_1 a b) x l) (List.set.{u2} β (List.map.{u1, u2} α β f l) (List.indexOfₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) x l) y) (List.map.{u1, u2} α β f l)))
-but is expected to have type
- forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] {l : List.{u1} α}, (List.Nodup.{u1} α l) -> (forall (f : α -> β) (x : α) (y : β), Eq.{succ u2} (List.{u2} β) (List.map.{u1, u2} α β (Function.update.{succ u1, succ u2} α (fun (ᾰ : α) => β) (fun (a : α) (b : α) => _inst_1 a b) f x y) l) (ite.{succ u2} (List.{u2} β) (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) x l) (List.instDecidableMemListInstMembershipList.{u1} α (fun (a : α) (b : α) => _inst_1 a b) x l) (List.set.{u2} β (List.map.{u1, u2} α β f l) (List.indexOf.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) x l) y) (List.map.{u1, u2} α β f l)))
-Case conversion may be inaccurate. Consider using '#align list.nodup.map_update List.Nodup.map_updateₓ'. -/
theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α → β) (x : α) (y : β) :
l.map (Function.update f x y) = if x ∈ l then (l.map f).set (l.indexOfₓ x) y else l.map f :=
by
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -370,14 +370,9 @@ theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
by
induction' d with b l m d IH; · rfl
by_cases b = a
- · subst h
- rw [erase_cons_head, filter_cons_of_neg]
- symm
- rw [filter_eq_self]
- simpa only [Ne.def, eq_comm] using m
- exact not_not_intro rfl
- · rw [erase_cons_tail _ h, filter_cons_of_pos, IH]
- exact h
+ · subst h; rw [erase_cons_head, filter_cons_of_neg]
+ symm; rw [filter_eq_self]; simpa only [Ne.def, eq_comm] using m; exact not_not_intro rfl
+ · rw [erase_cons_tail _ h, filter_cons_of_pos, IH]; exact h
#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
/- warning: list.nodup.erase -> List.Nodup.erase is a dubious translation:
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce86f4e05e9a9b8da5e316b22c76ce76440c56a1
@@ -4,14 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
! This file was ported from Lean 3 source module data.list.nodup
-! leanprover-community/mathlib commit f694c7dead66f5d4c80f446c796a5aad14707f0e
+! leanprover-community/mathlib commit c227d107bbada5d0d9d20287e3282c0a7f1651a0
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.List.Lattice
import Mathbin.Data.List.Pairwise
import Mathbin.Data.List.Forall2
-import Mathbin.Data.Set.Pairwise
+import Mathbin.Data.Set.Pairwise.Basic
/-!
# Lists with no duplicates
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
Most of them go back to the port.
@@ -101,7 +101,7 @@ theorem nodup_iff_injective_get {l : List α} :
fun hinj i j hij h => Nat.ne_of_lt hij (Fin.val_eq_of_eq (hinj h))⟩
set_option linter.deprecated false in
-@[deprecated nodup_iff_injective_get]
+@[deprecated nodup_iff_injective_get] -- 2023-01-10
theorem nodup_iff_nthLe_inj {l : List α} :
Nodup l ↔ ∀ i j h₁ h₂, nthLe l i h₁ = nthLe l j h₂ → i = j :=
nodup_iff_injective_get.trans
@@ -114,7 +114,7 @@ theorem Nodup.get_inj_iff {l : List α} (h : Nodup l) {i j : Fin l.length} :
(nodup_iff_injective_get.1 h).eq_iff
set_option linter.deprecated false in
-@[deprecated Nodup.get_inj_iff]
+@[deprecated Nodup.get_inj_iff] -- 2023-01-10
theorem Nodup.nthLe_inj_iff {l : List α} (h : Nodup l) {i j : ℕ} (hi : i < l.length)
(hj : j < l.length) : l.nthLe i hi = l.nthLe j hj ↔ i = j :=
⟨nodup_iff_nthLe_inj.mp h _ _ _ _, by simp (config := { contextual := true })⟩
@@ -160,7 +160,7 @@ theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.leng
nodup_iff_injective_get.1 H (by simp)
set_option linter.deprecated false in
-@[simp, deprecated get_indexOf]
+@[simp, deprecated get_indexOf] -- 2023-01-10
theorem nthLe_index_of [DecidableEq α] {l : List α} (H : Nodup l) (n h) :
indexOf (nthLe l n h) l = n :=
nodup_iff_nthLe_inj.1 H _ _ _ h <| indexOf_nthLe <| indexOf_lt_length.2 <| nthLe_mem _ _ _
@@ -150,15 +150,7 @@ theorem not_nodup_of_get_eq_of_ne (xs : List α) (n m : Fin xs.length)
(h : xs.get n = xs.get m) (hne : n ≠ m) : ¬Nodup xs := by
rw [nodup_iff_injective_get]
exact fun hinj => hne (hinj h)
-
-set_option linter.deprecated false in
-@[deprecated not_nodup_of_get_eq_of_ne]
-theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.length)
- (hm : m < xs.length) (h : xs.nthLe n hn = xs.nthLe m hm) (hne : n ≠ m) : ¬Nodup xs := by
- rw [nodup_iff_nthLe_inj]
- simp only [exists_prop, exists_and_right, not_forall]
- exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
-#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
+#align list.nth_le_eq_of_ne_imp_not_nodup List.not_nodup_of_get_eq_of_ne
-- Porting note (#10756): new theorem
theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.length) :
@@ -469,7 +469,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) :
-- Porting note (#10756): new theorem
theorem Nodup.take_eq_filter_mem [DecidableEq α] :
- ∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (· ∈ l.take n)
+ ∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (l.take n).elem
| [], n, _ => by simp
| b::l, 0, _ => by simp
| b::l, n+1, hl => by
@@ -125,10 +125,10 @@ theorem nodup_iff_get?_ne_get? {l : List α} :
rw [Nodup, pairwise_iff_get]
constructor
· intro h i j hij hj
- rw [get?_eq_get (lt_trans hij hj), get?_eq_get hj, Ne.def, Option.some_inj]
+ rw [get?_eq_get (lt_trans hij hj), get?_eq_get hj, Ne, Option.some_inj]
exact h _ _ hij
· intro h i j hij
- rw [Ne.def, ← Option.some_inj, ← get?_eq_get, ← get?_eq_get]
+ rw [Ne, ← Option.some_inj, ← get?_eq_get, ← get?_eq_get]
exact h i j hij j.2
#align list.nodup_iff_nth_ne_nth List.nodup_iff_get?_ne_get?
@@ -139,7 +139,7 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
· specialize hl h.of_cons
by_cases hx : tl = [x]
· simpa [hx, and_comm, and_or_left] using h
- · rw [← Ne.def, hl] at hx
+ · rw [← Ne, hl] at hx
rcases hx with (rfl | ⟨y, hy, hx⟩)
· simp
· suffices ∃ y ∈ hd :: tl, y ≠ x by simpa [ne_nil_of_mem hy]
@@ -298,7 +298,7 @@ theorem Nodup.filter (p : α → Bool) {l} : Nodup l → Nodup (filter p l) := b
@[simp]
theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
- pairwise_reverse.trans <| by simp only [Nodup, Ne.def, eq_comm]
+ pairwise_reverse.trans <| by simp only [Nodup, Ne, eq_comm]
#align list.nodup_reverse List.nodup_reverse
theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
apply foo.mpr
by rw [foo]
(#11515)
Sometimes, that line can be golfed into the next line. Inspired by a comment of @loefflerd; any decisions are my own.
@@ -441,7 +441,7 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
(h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
- apply pairwise_iff_forall_sublist.mpr
+ rw [pairwise_iff_forall_sublist]
intro a b hab
if heq : a = b then
cases heq; have := nodup_iff_sublist.mp hl _ hab; contradiction
@@ -88,7 +88,7 @@ theorem nodup_iff_sublist {l : List α} : Nodup l ↔ ∀ a, ¬[a, a] <+ l :=
h a <| (singleton_sublist.2 al).cons_cons _⟩
#align list.nodup_iff_sublist List.nodup_iff_sublist
--- Porting note: new theorem
+-- Porting note (#10756): new theorem
theorem nodup_iff_injective_get {l : List α} :
Nodup l ↔ Function.Injective l.get :=
pairwise_iff_get.trans
@@ -160,7 +160,7 @@ theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.len
exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
--- Porting note: new theorem
+-- Porting note (#10756): new theorem
theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.length) :
indexOf (get l i) l = i :=
suffices (⟨indexOf (get l i) l, indexOf_lt_length.2 (get_mem _ _ _)⟩ : Fin l.length) = i
@@ -467,7 +467,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) :
forall₂_congr this]
#align list.nodup.pairwise_coe List.Nodup.pairwise_coe
--- Porting note: new theorem
+-- Porting note (#10756): new theorem
theorem Nodup.take_eq_filter_mem [DecidableEq α] :
∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (· ∈ l.take n)
| [], n, _ => by simp
Homogenises porting notes via capitalisation and addition of whitespace.
It makes the following changes:
@@ -88,7 +88,7 @@ theorem nodup_iff_sublist {l : List α} : Nodup l ↔ ∀ a, ¬[a, a] <+ l :=
h a <| (singleton_sublist.2 al).cons_cons _⟩
#align list.nodup_iff_sublist List.nodup_iff_sublist
---Porting note: new theorem
+-- Porting note: new theorem
theorem nodup_iff_injective_get {l : List α} :
Nodup l ↔ Function.Injective l.get :=
pairwise_iff_get.trans
@@ -160,7 +160,7 @@ theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.len
exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
---Porting note: new theorem
+-- Porting note: new theorem
theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.length) :
indexOf (get l i) l = i :=
suffices (⟨indexOf (get l i) l, indexOf_lt_length.2 (get_mem _ _ _)⟩ : Fin l.length) = i
@@ -283,7 +283,7 @@ alias ⟨Nodup.of_attach, Nodup.attach⟩ := nodup_attach
#align list.nodup.attach List.Nodup.attach
#align list.nodup.of_attach List.Nodup.of_attach
---Porting note: commented out
+-- Porting note: commented out
--attribute [protected] nodup.attach
theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H}
@@ -467,7 +467,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) :
forall₂_congr this]
#align list.nodup.pairwise_coe List.Nodup.pairwise_coe
---Porting note: new theorem
+-- Porting note: new theorem
theorem Nodup.take_eq_filter_mem [DecidableEq α] :
∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (· ∈ l.take n)
| [], n, _ => by simp
Fin.eq_of_veq
and Fin.veq_of_eq
(#10626)
We have Fin.eq_of_val_eq
and Fin.val_eq_of_eq
in Lean core now.
Also slightly shake the tree.
@@ -98,7 +98,7 @@ theorem nodup_iff_injective_get {l : List α} :
· exact (h ⟨i, hi⟩ ⟨j, hj⟩ hij hg).elim
· rfl
· exact (h ⟨j, hj⟩ ⟨i, hi⟩ hji hg.symm).elim,
- fun hinj i j hij h => Nat.ne_of_lt hij (Fin.veq_of_eq (hinj h))⟩
+ fun hinj i j hij h => Nat.ne_of_lt hij (Fin.val_eq_of_eq (hinj h))⟩
set_option linter.deprecated false in
@[deprecated nodup_iff_injective_get]
@@ -164,7 +164,7 @@ theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.len
theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.length) :
indexOf (get l i) l = i :=
suffices (⟨indexOf (get l i) l, indexOf_lt_length.2 (get_mem _ _ _)⟩ : Fin l.length) = i
- from Fin.veq_of_eq this
+ from Fin.val_eq_of_eq this
nodup_iff_injective_get.1 H (by simp)
set_option linter.deprecated false in
add (iterated) deriv for prod
HasFDerivAt
+ variants for Finset.prod
(and ContinuousMultilinearMap.mkPiAlgebra
)iteratedFDerivWithin
equivalents for zero, const (resolves a todo in Analysis.Calculus.ContDiff.Basic
)iteratedFDeriv[Within]_sum
for symmetrySym
and Finset.{prod,sum}
@@ -318,6 +318,21 @@ theorem Nodup.erase [DecidableEq α] (a : α) : Nodup l → Nodup (l.erase a) :=
Nodup.sublist <| erase_sublist _ _
#align list.nodup.erase List.Nodup.erase
+theorem Nodup.erase_get [DecidableEq α] {l : List α} (hl : l.Nodup) :
+ ∀ i : Fin l.length, l.erase (l.get i) = l.eraseIdx ↑i := by
+ induction l with
+ | nil => simp
+ | cons a l IH =>
+ intro i
+ cases i using Fin.cases with
+ | zero => simp
+ | succ i =>
+ rw [nodup_cons] at hl
+ rw [erase_cons_tail]
+ · simp [IH hl.2]
+ · rw [beq_iff_eq, get_cons_succ']
+ exact mt (· ▸ l.get_mem i i.isLt) hl.1
+
theorem Nodup.diff [DecidableEq α] : l₁.Nodup → (l₁.diff l₂).Nodup :=
Nodup.sublist <| diff_sublist _ _
#align list.nodup.diff List.Nodup.diff
@@ -310,7 +310,7 @@ theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
symm
rw [filter_eq_self]
simpa [@eq_comm α] using m
- · rw [erase_cons_tail _ h, filter_cons_of_pos, IH]
+ · rw [erase_cons_tail _ (not_beq_of_ne h), filter_cons_of_pos, IH]
simp [h]
#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
@@ -3,8 +3,6 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
-/
-import Mathlib.Data.List.Lattice
-import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.Forall2
import Mathlib.Data.Set.Pairwise.Basic
import Mathlib.Init.Data.Fin.Basic
∃ x ∈ s, _
instead of ∃ (x) (_ : x ∈ s), _
(#9184)
Search for [∀∃].*(_
and manually replace some occurrences with more readable versions.
In case of ∀
, the new expressions are defeq to the old ones.
In case of ∃
, they differ by exists_prop
.
In some rare cases, golf proofs that needed fixing.
@@ -144,7 +144,7 @@ theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
· rw [← Ne.def, hl] at hx
rcases hx with (rfl | ⟨y, hy, hx⟩)
· simp
- · suffices ∃ (y : α) (_ : y ∈ hd :: tl), y ≠ x by simpa [ne_nil_of_mem hy]
+ · suffices ∃ y ∈ hd :: tl, y ≠ x by simpa [ne_nil_of_mem hy]
exact ⟨y, mem_cons_of_mem _ hy, hx⟩
#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iff
Fin
(#8510)
Unique
should be available earlier than results about Fin n
, by virtue of being a very basic logic typeclass with no dependencies on Nat or algebra.
This also generalizes some of the moved instances and lemmas. There are no new declarations in this PR, only renames of existing ones.
@@ -7,6 +7,7 @@ import Mathlib.Data.List.Lattice
import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.Forall2
import Mathlib.Data.Set.Pairwise.Basic
+import Mathlib.Init.Data.Fin.Basic
#align_import data.list.nodup from "leanprover-community/mathlib"@"c227d107bbada5d0d9d20287e3282c0a7f1651a0"
@@ -182,6 +182,11 @@ theorem nodup_iff_count_le_one [DecidableEq α] {l : List α} : Nodup l ↔ ∀
(not_congr this).trans not_lt
#align list.nodup_iff_count_le_one List.nodup_iff_count_le_one
+theorem nodup_iff_count_eq_one [DecidableEq α] : Nodup l ↔ ∀ a ∈ l, count a l = 1 :=
+ nodup_iff_count_le_one.trans <| forall_congr' fun _ =>
+ ⟨fun H h => H.antisymm (count_pos_iff_mem.mpr h),
+ fun H => if h : _ then (H h).le else (count_eq_zero.mpr h).trans_le (Nat.zero_le 1)⟩
+
theorem nodup_replicate (a : α) : ∀ {n : ℕ}, Nodup (replicate n a) ↔ n ≤ 1
| 0 => by simp [Nat.zero_le]
| 1 => by simp
Std bump patch for https://github.com/leanprover/std4/pull/100
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -422,11 +422,13 @@ theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α
theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
(h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
- classical
- refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
- intro x hx
- rw [nodup_iff_count_le_one] at hl
- exact absurd (hl x) hx.not_le
+ apply pairwise_iff_forall_sublist.mpr
+ intro a b hab
+ if heq : a = b then
+ cases heq; have := nodup_iff_sublist.mp hl _ hab; contradiction
+ else
+ apply h <;> try (apply hab.subset; simp)
+ exact heq
#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
theorem Nodup.pairwise_of_set_pairwise {l : List α} {r : α → α → Prop} (hl : l.Nodup)
A linter that throws on seeing a colon at the start of a line, according to the style guideline that says these operators should go before linebreaks.
@@ -435,8 +435,8 @@ theorem Nodup.pairwise_of_set_pairwise {l : List α} {r : α → α → Prop} (h
#align list.nodup.pairwise_of_set_pairwise List.Nodup.pairwise_of_set_pairwise
@[simp]
-theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup)
- : { a | a ∈ l }.Pairwise r ↔ l.Pairwise r := by
+theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) :
+ { a | a ∈ l }.Pairwise r ↔ l.Pairwise r := by
induction' l with a l ih
· simp
rw [List.nodup_cons] at hl
@@ -275,7 +275,7 @@ theorem nodup_attach {l : List α} : Nodup (attach l) ↔ Nodup l :=
Nodup.of_map Subtype.val ((attach_map_val l).symm ▸ h)⟩
#align list.nodup_attach List.nodup_attach
-alias nodup_attach ↔ Nodup.of_attach Nodup.attach
+alias ⟨Nodup.of_attach, Nodup.attach⟩ := nodup_attach
#align list.nodup.attach List.Nodup.attach
#align list.nodup.of_attach List.Nodup.of_attach
This incorporates changes from https://github.com/leanprover-community/mathlib4/pull/6575
I have also renamed Multiset.countp
to Multiset.countP
for consistency.
Co-authored-by: James Gallichio <jamesgallicchio@gmail.com>
Co-authored-by: James <jamesgallicchio@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -178,7 +178,7 @@ theorem nthLe_index_of [DecidableEq α] {l : List α} (H : Nodup l) (n h) :
theorem nodup_iff_count_le_one [DecidableEq α] {l : List α} : Nodup l ↔ ∀ a, count a l ≤ 1 :=
nodup_iff_sublist.trans <|
forall_congr' fun a =>
- have : [a, a] <+ l ↔ 1 < count a l := (@le_count_iff_replicate_sublist _ _ _ 2 _).symm
+ have : replicate 2 a <+ l ↔ 1 < count a l := (le_count_iff_replicate_sublist ..).symm
(not_congr this).trans not_lt
#align list.nodup_iff_count_le_one List.nodup_iff_count_le_one
@@ -194,7 +194,7 @@ theorem nodup_replicate (a : α) : ∀ {n : ℕ}, Nodup (replicate n a) ↔ n
@[simp]
theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l) (h : a ∈ l) :
count a l = 1 :=
- _root_.le_antisymm (nodup_iff_count_le_one.1 d a) (Nat.succ_le_of_lt (count_pos.2 h))
+ _root_.le_antisymm (nodup_iff_count_le_one.1 d a) (Nat.succ_le_of_lt (count_pos_iff_mem.2 h))
#align list.count_eq_one_of_mem List.count_eq_one_of_mem
theorem count_eq_of_nodup [DecidableEq α] {a : α} {l : List α} (d : Nodup l) :
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -350,7 +350,7 @@ protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l
exact n rfl⟩
#align list.nodup.product List.Nodup.product
-theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a , List (σ a)} (d₁ : Nodup l₁)
+theorem Nodup.sigma {σ : α → Type*} {l₂ : ∀ a , List (σ a)} (d₁ : Nodup l₁)
(d₂ : ∀ a , Nodup (l₂ a)) : (l₁.sigma l₂).Nodup :=
nodup_bind.2
⟨fun a _ => (d₂ a).map fun b b' h => by injection h with _ h,
protected
to *.insert
theorems (#6142)
Otherwise code like
theorem ContMDiffWithinAt.mythm (h : x ∈ insert y s) : _ = _
interprets insert
as ContMDiffWithinAt.insert
, not Insert.insert
.
@@ -369,7 +369,7 @@ protected theorem Nodup.concat (h : a ∉ l) (h' : l.Nodup) : (l.concat a).Nodup
rw [concat_eq_append]; exact h'.append (nodup_singleton _) (disjoint_singleton.2 h)
#align list.nodup.concat List.Nodup.concat
-theorem Nodup.insert [DecidableEq α] (h : l.Nodup) : (l.insert a).Nodup :=
+protected theorem Nodup.insert [DecidableEq α] (h : l.Nodup) : (l.insert a).Nodup :=
if h' : a ∈ l then by rw [insert_of_mem h']; exact h
else by rw [insert_of_not_mem h', nodup_cons]; constructor <;> assumption
#align list.nodup.insert List.Nodup.insert
@@ -448,7 +448,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup)
--Porting note: new theorem
theorem Nodup.take_eq_filter_mem [DecidableEq α] :
- ∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (. ∈ l.take n)
+ ∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (· ∈ l.take n)
| [], n, _ => by simp
| b::l, 0, _ => by simp
| b::l, n+1, hl => by
@@ -2,17 +2,14 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
-
-! This file was ported from Lean 3 source module data.list.nodup
-! leanprover-community/mathlib commit c227d107bbada5d0d9d20287e3282c0a7f1651a0
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Data.List.Lattice
import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.Forall2
import Mathlib.Data.Set.Pairwise.Basic
+#align_import data.list.nodup from "leanprover-community/mathlib"@"c227d107bbada5d0d9d20287e3282c0a7f1651a0"
+
/-!
# Lists with no duplicates
This PR is the result of running
find . -type f -name "*.lean" -exec sed -i -E 's/^( +)\. /\1· /' {} \;
find . -type f -name "*.lean" -exec sed -i -E 'N;s/^( +·)\n +(.*)$/\1 \2/;P;D' {} \;
which firstly replaces .
focusing dots with ·
and secondly removes isolated instances of such dots, unifying them with the following line. A new rule is placed in the style linter to verify this.
@@ -99,9 +99,9 @@ theorem nodup_iff_injective_get {l : List α} :
⟨fun h i j hg => by
cases' i with i hi; cases' j with j hj
rcases lt_trichotomy i j with (hij | rfl | hji)
- . exact (h ⟨i, hi⟩ ⟨j, hj⟩ hij hg).elim
- . rfl
- . exact (h ⟨j, hj⟩ ⟨i, hi⟩ hji hg.symm).elim,
+ · exact (h ⟨i, hi⟩ ⟨j, hj⟩ hij hg).elim
+ · rfl
+ · exact (h ⟨j, hj⟩ ⟨i, hi⟩ hji hg.symm).elim,
fun hinj i j hij h => Nat.ne_of_lt hij (Fin.veq_of_eq (hinj h))⟩
set_option linter.deprecated false in
@@ -128,10 +128,10 @@ theorem nodup_iff_get?_ne_get? {l : List α} :
l.Nodup ↔ ∀ i j : ℕ, i < j → j < l.length → l.get? i ≠ l.get? j := by
rw [Nodup, pairwise_iff_get]
constructor
- . intro h i j hij hj
+ · intro h i j hij hj
rw [get?_eq_get (lt_trans hij hj), get?_eq_get hj, Ne.def, Option.some_inj]
exact h _ _ hij
- . intro h i j hij
+ · intro h i j hij
rw [Ne.def, ← Option.some_inj, ← get?_eq_get, ← get?_eq_get]
exact h i j hij j.2
#align list.nodup_iff_nth_ne_nth List.nodup_iff_get?_ne_get?
SProd
to implement overloaded notation · ×ˢ ·
(#4200)
Currently, the following notations are changed from · ×ˢ ·
because Lean 4 can't deal with ambiguous notations.
| Definition | Notation |
| :
Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
@@ -344,7 +344,7 @@ theorem nodup_bind {l₁ : List α} {f : α → List β} :
#align list.nodup_bind List.nodup_bind
protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l₂.Nodup) :
- (l₁.product l₂).Nodup :=
+ (l₁ ×ˢ l₂).Nodup :=
nodup_bind.2
⟨fun a _ => d₂.map <| LeftInverse.injective fun b => (rfl : (a, b).2 = b),
d₁.imp fun {a₁ a₂} n x h₁ h₂ => by
by
s! (#3825)
This PR puts, with one exception, every single remaining by
that lies all by itself on its own line to the previous line, thus matching the current behaviour of start-port.sh
. The exception is when the by
begins the second or later argument to a tuple or anonymous constructor; see https://github.com/leanprover-community/mathlib4/pull/3825#discussion_r1186702599.
Essentially this is s/\n *by$/ by/g
, but with manual editing to satisfy the linter's max-100-char-line requirement. The Python style linter is also modified to catch these "isolated by
s".
@@ -87,9 +87,8 @@ theorem not_nodup_pair (a : α) : ¬Nodup [a, a] :=
theorem nodup_iff_sublist {l : List α} : Nodup l ↔ ∀ a, ¬[a, a] <+ l :=
⟨fun d a h => not_nodup_pair a (d.sublist h),
by
- induction' l with a l IH <;> intro h; · exact nodup_nil
- exact
- (IH fun a s => h a <| sublist_cons_of_sublist _ s).cons fun al =>
+ induction' l with a l IH <;> intro h; · exact nodup_nil
+ exact (IH fun a s => h a <| sublist_cons_of_sublist _ s).cons fun al =>
h a <| (singleton_sublist.2 al).cons_cons _⟩
#align list.nodup_iff_sublist List.nodup_iff_sublist
data.set.pairwise
(#3117)
Match https://github.com/leanprover-community/mathlib/pull/17880
The new import of Mathlib.Data.Set.Lattice
in Mathlib.Data.Finset.Basic
was implied transitively from tactic imports present in Lean 3.
Co-authored-by: Parcly Taxel <reddeloostw@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Jeremy Tan Jie Rui <reddeloostw@gmail.com>
@@ -4,14 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
! This file was ported from Lean 3 source module data.list.nodup
-! leanprover-community/mathlib commit f694c7dead66f5d4c80f446c796a5aad14707f0e
+! leanprover-community/mathlib commit c227d107bbada5d0d9d20287e3282c0a7f1651a0
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.List.Lattice
import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.Forall2
-import Mathlib.Data.Set.Pairwise
+import Mathlib.Data.Set.Pairwise.Basic
/-!
# Lists with no duplicates
Notably incorporates https://github.com/leanprover/std4/pull/98 and https://github.com/leanprover/std4/pull/109.
https://github.com/leanprover/std4/pull/98 moves a number of lemmas from Mathlib to Std, so the bump requires deleting them in Mathlib. I did check on each lemma whether its attributes were kept in the move (and gave attribute markings in Mathlib if they were not present in Std), but a reviewer may wish to re-check.
List.mem_map
changed statement from b ∈ l.map f ↔ ∃ a, a ∈ l ∧ b = f a
to b ∈ l.map f ↔ ∃ a, a ∈ l ∧ f a = b
. Similarly for List.exists_of_mem_map
. This was a deliberate change, so I have simply adjusted proofs (many become simpler, which supports the change). I also deleted List.mem_map'
, List.exists_of_mem_map'
, which were temporary versions in Mathlib while waiting for this change (replacing their uses with the unprimed versions).
Also, the lemma sublist_nil_iff_eq_nil
seems to have been renamed to sublist_nil
during the move, so I added an alias for the old name.
(another issue fixed during review by @digama0) List.Sublist.filter
had an argument change from explicit to implicit. This appears to have been an oversight (cc @JamesGallicchio). I have temporarily introduced List.Sublist.filter'
with the argument explicit, and replaced Mathlib uses of Sublist.filter
with Sublist.filter'
. Later we can fix the argument in Std, and then delete List.Sublist.filter'
.
@@ -255,8 +255,8 @@ theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : Nodup (map f l))
simp only [mem_cons]
rintro _ (rfl | h₁) _ (rfl | h₂) h₃
· rfl
- · apply (d.1 _ h₂ h₃).elim
- · apply (d.1 _ h₁ h₃.symm).elim
+ · apply (d.1 _ h₂ h₃.symm).elim
+ · apply (d.1 _ h₁ h₃).elim
· apply ih d.2 h₁ h₂ h₃
#align list.inj_on_of_nodup_map List.inj_on_of_nodup_map
@@ -340,8 +340,8 @@ theorem nodup_bind {l₁ : List α} {f : α → List β} :
(∀ x ∈ l₁, Nodup (f x)) ∧ Pairwise (fun a b : α => Disjoint (f a) (f b)) l₁ := by
simp only [List.bind, nodup_join, pairwise_map, and_comm, and_left_comm, mem_map, exists_imp,
and_imp]
- rw [show (∀ (l : List β) (x : α), l = f x → x ∈ l₁ → Nodup l) ↔ ∀ x : α, x ∈ l₁ → Nodup (f x)
- from forall_swap.trans <| forall_congr' fun _ => forall_eq]
+ rw [show (∀ (l : List β) (x : α), f x = l → x ∈ l₁ → Nodup l) ↔ ∀ x : α, x ∈ l₁ → Nodup (f x)
+ from forall_swap.trans <| forall_congr' fun _ => forall_eq']
#align list.nodup_bind List.nodup_bind
protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l₂.Nodup) :
@@ -304,7 +304,7 @@ theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
l.erase a = l.filter (· ≠ a) := by
induction' d with b l m _ IH; · rfl
- by_cases b = a
+ by_cases h : b = a
· subst h
rw [erase_cons_head, filter_cons_of_neg _ (by simp)]
symm
Part of the List.repeat
-> List.replicate
refactor. On Mathlib 4 side, I removed mentions of List.repeat
in #1475 and #1579
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
! This file was ported from Lean 3 source module data.list.nodup
-! leanprover-community/mathlib commit dd71334db81d0bd444af1ee339a29298bef40734
+! leanprover-community/mathlib commit f694c7dead66f5d4c80f446c796a5aad14707f0e
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -288,8 +288,8 @@ alias nodup_attach ↔ Nodup.of_attach Nodup.attach
theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H}
(hf : ∀ a ha b hb, f a ha = f b hb → a = b) (h : Nodup l) : Nodup (pmap f l H) := by
- rw [pmap_eq_map_attach];
- exact h.attach.map fun ⟨a, ha⟩ ⟨b, hb⟩ h => by congr; exact hf a (H _ ha) b (H _ hb) h
+ rw [pmap_eq_map_attach]
+ exact h.attach.map fun ⟨a, ha⟩ ⟨b, hb⟩ h => by congr; exact hf a (H _ ha) b (H _ hb) h
#align list.nodup.pmap List.Nodup.pmap
theorem Nodup.filter (p : α → Bool) {l} : Nodup l → Nodup (filter p l) := by
@@ -306,11 +306,10 @@ theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
induction' d with b l m _ IH; · rfl
by_cases b = a
· subst h
- rw [erase_cons_head, filter_cons_of_neg]
+ rw [erase_cons_head, filter_cons_of_neg _ (by simp)]
symm
rw [filter_eq_self]
simpa [@eq_comm α] using m
- simp
· rw [erase_cons_tail _ h, filter_cons_of_pos, IH]
simp [h]
#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
@@ -349,7 +348,7 @@ protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l
(l₁.product l₂).Nodup :=
nodup_bind.2
⟨fun a _ => d₂.map <| LeftInverse.injective fun b => (rfl : (a, b).2 = b),
- d₁.imp @fun a₁ a₂ n x h₁ h₂ => by
+ d₁.imp fun {a₁ a₂} n x h₁ h₂ => by
rcases mem_map.1 h₁ with ⟨b₁, _, rfl⟩
rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩
exact n rfl⟩
@@ -359,7 +358,7 @@ theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a , List (σ a)} (d₁ : No
(d₂ : ∀ a , Nodup (l₂ a)) : (l₁.sigma l₂).Nodup :=
nodup_bind.2
⟨fun a _ => (d₂ a).map fun b b' h => by injection h with _ h,
- d₁.imp @fun a₁ a₂ n x h₁ h₂ => by
+ d₁.imp fun {a₁ a₂} n x h₁ h₂ => by
rcases mem_map.1 h₁ with ⟨b₁, _, rfl⟩
rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩
exact n rfl⟩
@@ -457,13 +456,12 @@ theorem Nodup.take_eq_filter_mem [DecidableEq α] :
| [], n, _ => by simp
| b::l, 0, _ => by simp
| b::l, n+1, hl => by
- rw [take_cons, Nodup.take_eq_filter_mem (Nodup.of_cons hl), List.filter_cons_of_pos]
+ rw [take_cons, Nodup.take_eq_filter_mem (Nodup.of_cons hl), List.filter_cons_of_pos _ (by simp)]
congr 1
refine' List.filter_congr' _
intro x hx
have : x ≠ b := fun h => (nodup_cons.1 hl).1 (h ▸ hx)
simp (config := {contextual := true}) [List.mem_filter, this, hx]
- simp
end List
theorem Option.toList_nodup {α} : ∀ o : Option α, o.toList.Nodup
This PR is the result of a slight variant on the following "algorithm"
_
and make all uppercase letters into lowercase_
and make all uppercase letters into lowercase(original_lean3_name, OriginalLean4Name)
#align
statement just before the next empty line#align
statement to have been inserted too early)@@ -280,6 +280,8 @@ theorem nodup_attach {l : List α} : Nodup (attach l) ↔ Nodup l :=
#align list.nodup_attach List.nodup_attach
alias nodup_attach ↔ Nodup.of_attach Nodup.attach
+#align list.nodup.attach List.Nodup.attach
+#align list.nodup.of_attach List.Nodup.of_attach
--Porting note: commented out
--attribute [protected] nodup.attach
This was done semi-automatically with some regular expressions in vim in contrast to the fully automatic https://github.com/leanprover-community/mathlib4/pull/1523.
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -438,8 +438,8 @@ theorem Nodup.pairwise_of_set_pairwise {l : List α} {r : α → α → Prop} (h
#align list.nodup.pairwise_of_set_pairwise List.Nodup.pairwise_of_set_pairwise
@[simp]
-theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : { a | a ∈ l }.Pairwise r ↔ l.Pairwise r :=
- by
+theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup)
+ : { a | a ∈ l }.Pairwise r ↔ l.Pairwise r := by
induction' l with a l ih
· simp
rw [List.nodup_cons] at hl
by
line breaks (#1523)
During porting, I usually fix the desired format we seem to want for the line breaks around by
with
awk '{do {{if (match($0, "^ by$") && length(p) < 98) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}' Mathlib/File/Im/Working/On.lean
I noticed there are some more files that slipped through.
This pull request is the result of running this command:
grep -lr "^ by\$" Mathlib | xargs -n 1 awk -i inplace '{do {{if (match($0, "^ by$") && length(p) < 98 && not (match(p, "^[ \t]*--"))) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}'
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -202,8 +202,7 @@ theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l
#align list.count_eq_one_of_mem List.count_eq_one_of_mem
theorem count_eq_of_nodup [DecidableEq α] {a : α} {l : List α} (d : Nodup l) :
- count a l = if a ∈ l then 1 else 0 :=
- by
+ count a l = if a ∈ l then 1 else 0 := by
split_ifs with h
· exact count_eq_one_of_mem d h
· exact count_eq_zero_of_not_mem h
@@ -249,8 +248,7 @@ theorem Nodup.map_on {f : α → β} (H : ∀ x ∈ l, ∀ y ∈ l, f x = f y
#align list.nodup.map_on List.Nodup.map_onₓ -- Porting note: different universe order
theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : Nodup (map f l)) :
- ∀ ⦃x⦄, x ∈ l → ∀ ⦃y⦄, y ∈ l → f x = f y → x = y :=
- by
+ ∀ ⦃x⦄, x ∈ l → ∀ ⦃y⦄, y ∈ l → f x = f y → x = y := by
induction' l with hd tl ih
· simp
· simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
@@ -302,8 +300,7 @@ theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
#align list.nodup_reverse List.nodup_reverse
theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
- l.erase a = l.filter (· ≠ a) :=
- by
+ l.erase a = l.filter (· ≠ a) := by
induction' d with b l m _ IH; · rfl
by_cases b = a
· subst h
@@ -380,8 +377,7 @@ theorem Nodup.insert [DecidableEq α] (h : l.Nodup) : (l.insert a).Nodup :=
else by rw [insert_of_not_mem h', nodup_cons]; constructor <;> assumption
#align list.nodup.insert List.Nodup.insert
-theorem Nodup.union [DecidableEq α] (l₁ : List α) (h : Nodup l₂) : (l₁ ∪ l₂).Nodup :=
- by
+theorem Nodup.union [DecidableEq α] (l₁ : List α) (h : Nodup l₂) : (l₁ ∪ l₂).Nodup := by
induction' l₁ with a l₁ ih generalizing l₂
· exact h
· exact (ih h).insert
List.repeat
(#1579)
Mathlib 3 migrated to list.replicate
in leanprover-community/mathlib#18127 (merged) and leanprover-community/mathlib#18181 (awaiting review).
@@ -193,11 +193,7 @@ theorem nodup_replicate (a : α) : ∀ {n : ℕ}, Nodup (replicate n a) ↔ n
iff_of_false
(fun H => nodup_iff_sublist.1 H a ((replicate_sublist_replicate _).2 (Nat.le_add_left 2 n)))
(not_le_of_lt <| Nat.le_add_left 2 n)
-
-set_option linter.deprecated false in
-theorem nodup_repeat (a : α) : ∀ {n : ℕ}, Nodup (List.repeat a n) ↔ n ≤ 1 :=
- nodup_replicate a
-#align list.nodup_repeat List.nodup_repeat
+#align list.nodup_replicate List.nodup_replicate
@[simp]
theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l) (h : a ∈ l) :
@@ -457,6 +457,19 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : { a | a ∈ l }.Pairwi
forall₂_congr this]
#align list.nodup.pairwise_coe List.Nodup.pairwise_coe
+--Porting note: new theorem
+theorem Nodup.take_eq_filter_mem [DecidableEq α] :
+ ∀ {l : List α} {n : ℕ} (_ : l.Nodup), l.take n = l.filter (. ∈ l.take n)
+ | [], n, _ => by simp
+ | b::l, 0, _ => by simp
+ | b::l, n+1, hl => by
+ rw [take_cons, Nodup.take_eq_filter_mem (Nodup.of_cons hl), List.filter_cons_of_pos]
+ congr 1
+ refine' List.filter_congr' _
+ intro x hx
+ have : x ≠ b := fun h => (nodup_cons.1 hl).1 (h ▸ hx)
+ simp (config := {contextual := true}) [List.mem_filter, this, hx]
+ simp
end List
theorem Option.toList_nodup {α} : ∀ o : Option α, o.toList.Nodup
@@ -2,43 +2,464 @@
Copyright (c) 2018 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kenny Lau
+
+! This file was ported from Lean 3 source module data.list.nodup
+! leanprover-community/mathlib commit dd71334db81d0bd444af1ee339a29298bef40734
+! Please do not edit these lines, except to modify the commit id
+! if you have ported upstream changes.
-/
+import Mathlib.Data.List.Lattice
import Mathlib.Data.List.Pairwise
+import Mathlib.Data.List.Forall2
+import Mathlib.Data.Set.Pairwise
/-!
# Lists with no duplicates
-`List.Nodup` is defined in `Std.Data.List.Basic`. In this file we prove various properties of this
+`List.Nodup` is defined in `Data/List/Basic`. In this file we prove various properties of this
predicate.
-/
-open Function
+
+universe u v
+
+open Nat Function
+
+variable {α : Type u} {β : Type v} {l l₁ l₂ : List α} {r : α → α → Prop} {a b : α}
namespace List
+@[simp]
+theorem forall_mem_ne {a : α} {l : List α} : (∀ a' : α, a' ∈ l → ¬a = a') ↔ a ∉ l :=
+ ⟨fun h m => h _ m rfl, fun h _ m e => h (e.symm ▸ m)⟩
+#align list.forall_mem_ne List.forall_mem_ne
+
+@[simp]
+theorem nodup_nil : @Nodup α [] :=
+ Pairwise.nil
+#align list.nodup_nil List.nodup_nil
+
+@[simp]
+theorem nodup_cons {a : α} {l : List α} : Nodup (a :: l) ↔ a ∉ l ∧ Nodup l := by
+ simp only [Nodup, pairwise_cons, forall_mem_ne]
+#align list.nodup_cons List.nodup_cons
+
+protected theorem Pairwise.nodup {l : List α} {r : α → α → Prop} [IsIrrefl α r] (h : Pairwise r l) :
+ Nodup l :=
+ h.imp ne_of_irrefl
+#align list.pairwise.nodup List.Pairwise.nodup
+
+theorem rel_nodup {r : α → β → Prop} (hr : Relator.BiUnique r) : (Forall₂ r ⇒ (· ↔ ·)) Nodup Nodup
+ | _, _, Forall₂.nil => by simp only [nodup_nil]
+ | _, _, Forall₂.cons hab h => by
+ simpa only [nodup_cons] using
+ Relator.rel_and (Relator.rel_not (rel_mem hr hab h)) (rel_nodup hr h)
+#align list.rel_nodup List.rel_nodup
+
+protected theorem Nodup.cons (ha : a ∉ l) (hl : Nodup l) : Nodup (a :: l) :=
+ nodup_cons.2 ⟨ha, hl⟩
+#align list.nodup.cons List.Nodup.cons
+
+theorem nodup_singleton (a : α) : Nodup [a] :=
+ pairwise_singleton _ _
+#align list.nodup_singleton List.nodup_singleton
+
+theorem Nodup.of_cons (h : Nodup (a :: l)) : Nodup l :=
+ (nodup_cons.1 h).2
+#align list.nodup.of_cons List.Nodup.of_cons
+
+theorem Nodup.not_mem (h : (a :: l).Nodup) : a ∉ l :=
+ (nodup_cons.1 h).1
+#align list.nodup.not_mem List.Nodup.not_mem
+
+theorem not_nodup_cons_of_mem : a ∈ l → ¬Nodup (a :: l) :=
+ imp_not_comm.1 Nodup.not_mem
+#align list.not_nodup_cons_of_mem List.not_nodup_cons_of_mem
+
+protected theorem Nodup.sublist : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
+ Pairwise.sublist
+#align list.nodup.sublist List.Nodup.sublist
+
+theorem not_nodup_pair (a : α) : ¬Nodup [a, a] :=
+ not_nodup_cons_of_mem <| mem_singleton_self _
+#align list.not_nodup_pair List.not_nodup_pair
+
+theorem nodup_iff_sublist {l : List α} : Nodup l ↔ ∀ a, ¬[a, a] <+ l :=
+ ⟨fun d a h => not_nodup_pair a (d.sublist h),
+ by
+ induction' l with a l IH <;> intro h; · exact nodup_nil
+ exact
+ (IH fun a s => h a <| sublist_cons_of_sublist _ s).cons fun al =>
+ h a <| (singleton_sublist.2 al).cons_cons _⟩
+#align list.nodup_iff_sublist List.nodup_iff_sublist
+
+--Porting note: new theorem
+theorem nodup_iff_injective_get {l : List α} :
+ Nodup l ↔ Function.Injective l.get :=
+ pairwise_iff_get.trans
+ ⟨fun h i j hg => by
+ cases' i with i hi; cases' j with j hj
+ rcases lt_trichotomy i j with (hij | rfl | hji)
+ . exact (h ⟨i, hi⟩ ⟨j, hj⟩ hij hg).elim
+ . rfl
+ . exact (h ⟨j, hj⟩ ⟨i, hi⟩ hji hg.symm).elim,
+ fun hinj i j hij h => Nat.ne_of_lt hij (Fin.veq_of_eq (hinj h))⟩
+
+set_option linter.deprecated false in
+@[deprecated nodup_iff_injective_get]
+theorem nodup_iff_nthLe_inj {l : List α} :
+ Nodup l ↔ ∀ i j h₁ h₂, nthLe l i h₁ = nthLe l j h₂ → i = j :=
+ nodup_iff_injective_get.trans
+ ⟨fun hinj _ _ _ _ h => congr_arg Fin.val (hinj h),
+ fun hinj i j h => Fin.eq_of_veq (hinj i j i.2 j.2 h)⟩
+#align list.nodup_iff_nth_le_inj List.nodup_iff_nthLe_inj
+
+theorem Nodup.get_inj_iff {l : List α} (h : Nodup l) {i j : Fin l.length} :
+ l.get i = l.get j ↔ i = j :=
+ (nodup_iff_injective_get.1 h).eq_iff
+
+set_option linter.deprecated false in
+@[deprecated Nodup.get_inj_iff]
+theorem Nodup.nthLe_inj_iff {l : List α} (h : Nodup l) {i j : ℕ} (hi : i < l.length)
+ (hj : j < l.length) : l.nthLe i hi = l.nthLe j hj ↔ i = j :=
+ ⟨nodup_iff_nthLe_inj.mp h _ _ _ _, by simp (config := { contextual := true })⟩
+#align list.nodup.nth_le_inj_iff List.Nodup.nthLe_inj_iff
+
+theorem nodup_iff_get?_ne_get? {l : List α} :
+ l.Nodup ↔ ∀ i j : ℕ, i < j → j < l.length → l.get? i ≠ l.get? j := by
+ rw [Nodup, pairwise_iff_get]
+ constructor
+ . intro h i j hij hj
+ rw [get?_eq_get (lt_trans hij hj), get?_eq_get hj, Ne.def, Option.some_inj]
+ exact h _ _ hij
+ . intro h i j hij
+ rw [Ne.def, ← Option.some_inj, ← get?_eq_get, ← get?_eq_get]
+ exact h i j hij j.2
+#align list.nodup_iff_nth_ne_nth List.nodup_iff_get?_ne_get?
+
+theorem Nodup.ne_singleton_iff {l : List α} (h : Nodup l) (x : α) :
+ l ≠ [x] ↔ l = [] ∨ ∃ y ∈ l, y ≠ x := by
+ induction' l with hd tl hl
+ · simp
+ · specialize hl h.of_cons
+ by_cases hx : tl = [x]
+ · simpa [hx, and_comm, and_or_left] using h
+ · rw [← Ne.def, hl] at hx
+ rcases hx with (rfl | ⟨y, hy, hx⟩)
+ · simp
+ · suffices ∃ (y : α) (_ : y ∈ hd :: tl), y ≠ x by simpa [ne_nil_of_mem hy]
+ exact ⟨y, mem_cons_of_mem _ hy, hx⟩
+#align list.nodup.ne_singleton_iff List.Nodup.ne_singleton_iff
+
+theorem not_nodup_of_get_eq_of_ne (xs : List α) (n m : Fin xs.length)
+ (h : xs.get n = xs.get m) (hne : n ≠ m) : ¬Nodup xs := by
+ rw [nodup_iff_injective_get]
+ exact fun hinj => hne (hinj h)
+
+set_option linter.deprecated false in
+@[deprecated not_nodup_of_get_eq_of_ne]
+theorem nthLe_eq_of_ne_imp_not_nodup (xs : List α) (n m : ℕ) (hn : n < xs.length)
+ (hm : m < xs.length) (h : xs.nthLe n hn = xs.nthLe m hm) (hne : n ≠ m) : ¬Nodup xs := by
+ rw [nodup_iff_nthLe_inj]
+ simp only [exists_prop, exists_and_right, not_forall]
+ exact ⟨n, m, ⟨hn, hm, h⟩, hne⟩
+#align list.nth_le_eq_of_ne_imp_not_nodup List.nthLe_eq_of_ne_imp_not_nodup
+
+--Porting note: new theorem
+theorem get_indexOf [DecidableEq α] {l : List α} (H : Nodup l) (i : Fin l.length) :
+ indexOf (get l i) l = i :=
+ suffices (⟨indexOf (get l i) l, indexOf_lt_length.2 (get_mem _ _ _)⟩ : Fin l.length) = i
+ from Fin.veq_of_eq this
+ nodup_iff_injective_get.1 H (by simp)
+
+set_option linter.deprecated false in
+@[simp, deprecated get_indexOf]
+theorem nthLe_index_of [DecidableEq α] {l : List α} (H : Nodup l) (n h) :
+ indexOf (nthLe l n h) l = n :=
+ nodup_iff_nthLe_inj.1 H _ _ _ h <| indexOf_nthLe <| indexOf_lt_length.2 <| nthLe_mem _ _ _
+#align list.nth_le_index_of List.nthLe_index_of
+
+theorem nodup_iff_count_le_one [DecidableEq α] {l : List α} : Nodup l ↔ ∀ a, count a l ≤ 1 :=
+ nodup_iff_sublist.trans <|
+ forall_congr' fun a =>
+ have : [a, a] <+ l ↔ 1 < count a l := (@le_count_iff_replicate_sublist _ _ _ 2 _).symm
+ (not_congr this).trans not_lt
+#align list.nodup_iff_count_le_one List.nodup_iff_count_le_one
+
+theorem nodup_replicate (a : α) : ∀ {n : ℕ}, Nodup (replicate n a) ↔ n ≤ 1
+ | 0 => by simp [Nat.zero_le]
+ | 1 => by simp
+ | n + 2 =>
+ iff_of_false
+ (fun H => nodup_iff_sublist.1 H a ((replicate_sublist_replicate _).2 (Nat.le_add_left 2 n)))
+ (not_le_of_lt <| Nat.le_add_left 2 n)
+
+set_option linter.deprecated false in
+theorem nodup_repeat (a : α) : ∀ {n : ℕ}, Nodup (List.repeat a n) ↔ n ≤ 1 :=
+ nodup_replicate a
+#align list.nodup_repeat List.nodup_repeat
+
+@[simp]
+theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l) (h : a ∈ l) :
+ count a l = 1 :=
+ _root_.le_antisymm (nodup_iff_count_le_one.1 d a) (Nat.succ_le_of_lt (count_pos.2 h))
+#align list.count_eq_one_of_mem List.count_eq_one_of_mem
+
+theorem count_eq_of_nodup [DecidableEq α] {a : α} {l : List α} (d : Nodup l) :
+ count a l = if a ∈ l then 1 else 0 :=
+ by
+ split_ifs with h
+ · exact count_eq_one_of_mem d h
+ · exact count_eq_zero_of_not_mem h
+#align list.count_eq_of_nodup List.count_eq_of_nodup
+
+theorem Nodup.of_append_left : Nodup (l₁ ++ l₂) → Nodup l₁ :=
+ Nodup.sublist (sublist_append_left l₁ l₂)
+#align list.nodup.of_append_left List.Nodup.of_append_left
+
+theorem Nodup.of_append_right : Nodup (l₁ ++ l₂) → Nodup l₂ :=
+ Nodup.sublist (sublist_append_right l₁ l₂)
+#align list.nodup.of_append_right List.Nodup.of_append_right
+
+theorem nodup_append {l₁ l₂ : List α} : Nodup (l₁ ++ l₂) ↔ Nodup l₁ ∧ Nodup l₂ ∧ Disjoint l₁ l₂ :=
+ by simp only [Nodup, pairwise_append, disjoint_iff_ne]
+#align list.nodup_append List.nodup_append
+
+theorem disjoint_of_nodup_append {l₁ l₂ : List α} (d : Nodup (l₁ ++ l₂)) : Disjoint l₁ l₂ :=
+ (nodup_append.1 d).2.2
+#align list.disjoint_of_nodup_append List.disjoint_of_nodup_append
+
+theorem Nodup.append (d₁ : Nodup l₁) (d₂ : Nodup l₂) (dj : Disjoint l₁ l₂) : Nodup (l₁ ++ l₂) :=
+ nodup_append.2 ⟨d₁, d₂, dj⟩
+#align list.nodup.append List.Nodup.append
+
+theorem nodup_append_comm {l₁ l₂ : List α} : Nodup (l₁ ++ l₂) ↔ Nodup (l₂ ++ l₁) := by
+ simp only [nodup_append, and_left_comm, disjoint_comm]
+#align list.nodup_append_comm List.nodup_append_comm
+
+theorem nodup_middle {a : α} {l₁ l₂ : List α} :
+ Nodup (l₁ ++ a :: l₂) ↔ Nodup (a :: (l₁ ++ l₂)) := by
+ simp only [nodup_append, not_or, and_left_comm, and_assoc, nodup_cons, mem_append,
+ disjoint_cons_right]
+#align list.nodup_middle List.nodup_middle
+
+theorem Nodup.of_map (f : α → β) {l : List α} : Nodup (map f l) → Nodup l :=
+ (Pairwise.of_map f) fun _ _ => mt <| congr_arg f
+#align list.nodup.of_map List.Nodup.of_mapₓ -- Porting note: different universe order
+
theorem Nodup.map_on {f : α → β} (H : ∀ x ∈ l, ∀ y ∈ l, f x = f y → x = y) (d : Nodup l) :
(map f l).Nodup :=
- Pairwise.map _ (fun a b ⟨ma, mb, n⟩ e ↦ n (H a ma b mb e)) (Pairwise.and_mem.1 d)
+ Pairwise.map _ (fun a b ⟨ma, mb, n⟩ e => n (H a ma b mb e)) (Pairwise.and_mem.1 d)
+#align list.nodup.map_on List.Nodup.map_onₓ -- Porting note: different universe order
-protected theorem Nodup.map {f : α → β} (hf : Function.Injective f) : Nodup l → Nodup (map f l) :=
- Nodup.map_on fun _ _ _ _ h ↦ hf h
+theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : Nodup (map f l)) :
+ ∀ ⦃x⦄, x ∈ l → ∀ ⦃y⦄, y ∈ l → f x = f y → x = y :=
+ by
+ induction' l with hd tl ih
+ · simp
+ · simp only [map, nodup_cons, mem_map, not_exists, not_and, ← Ne.def] at d
+ simp only [mem_cons]
+ rintro _ (rfl | h₁) _ (rfl | h₂) h₃
+ · rfl
+ · apply (d.1 _ h₂ h₃).elim
+ · apply (d.1 _ h₁ h₃.symm).elim
+ · apply ih d.2 h₁ h₂ h₃
+#align list.inj_on_of_nodup_map List.inj_on_of_nodup_map
-theorem Nodup.of_map (f : α → β) {l : List α} : Nodup (map f l) → Nodup l :=
- (Pairwise.of_map f) fun _ _ ↦ mt <| congr_arg f
+theorem nodup_map_iff_inj_on {f : α → β} {l : List α} (d : Nodup l) :
+ Nodup (map f l) ↔ ∀ x ∈ l, ∀ y ∈ l, f x = f y → x = y :=
+ ⟨inj_on_of_nodup_map, fun h => d.map_on h⟩
+#align list.nodup_map_iff_inj_on List.nodup_map_iff_inj_on
+
+protected theorem Nodup.map {f : α → β} (hf : Injective f) : Nodup l → Nodup (map f l) :=
+ Nodup.map_on fun _ _ _ _ h => hf h
+#align list.nodup.map List.Nodup.map -- Porting note: different universe order
+
+theorem nodup_map_iff {f : α → β} {l : List α} (hf : Injective f) : Nodup (map f l) ↔ Nodup l :=
+ ⟨Nodup.of_map _, Nodup.map hf⟩
+#align list.nodup_map_iff List.nodup_map_iff
@[simp]
theorem nodup_attach {l : List α} : Nodup (attach l) ↔ Nodup l :=
- ⟨fun h ↦ attach_map_val l ▸ h.map fun _ _ ↦ Subtype.eq,
- fun h ↦ Nodup.of_map Subtype.val ((attach_map_val l).symm ▸ h)⟩
+ ⟨fun h => attach_map_val l ▸ h.map fun _ _ => Subtype.eq, fun h =>
+ Nodup.of_map Subtype.val ((attach_map_val l).symm ▸ h)⟩
+#align list.nodup_attach List.nodup_attach
alias nodup_attach ↔ Nodup.of_attach Nodup.attach
--- TODO in mathlib3 we had:
--- attribute [protected] nodup.attach
+--Porting note: commented out
+--attribute [protected] nodup.attach
theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H}
(hf : ∀ a ha b hb, f a ha = f b hb → a = b) (h : Nodup l) : Nodup (pmap f l H) := by
- rw [pmap_eq_map_attach]
- exact h.attach.map fun ⟨a, ha⟩ ⟨b, hb⟩ h ↦ by
- congr
- exact hf a (H _ ha) b (H _ hb) h
+ rw [pmap_eq_map_attach];
+ exact h.attach.map fun ⟨a, ha⟩ ⟨b, hb⟩ h => by congr; exact hf a (H _ ha) b (H _ hb) h
+#align list.nodup.pmap List.Nodup.pmap
+
+theorem Nodup.filter (p : α → Bool) {l} : Nodup l → Nodup (filter p l) := by
+ simpa using Pairwise.filter (fun a ↦ p a)
+#align list.nodup.filter List.Nodup.filter
+
+@[simp]
+theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
+ pairwise_reverse.trans <| by simp only [Nodup, Ne.def, eq_comm]
+#align list.nodup_reverse List.nodup_reverse
+
+theorem Nodup.erase_eq_filter [DecidableEq α] {l} (d : Nodup l) (a : α) :
+ l.erase a = l.filter (· ≠ a) :=
+ by
+ induction' d with b l m _ IH; · rfl
+ by_cases b = a
+ · subst h
+ rw [erase_cons_head, filter_cons_of_neg]
+ symm
+ rw [filter_eq_self]
+ simpa [@eq_comm α] using m
+ simp
+ · rw [erase_cons_tail _ h, filter_cons_of_pos, IH]
+ simp [h]
+#align list.nodup.erase_eq_filter List.Nodup.erase_eq_filter
+
+theorem Nodup.erase [DecidableEq α] (a : α) : Nodup l → Nodup (l.erase a) :=
+ Nodup.sublist <| erase_sublist _ _
+#align list.nodup.erase List.Nodup.erase
+
+theorem Nodup.diff [DecidableEq α] : l₁.Nodup → (l₁.diff l₂).Nodup :=
+ Nodup.sublist <| diff_sublist _ _
+#align list.nodup.diff List.Nodup.diff
+
+theorem Nodup.mem_erase_iff [DecidableEq α] (d : Nodup l) : a ∈ l.erase b ↔ a ≠ b ∧ a ∈ l := by
+ rw [d.erase_eq_filter, mem_filter, and_comm, decide_eq_true_iff]
+#align list.nodup.mem_erase_iff List.Nodup.mem_erase_iff
+
+theorem Nodup.not_mem_erase [DecidableEq α] (h : Nodup l) : a ∉ l.erase a := fun H =>
+ (h.mem_erase_iff.1 H).1 rfl
+#align list.nodup.not_mem_erase List.Nodup.not_mem_erase
+
+theorem nodup_join {L : List (List α)} :
+ Nodup (join L) ↔ (∀ l ∈ L, Nodup l) ∧ Pairwise Disjoint L := by
+ simp only [Nodup, pairwise_join, disjoint_left.symm, forall_mem_ne]
+#align list.nodup_join List.nodup_join
+
+theorem nodup_bind {l₁ : List α} {f : α → List β} :
+ Nodup (l₁.bind f) ↔
+ (∀ x ∈ l₁, Nodup (f x)) ∧ Pairwise (fun a b : α => Disjoint (f a) (f b)) l₁ := by
+ simp only [List.bind, nodup_join, pairwise_map, and_comm, and_left_comm, mem_map, exists_imp,
+ and_imp]
+ rw [show (∀ (l : List β) (x : α), l = f x → x ∈ l₁ → Nodup l) ↔ ∀ x : α, x ∈ l₁ → Nodup (f x)
+ from forall_swap.trans <| forall_congr' fun _ => forall_eq]
+#align list.nodup_bind List.nodup_bind
+
+protected theorem Nodup.product {l₂ : List β} (d₁ : l₁.Nodup) (d₂ : l₂.Nodup) :
+ (l₁.product l₂).Nodup :=
+ nodup_bind.2
+ ⟨fun a _ => d₂.map <| LeftInverse.injective fun b => (rfl : (a, b).2 = b),
+ d₁.imp @fun a₁ a₂ n x h₁ h₂ => by
+ rcases mem_map.1 h₁ with ⟨b₁, _, rfl⟩
+ rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩
+ exact n rfl⟩
+#align list.nodup.product List.Nodup.product
+
+theorem Nodup.sigma {σ : α → Type _} {l₂ : ∀ a , List (σ a)} (d₁ : Nodup l₁)
+ (d₂ : ∀ a , Nodup (l₂ a)) : (l₁.sigma l₂).Nodup :=
+ nodup_bind.2
+ ⟨fun a _ => (d₂ a).map fun b b' h => by injection h with _ h,
+ d₁.imp @fun a₁ a₂ n x h₁ h₂ => by
+ rcases mem_map.1 h₁ with ⟨b₁, _, rfl⟩
+ rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩
+ exact n rfl⟩
+#align list.nodup.sigma List.Nodup.sigma
+
+protected theorem Nodup.filterMap {f : α → Option β} (h : ∀ a a' b, b ∈ f a → b ∈ f a' → a = a') :
+ Nodup l → Nodup (filterMap f l) :=
+ (Pairwise.filter_map f) @fun a a' n b bm b' bm' e => n <| h a a' b' (by rw [← e]; exact bm) bm'
+#align list.nodup.filter_map List.Nodup.filterMap
+
+protected theorem Nodup.concat (h : a ∉ l) (h' : l.Nodup) : (l.concat a).Nodup := by
+ rw [concat_eq_append]; exact h'.append (nodup_singleton _) (disjoint_singleton.2 h)
+#align list.nodup.concat List.Nodup.concat
+
+theorem Nodup.insert [DecidableEq α] (h : l.Nodup) : (l.insert a).Nodup :=
+ if h' : a ∈ l then by rw [insert_of_mem h']; exact h
+ else by rw [insert_of_not_mem h', nodup_cons]; constructor <;> assumption
+#align list.nodup.insert List.Nodup.insert
+
+theorem Nodup.union [DecidableEq α] (l₁ : List α) (h : Nodup l₂) : (l₁ ∪ l₂).Nodup :=
+ by
+ induction' l₁ with a l₁ ih generalizing l₂
+ · exact h
+ · exact (ih h).insert
+#align list.nodup.union List.Nodup.union
+
+theorem Nodup.inter [DecidableEq α] (l₂ : List α) : Nodup l₁ → Nodup (l₁ ∩ l₂) :=
+ Nodup.filter _
+#align list.nodup.inter List.Nodup.inter
+
+theorem Nodup.diff_eq_filter [DecidableEq α] :
+ ∀ {l₁ l₂ : List α} (_ : l₁.Nodup), l₁.diff l₂ = l₁.filter (· ∉ l₂)
+ | l₁, [], _ => by simp
+ | l₁, a :: l₂, hl₁ => by
+ rw [diff_cons, (hl₁.erase _).diff_eq_filter, hl₁.erase_eq_filter, filter_filter]
+ simp only [decide_not, Bool.not_eq_true', decide_eq_false_iff_not, ne_eq, and_comm,
+ Bool.decide_and, find?, mem_cons, not_or]
+#align list.nodup.diff_eq_filter List.Nodup.diff_eq_filter
+
+theorem Nodup.mem_diff_iff [DecidableEq α] (hl₁ : l₁.Nodup) : a ∈ l₁.diff l₂ ↔ a ∈ l₁ ∧ a ∉ l₂ := by
+ rw [hl₁.diff_eq_filter, mem_filter, decide_eq_true_iff]
+#align list.nodup.mem_diff_iff List.Nodup.mem_diff_iff
+
+protected theorem Nodup.set :
+ ∀ {l : List α} {n : ℕ} {a : α} (_ : l.Nodup) (_ : a ∉ l), (l.set n a).Nodup
+ | [], _, _, _, _ => nodup_nil
+ | _ :: _, 0, _, hl, ha => nodup_cons.2 ⟨mt (mem_cons_of_mem _) ha, (nodup_cons.1 hl).2⟩
+ | _ :: _, _ + 1, _, hl, ha =>
+ nodup_cons.2
+ ⟨fun h =>
+ (mem_or_eq_of_mem_set h).elim (nodup_cons.1 hl).1 fun hba => ha (hba ▸ mem_cons_self _ _),
+ hl.of_cons.set (mt (mem_cons_of_mem _) ha)⟩
+#align list.nodup.update_nth List.Nodup.set
+
+theorem Nodup.map_update [DecidableEq α] {l : List α} (hl : l.Nodup) (f : α → β) (x : α) (y : β) :
+ l.map (Function.update f x y) =
+ if x ∈ l then (l.map f).set (l.indexOf x) y else l.map f := by
+ induction' l with hd tl ihl; · simp
+ rw [nodup_cons] at hl
+ simp only [mem_cons, map, ihl hl.2]
+ by_cases H : hd = x
+ · subst hd
+ simp [set, hl.1]
+ · simp [Ne.symm H, H, set, ← apply_ite (cons (f hd))]
+#align list.nodup.map_update List.Nodup.map_update
+
+theorem Nodup.pairwise_of_forall_ne {l : List α} {r : α → α → Prop} (hl : l.Nodup)
+ (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by
+ classical
+ refine' pairwise_of_reflexive_on_dupl_of_forall_ne _ h
+ intro x hx
+ rw [nodup_iff_count_le_one] at hl
+ exact absurd (hl x) hx.not_le
+#align list.nodup.pairwise_of_forall_ne List.Nodup.pairwise_of_forall_ne
+
+theorem Nodup.pairwise_of_set_pairwise {l : List α} {r : α → α → Prop} (hl : l.Nodup)
+ (h : { x | x ∈ l }.Pairwise r) : l.Pairwise r :=
+ hl.pairwise_of_forall_ne h
+#align list.nodup.pairwise_of_set_pairwise List.Nodup.pairwise_of_set_pairwise
+
+@[simp]
+theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : { a | a ∈ l }.Pairwise r ↔ l.Pairwise r :=
+ by
+ induction' l with a l ih
+ · simp
+ rw [List.nodup_cons] at hl
+ have : ∀ b ∈ l, ¬a = b → r a b ↔ r a b := fun b hb =>
+ imp_iff_right (ne_of_mem_of_not_mem hb hl.1).symm
+ simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm,
+ forall₂_congr this]
+#align list.nodup.pairwise_coe List.Nodup.pairwise_coe
+
+end List
+
+theorem Option.toList_nodup {α} : ∀ o : Option α, o.toList.Nodup
+ | none => List.nodup_nil
+ | some x => List.nodup_singleton x
+#align option.to_list_nodup Option.toList_nodup
The unported dependencies are