File: Mathlib/Data/List/Sort.lean

full_name: List.Sorted
code: /-- `Sorted r l` is the same as `List.Pairwise r l`, preferred in the case that `r`
  is a `<` or `≤`-like relation (transitive and antisymmetric or asymmetric) -/
def Sorted 
goal: List α → Prop

full_name: List.decidableSorted
code: instance decidableSorted [DecidableRel r] (l : List α) : Decidable (Sorted r l) 
goal: Decidable (List.Sorted r l)

full_name: List.Sorted.le_of_lt
code: protected theorem Sorted.le_of_lt [Preorder α] {l : List α} (h : l.Sorted (· < ·)) :
    l.Sorted (· ≤ ·) 
goal: List.Sorted (fun x x_1 => x ≤ x_1) l

full_name: List.Sorted.lt_of_le
code: protected theorem Sorted.lt_of_le [PartialOrder α] {l : List α} (h₁ : l.Sorted (· ≤ ·))
    (h₂ : l.Nodup) : l.Sorted (· < ·) 
goal: List.Sorted (fun x x_1 => x < x_1) l

full_name: List.Sorted.ge_of_gt
code: protected theorem Sorted.ge_of_gt [Preorder α] {l : List α} (h : l.Sorted (· > ·)) :
    l.Sorted (· ≥ ·) 
goal: List.Sorted (fun x x_1 => x ≥ x_1) l

full_name: List.Sorted.gt_of_ge
code: protected theorem Sorted.gt_of_ge [PartialOrder α] {l : List α} (h₁ : l.Sorted (· ≥ ·))
    (h₂ : l.Nodup) : l.Sorted (· > ·) 
goal: List.Sorted (fun x x_1 => x > x_1) l

full_name: List.sorted_nil
code: @[simp]
theorem sorted_nil : Sorted r [] 
goal: List.Sorted r []

full_name: List.Sorted.of_cons
code: theorem Sorted.of_cons : Sorted r (a :: l) → Sorted r l 
goal: List.Sorted r (a :: l) → List.Sorted r l

full_name: List.Sorted.tail
code: theorem Sorted.tail {r : α → α → Prop} {l : List α} (h : Sorted r l) : Sorted r l.tail 
goal: List.Sorted r l.tail

full_name: List.rel_of_sorted_cons
code: theorem rel_of_sorted_cons {a : α} {l : List α} : Sorted r (a :: l) → ∀ b ∈ l, r a b 
goal: List.Sorted r (a :: l) → ∀ b ∈ l, r a b

full_name: List.Sorted.head!_le
code: theorem Sorted.head!_le [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· < ·) l)
    (ha : a ∈ l) : l.head! ≤ a 
goal: l.head! ≤ a

full_name: List.Sorted.le_head!
code: theorem Sorted.le_head! [Inhabited α] [Preorder α] {a : α} {l : List α} (h : Sorted (· > ·) l)
    (ha : a ∈ l) : a ≤ l.head! 
goal: a ≤ l.head!

full_name: List.sorted_cons
code: @[simp]
theorem sorted_cons {a : α} {l : List α} : Sorted r (a :: l) ↔ (∀ b ∈ l, r a b) ∧ Sorted r l 
goal: List.Sorted r (a :: l) ↔ (∀ b ∈ l, r a b) ∧ List.Sorted r l

full_name: List.Sorted.nodup
code: protected theorem Sorted.nodup {r : α → α → Prop} [IsIrrefl α r] {l : List α} (h : Sorted r l) :
    Nodup l 
goal: l.Nodup

full_name: List.eq_of_perm_of_sorted
code: theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (hp : l₁ ~ l₂) (hs₁ : Sorted r l₁)
    (hs₂ : Sorted r l₂) : l₁ = l₂ 
goal: l₁ = l₂

full_name: List.sublist_of_subperm_of_sorted
code: theorem sublist_of_subperm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (hp : l₁ <+~ l₂)
    (hs₁ : l₁.Sorted r) (hs₂ : l₂.Sorted r) : l₁ <+ l₂ 
goal: l₁.Sublist l₂

full_name: List.sorted_singleton
code: @[simp 1100] -- Porting note: higher priority for linter
theorem sorted_singleton (a : α) : Sorted r [a] 
goal: List.Sorted r [a]

