data.list.nodupMathlib.Data.List.Nodup

This file has been ported!

Changes since the initial port

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.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(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)

chore(data/set/pairwise): split (#17880)

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.

Zulip

mathlib4 PR: https://github.com/leanprover-community/mathlib4/pull/1184

Co-authored-by: Yaël Dillies <yael.dillies@gmail.com>

Diff
@@ -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)

refactor(*): define 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.

Diff
@@ -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)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -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 /-
Diff
@@ -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
 -/
Diff
@@ -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',
Diff
@@ -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
 -/
 
Diff
@@ -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
 -/
 
Diff
@@ -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
 -/
Diff
@@ -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"
 
Diff
@@ -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
 
Diff
@@ -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
 
Diff
@@ -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
 -/
Diff
@@ -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)
Diff
@@ -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
Diff
@@ -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',
Diff
@@ -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
Diff
@@ -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:
Diff
@@ -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

Changes in mathlib4

mathlib3
mathlib4
chore(Data/List): add dates to all deprecated lemmas (#12337)

Most of them go back to the port.

Diff
@@ -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 _ _ _
chore(Data/List/Basic): remove some long-deprecated unused lemmas (#12367)
Diff
@@ -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) :
chore: update Std (#11858)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -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
chore: avoid Ne.def (adaptation for nightly-2024-03-27) (#11801)
Diff
@@ -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 : α) :
golf: replace some 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.

Diff
@@ -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
chore: classify new theorem / theorem porting notes (#11432)

Classifies by adding issue number #10756 to porting notes claiming anything equivalent to:

  • "added theorem"
  • "added theorems"
  • "new theorem"
  • "new theorems"
  • "added lemma"
  • "new lemma"
  • "new lemmas"
Diff
@@ -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
style: homogenise porting notes (#11145)

Homogenises porting notes via capitalisation and addition of whitespace.

It makes the following changes:

  • converts "--porting note" into "-- Porting note";
  • converts "porting note" into "Porting note".
Diff
@@ -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
chore(Init/Fin): deprecate 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.

Diff
@@ -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
feat: Add norm_iteratedFDeriv_prod_le using Sym (#10022)

add (iterated) deriv for prod

  • Add HasFDerivAt + variants for Finset.prod (and ContinuousMultilinearMap.mkPiAlgebra)
  • Add missing iteratedFDerivWithin equivalents for zero, const (resolves a todo in Analysis.Calculus.ContDiff.Basic)
  • Add iteratedFDeriv[Within]_sum for symmetry
  • Add a couple of convenience lemmas for Sym and Finset.{prod,sum}
Diff
@@ -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
chore: bump dependencies (#10954)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Riccardo Brasca <riccardo.brasca@gmail.com>

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
 
chore: reduce imports (#9830)

This uses the improved shake script from #9772 to reduce imports across mathlib. The corresponding noshake.json file has been added to #9772.

Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -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
chore(*): use ∃ 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.

Diff
@@ -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
 
refactor(Logic/Unique): remove dependency on 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.

Diff
@@ -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"
 
feat: add some Multiset.Nodup lemmas (#8464)

Based on results from flt-regular.

Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com>

Diff
@@ -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
chore: update to std4#100 (#6743)

Std bump patch for https://github.com/leanprover/std4/pull/100

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -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)
style: a linter for colons (#6761)

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.

Diff
@@ -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
feat: patch for new alias command (#6172)
Diff
@@ -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
 
chore: bump Std (#6721)

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>

Diff
@@ -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) :
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -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,
chore(*): add protected to *.insert theorems (#6142)

Otherwise code like

theorem ContMDiffWithinAt.mythm (h : x ∈ insert y s) : _ = _

interprets insert as ContMDiffWithinAt.insert, not Insert.insert.

Diff
@@ -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
chore: use · instead of . (#6085)
Diff
@@ -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
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -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
 
chore: fix focusing dots (#5708)

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.

Diff
@@ -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?
refactor: use the typeclass 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>

Diff
@@ -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
chore: bye-bye, solo bys! (#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 bys".

Diff
@@ -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
 
chore: Split 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>

Diff
@@ -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
chore: bump Std (#3113)

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'.

Diff
@@ -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) :
chore: add missing hypothesis names to by_cases (#2679)
Diff
@@ -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
Diff
@@ -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.
 -/
chore: tidy various files (#2056)
Diff
@@ -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
chore: add missing #align statements (#1902)

This PR is the result of a slight variant on the following "algorithm"

  • take all mathlib 3 names, remove _ and make all uppercase letters into lowercase
  • take all mathlib 4 names, remove _ and make all uppercase letters into lowercase
  • look for matches, and create pairs (original_lean3_name, OriginalLean4Name)
  • for pairs that do not have an align statement:
    • use Lean 4 to lookup the file + position of the Lean 4 name
    • add an #align statement just before the next empty line
  • manually fix some tiny mistakes (e.g., empty lines in proofs might cause the #align statement to have been inserted too early)
Diff
@@ -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
chore: format by line breaks with long lines (#1529)

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>

Diff
@@ -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
chore: format 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>

Diff
@@ -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
Refactor: drop List.repeat (#1579)

Mathlib 3 migrated to list.replicate in leanprover-community/mathlib#18127 (merged) and leanprover-community/mathlib#18181 (awaiting review).

Diff
@@ -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) :
feat: port Mathlib.Data.List.Perm (#1478)

Co-authored-by: Johan Commelin <johan@commelin.net> Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com>

Diff
@@ -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
feat: port Mathlib.Data.List.Nodup (#1456)

Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com>

Diff
@@ -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

Dependencies 2 + 103

104 files ported (98.1%)
51158 lines ported (99.7%)
Show graph

The unported dependencies are