full_name: List.Sorted.rel_get_of_lt
code: theorem Sorted.rel_get_of_lt {l : List α} (h : l.Sorted r) {a b : Fin l.length} (hab : a < b) :
    r (l.get a) (l.get b) 
goal: r (l.get a) (l.get b)

full_name: List.Sorted.rel_nthLe_of_lt
code: @[deprecated Sorted.rel_get_of_lt (since := "2024-05-08")]
theorem Sorted.rel_nthLe_of_lt {l : List α} (h : l.Sorted r) {a b : ℕ} (ha : a < l.length)
    (hb : b < l.length) (hab : a < b) : r (l.nthLe a ha) (l.nthLe b hb) 
goal: r (l.nthLe a ha) (l.nthLe b hb)

full_name: List.Sorted.rel_get_of_le
code: theorem Sorted.rel_get_of_le [IsRefl α r] {l : List α} (h : l.Sorted r) {a b : Fin l.length}
    (hab : a ≤ b) : r (l.get a) (l.get b) 
goal: r (l.get a) (l.get b)

full_name: List.Sorted.rel_nthLe_of_le
code: @[deprecated Sorted.rel_get_of_le (since := "2024-05-08")]
theorem Sorted.rel_nthLe_of_le [IsRefl α r] {l : List α} (h : l.Sorted r) {a b : ℕ}
    (ha : a < l.length) (hb : b < l.length) (hab : a ≤ b) : r (l.nthLe a ha) (l.nthLe b hb) 
goal: r (l.nthLe a ha) (l.nthLe b hb)

full_name: List.Sorted.rel_of_mem_take_of_mem_drop
code: theorem Sorted.rel_of_mem_take_of_mem_drop {l : List α} (h : List.Sorted r l) {k : ℕ} {x y : α}
    (hx : x ∈ List.take k l) (hy : y ∈ List.drop k l) : r x y 
goal: r x y

full_name: List.sorted_ofFn_iff
code: theorem sorted_ofFn_iff {r : α → α → Prop} : (ofFn f).Sorted r ↔ ((· < ·) ⇒ r) f f 
goal: List.Sorted r (List.ofFn f) ↔ ((fun x x_1 => x < x_1) ⇒ r) f f

full_name: List.sorted_lt_ofFn_iff
code: /-- The list `List.ofFn f` is strictly sorted with respect to `(· ≤ ·)` if and only if `f` is
strictly monotone. -/
@[simp] theorem sorted_lt_ofFn_iff : (ofFn f).Sorted (· < ·) ↔ StrictMono f 
goal: List.Sorted (fun x x_1 => x < x_1) (List.ofFn f) ↔ StrictMono f

full_name: List.sorted_le_ofFn_iff
code: /-- The list `List.ofFn f` is sorted with respect to `(· ≤ ·)` if and only if `f` is monotone. -/
@[simp] theorem sorted_le_ofFn_iff : (ofFn f).Sorted (· ≤ ·) ↔ Monotone f 
goal: List.Sorted (fun x x_1 => x ≤ x_1) (List.ofFn f) ↔ Monotone f

full_name: List.monotone_iff_ofFn_sorted
code: /-- A tuple is monotone if and only if the list obtained from it is sorted. -/
@[deprecated sorted_le_ofFn_iff (since := "2023-01-10")]
theorem monotone_iff_ofFn_sorted : Monotone f ↔ (ofFn f).Sorted (· ≤ ·) 
goal: Monotone f ↔ List.Sorted (fun x x_1 => x ≤ x_1) (List.ofFn f)

full_name: List.«_aux_Mathlib_Data_List_Sort___macroRules_List_term_≼__1»
code: local infixl:50 " ≼ " => r
goal: Lean.Macro

full_name: List.orderedInsert
code: /-- `orderedInsert a l` inserts `a` into `l` at such that
  `orderedInsert a l` is sorted if `l` is. -/
@[simp]
def orderedInsert (a : α) : List α → List α
  
goal: List α → List α

full_name: List.insertionSort
code: /-- `insertionSort l` returns `l` sorted using the insertion sort algorithm. -/
@[simp]
def insertionSort : List α → List α
  
goal: List α → List α

full_name: List.orderedInsert_nil
code: @[simp]
theorem orderedInsert_nil (a : α) : [].orderedInsert r a = [a] 
goal: List.orderedInsert r a [] = [a]

full_name: List.orderedInsert_length
code: theorem orderedInsert_length : ∀ (L : List α) (a : α), (L.orderedInsert r a).length = L.length + 1
  
goal: (List.orderedInsert r a L).length = L.length + 1

full_name: List.orderedInsert_eq_take_drop
code: /-- An alternative definition of `orderedInsert` using `takeWhile` and `dropWhile`. -/
theorem orderedInsert_eq_take_drop (a : α) :
    ∀ l : List α,
      l.orderedInsert r a = (l.takeWhile fun b => ¬a ≼ b) ++ a :: l.dropWhile fun b => ¬a ≼ b
  
goal: List.orderedInsert r a l = List.takeWhile (fun b => decide ¬r a b) l ++ a :: List.dropWhile (fun b => decide ¬r a b) l

full_name: List.insertionSort_cons_eq_take_drop
code: theorem insertionSort_cons_eq_take_drop (a : α) (l : List α) :
    insertionSort r (a :: l) =
      ((insertionSort r l).takeWhile fun b => ¬a ≼ b) ++
        a :: (insertionSort r l).dropWhile fun b => ¬a ≼ b 
goal: List.insertionSort r (a :: l) =
  List.takeWhile (fun b => decide ¬r a b) (List.insertionSort r l) ++
    a :: List.dropWhile (fun b => decide ¬r a b) (List.insertionSort r l)

full_name: List.mem_orderedInsert
code: @[simp]
theorem mem_orderedInsert {a b : α} {l : List α} :
    a ∈ orderedInsert r b l ↔ a = b ∨ a ∈ l 
goal: a ∈ List.orderedInsert r b l ↔ a = b ∨ a ∈ l

full_name: List.perm_orderedInsert
code: theorem perm_orderedInsert (a) : ∀ l : List α, orderedInsert r a l ~ a :: l
  
goal: (List.orderedInsert r a l).Perm (a :: l)

full_name: List.orderedInsert_count
code: theorem orderedInsert_count [DecidableEq α] (L : List α) (a b : α) :
    count a (L.orderedInsert r b) = count a L + if a = b then 1 else 0 
goal: List.count a (List.orderedInsert r b L) = List.count a L + if a = b then 1 else 0

full_name: List.perm_insertionSort
code: theorem perm_insertionSort : ∀ l : List α, insertionSort r l ~ l
  
goal: (List.insertionSort r l).Perm l

full_name: List.Sorted.insertionSort_eq
code: /-- If `l` is already `List.Sorted` with respect to `r`, then `insertionSort` does not change
it. -/
theorem Sorted.insertionSort_eq : ∀ {l : List α}, Sorted r l → insertionSort r l = l
  
goal: List.Sorted r l → List.insertionSort r l = l

full_name: List.erase_orderedInsert
code: /-- For a reflexive relation, insert then erasing is the identity. -/
theorem erase_orderedInsert [DecidableEq α] [IsRefl α r] (x : α) (xs : List α) :
    (xs.orderedInsert r x).erase x = xs 
goal: (List.orderedInsert r x xs).erase x = xs

full_name: List.erase_orderedInsert_of_not_mem
code: /-- Inserting then erasing an element that is absent is the identity. -/
theorem erase_orderedInsert_of_not_mem [DecidableEq α]
    {x : α} {xs : List α} (hx : x ∉ xs) :
    (xs.orderedInsert r x).erase x = xs 
goal: (List.orderedInsert r x xs).erase x = xs

full_name: List.orderedInsert_erase
code: /-- For an antisymmetric relation, erasing then inserting is the identity. -/
theorem orderedInsert_erase [DecidableEq α] [IsAntisymm α r] (x : α) (xs : List α) (hx : x ∈ xs)
    (hxs : Sorted r xs) :
    (xs.erase x).orderedInsert r x = xs 
goal: List.orderedInsert r x (xs.erase x) = xs

full_name: List.sublist_orderedInsert
code: theorem sublist_orderedInsert (x : α) (xs : List α) : xs <+ xs.orderedInsert r x 
goal: xs.Sublist (List.orderedInsert r x xs)

full_name: List.Sorted.orderedInsert
code: theorem Sorted.orderedInsert (a : α) : ∀ l, Sorted r l → Sorted r (orderedInsert r a l)
  
goal: List.Sorted r l → List.Sorted r (List.orderedInsert r a l)

full_name: List.sorted_insertionSort
code: /-- The list `List.insertionSort r l` is `List.Sorted` with respect to `r`. -/
theorem sorted_insertionSort : ∀ l, Sorted r (insertionSort r l)
  
goal: List.Sorted r (List.insertionSort r l)

full_name: List.split
code: /-- Split `l` into two lists of approximately equal length.

     split [1, 2, 3, 4, 5] = ([1, 3, 5], [2, 4]) -/
@[simp]
def split : List α → List α × List α
  
goal: List α → List α × List α

full_name: List.split_cons_of_eq
code: theorem split_cons_of_eq (a : α) {l l₁ l₂ : List α} (h : split l = (l₁, l₂)) :
    split (a :: l) = (a :: l₂, l₁) 
goal: (a :: l).split = (a :: l₂, l₁)

full_name: List.length_split_le
code: theorem length_split_le :
    ∀ {l l₁ l₂ : List α}, split l = (l₁, l₂) → length l₁ ≤ length l ∧ length l₂ ≤ length l
  
goal: l.split = (l₁, l₂) → l₁.length ≤ l.length ∧ l₂.length ≤ l.length

full_name: List.length_split_fst_le
code: theorem length_split_fst_le (l : List α) : length (split l).1 ≤ length l 
goal: l.split.1.length ≤ l.length

full_name: List.length_split_snd_le
code: theorem length_split_snd_le (l : List α) : length (split l).2 ≤ length l 
goal: l.split.2.length ≤ l.length

full_name: List.length_split_lt
code: theorem length_split_lt {a b} {l l₁ l₂ : List α} (h : split (a :: b :: l) = (l₁, l₂)) :
    length l₁ < length (a :: b :: l) ∧ length l₂ < length (a :: b :: l) 
goal: l₁.length < (a :: b :: l).length ∧ l₂.length < (a :: b :: l).length

full_name: List.perm_split
code: theorem perm_split : ∀ {l l₁ l₂ : List α}, split l = (l₁, l₂) → l ~ l₁ ++ l₂
  
goal: l.split = (l₁, l₂) → l.Perm (l₁ ++ l₂)

full_name: List.mergeSort
code: /-- Implementation of a merge sort algorithm to sort a list. -/
def mergeSort : List α → List α
  
goal: List α → List α

full_name: List.mergeSort_cons_cons
code: @[nolint unusedHavesSuffices] -- Porting note: false positive
theorem mergeSort_cons_cons {a b} {l l₁ l₂ : List α} (h : split (a :: b :: l) = (l₁, l₂)) :
    mergeSort r (a :: b :: l) = merge (r · ·) (mergeSort r l₁) (mergeSort r l₂) 
goal: List.mergeSort r (a :: b :: l) = List.merge (fun x x_1 => decide (r x x_1)) (List.mergeSort r l₁) (List.mergeSort r l₂)

full_name: List.perm_mergeSort
code: theorem perm_mergeSort : ∀ l : List α, mergeSort r l ~ l
  
goal: (List.mergeSort r l).Perm l

full_name: List.length_mergeSort
code: @[simp]
theorem length_mergeSort (l : List α) : (mergeSort r l).length = l.length 
goal: (List.mergeSort r l).length = l.length

full_name: List.Sorted.merge
code: theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sorted r (merge (r · ·) l l')
  
goal: List.Sorted r l → List.Sorted r l' → List.Sorted r (List.merge (fun x x_1 => decide (r x x_1)) l l')

full_name: List.sorted_mergeSort
code: theorem sorted_mergeSort : ∀ l : List α, Sorted r (mergeSort r l)
  
goal: List.Sorted r (List.mergeSort r l)

full_name: List.mergeSort_eq_self
code: theorem mergeSort_eq_self [IsAntisymm α r] {l : List α} : Sorted r l → mergeSort r l = l 
goal: List.Sorted r l → List.mergeSort r l = l

full_name: List.mergeSort_eq_insertionSort
code: theorem mergeSort_eq_insertionSort [IsAntisymm α r] (l : List α) :
    mergeSort r l = insertionSort r l 
goal: List.mergeSort r l = List.insertionSort r l

full_name: List.mergeSort_nil
code: @[simp]
theorem mergeSort_nil : [].mergeSort r = [] 
goal: List.mergeSort r [] = []

full_name: List.mergeSort_singleton
code: @[simp]
theorem mergeSort_singleton (a : α) : [a].mergeSort r = [a] 
goal: List.mergeSort r [a] = [a]