File: .lake/packages/lean4/src/lean/Init/Data/Array/Lemmas.lean

full_name: Array.singleton_def
code: @[simp] theorem singleton_def (v : α) : singleton v = #[v] 
goal: Array.singleton v = #[v]

full_name: Array.toArray_data
code: @[simp] theorem toArray_data : (a : Array α) → a.data.toArray = a
  
goal: List.toArray a.data = a

full_name: Array.data_length
code: @[simp] theorem data_length {l : Array α} : l.data.length = l.size 
goal: l.data.length = l.size

full_name: Array.mkEmpty_eq
code: @[simp] theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] 
goal: Array.mkEmpty n = #[]

full_name: Array.size_toArray
code: @[simp] theorem size_toArray (as : List α) : as.toArray.size = as.length 
goal: (List.toArray as).size = as.length

full_name: Array.size_mk
code: @[simp] theorem size_mk (as : List α) : (Array.mk as).size = as.length 
goal: { data := as }.size = as.length

full_name: Array.getElem_eq_data_getElem
code: theorem getElem_eq_data_getElem (a : Array α) (h : i < a.size) : a[i] = a.data[i] 
goal: a[i] = a.data[i]

full_name: Array.getElem_eq_data_get
code: @[deprecated getElem_eq_data_getElem (since := "2024-06-12")]
theorem getElem_eq_data_get (a : Array α) (h : i < a.size) : a[i] = a.data.get ⟨i, h⟩ 
goal: a[i] = a.data.get ⟨i, h⟩

full_name: Array.foldlM_eq_foldlM_data.aux
code: theorem foldlM_eq_foldlM_data.aux [Monad m]
    (f : β → α → m β) (arr : Array α) (i j) (H : arr.size ≤ i + j) (b) :
    foldlM.loop f arr arr.size (Nat.le_refl _) i j b = (arr.data.drop j).foldlM f b 
goal: Array.foldlM.loop f arr arr.size ⋯ i j b = List.foldlM f b (List.drop j arr.data)

full_name: Array.foldlM_eq_foldlM_data
code: theorem foldlM_eq_foldlM_data [Monad m]
    (f : β → α → m β) (init : β) (arr : Array α) :
    arr.foldlM f init = arr.data.foldlM f init 
goal: Array.foldlM f init arr 0 = List.foldlM f init arr.data

full_name: Array.foldl_eq_foldl_data
code: theorem foldl_eq_foldl_data (f : β → α → β) (init : β) (arr : Array α) :
    arr.foldl f init = arr.data.foldl f init 
goal: Array.foldl f init arr 0 = List.foldl f init arr.data

full_name: Array.foldrM_eq_reverse_foldlM_data.aux
code: theorem foldrM_eq_reverse_foldlM_data.aux [Monad m]
    (f : α → β → m β) (arr : Array α) (init : β) (i h) :
    (arr.data.take i).reverse.foldlM (fun x y => f y x) init = foldrM.fold f arr 0 i h init 
goal: List.foldlM (fun x y => f y x) init (List.take i arr.data).reverse = Array.foldrM.fold f arr 0 i h init

full_name: Array.foldrM_eq_reverse_foldlM_data
code: theorem foldrM_eq_reverse_foldlM_data [Monad m] (f : α → β → m β) (init : β) (arr : Array α) :
    arr.foldrM f init = arr.data.reverse.foldlM (fun x y => f y x) init 
goal: Array.foldrM f init arr arr.size = List.foldlM (fun x y => f y x) init arr.data.reverse

full_name: Array.foldrM_eq_foldrM_data
code: theorem foldrM_eq_foldrM_data [Monad m]
    (f : α → β → m β) (init : β) (arr : Array α) :
    arr.foldrM f init = arr.data.foldrM f init 
goal: Array.foldrM f init arr arr.size = List.foldrM f init arr.data

full_name: Array.foldr_eq_foldr_data
code: theorem foldr_eq_foldr_data (f : α → β → β) (init : β) (arr : Array α) :
    arr.foldr f init = arr.data.foldr f init 
goal: Array.foldr f init arr arr.size = List.foldr f init arr.data

full_name: Array.push_data
code: @[simp] theorem push_data (arr : Array α) (a : α) : (arr.push a).data = arr.data ++ [a] 
goal: (arr.push a).data = arr.data ++ [a]

full_name: Array.foldrM_push
code: theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
    (arr.push a).foldrM f init = f a init >>= arr.foldrM f 
goal: Array.foldrM f init (arr.push a) (arr.push a).size = do
  let init ← f a init
  Array.foldrM f init arr arr.size

full_name: Array.foldrM_push'
code: @[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
    (arr.push a).foldrM f init (start := arr.size + 1) = f a init >>= arr.foldrM f 
goal: Array.foldrM f init (arr.push a) (arr.size + 1) = do
  let init ← f a init
  Array.foldrM f init arr arr.size

full_name: Array.foldr_push
code: theorem foldr_push (f : α → β → β) (init : β) (arr : Array α) (a : α) :
    (arr.push a).foldr f init = arr.foldr f (f a init) 
goal: Array.foldr f init (arr.push a) (arr.push a).size = Array.foldr f (f a init) arr arr.size

full_name: Array.foldr_push'
code: @[simp] theorem foldr_push' (f : α → β → β) (init : β) (arr : Array α) (a : α) :
    (arr.push a).foldr f init (start := arr.size + 1) = arr.foldr f (f a init) 
goal: Array.foldr f init (arr.push a) (arr.size + 1) = Array.foldr f (f a init) arr arr.size

full_name: Array.toListAppend_eq
code: @[simp] theorem toListAppend_eq (arr : Array α) (l) : arr.toListAppend l = arr.data ++ l 
goal: arr.toListAppend l = arr.data ++ l

full_name: Array.toList_eq
code: @[simp] theorem toList_eq (arr : Array α) : arr.toList = arr.data 
goal: arr.toList = arr.data

full_name: Array.toListRev
code: /-- A more efficient version of `arr.toList.reverse`. -/
@[inline] def toListRev (arr : Array α) : List α 
goal: List α

full_name: Array.toListRev_eq
code: @[simp] theorem toListRev_eq (arr : Array α) : arr.toListRev = arr.data.reverse 
goal: arr.toListRev = arr.data.reverse

full_name: Array.get_push_lt
code: theorem get_push_lt (a : Array α) (x : α) (i : Nat) (h : i < a.size) :
    have : i < (a.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt]
    (a.push x)[i] = a[i] 
goal: let_fun this := ⋯;
(a.push x)[i] = a[i]

full_name: Array.get_push_eq
code: @[simp] theorem get_push_eq (a : Array α) (x : α) : (a.push x)[a.size] = x 
goal: (a.push x)[a.size] = x

full_name: Array.get_push
code: theorem get_push (a : Array α) (x : α) (i : Nat) (h : i < (a.push x).size) :
    (a.push x)[i] = if h : i < a.size then a[i] else x 
goal: (a.push x)[i] = if h : i < a.size then a[i] else x

full_name: Array.mapM_eq_foldlM
code: theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) :
    arr.mapM f = arr.foldlM (fun bs a => bs.push <$> f a) #[] 
goal: Array.mapM f arr = Array.foldlM (fun bs a => bs.push <$> f a) #[] arr 0

full_name: Array.mapM_eq_foldlM.aux
code: theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) :
    arr.mapM f = arr.foldlM (fun bs a => bs.push <$> f a) #[] 
goal: Array.mapM.map f arr i r = List.foldlM (fun bs a => bs.push <$> f a) r (List.drop i arr.data)

full_name: Array.map_data
code: @[simp] theorem map_data (f : α → β) (arr : Array α) : (arr.map f).data = arr.data.map f 
goal: (Array.map f arr).data = List.map f arr.data

full_name: Array.size_map
code: @[simp] theorem size_map (f : α → β) (arr : Array α) : (arr.map f).size = arr.size 
goal: (Array.map f arr).size = arr.size

full_name: Array.pop_data
code: @[simp] theorem pop_data (arr : Array α) : arr.pop.data = arr.data.dropLast 
goal: arr.pop.data = arr.data.dropLast

full_name: Array.append_eq_append
code: @[simp] theorem append_eq_append (arr arr' : Array α) : arr.append arr' = arr ++ arr' 
goal: arr.append arr' = arr ++ arr'

full_name: Array.append_data
code: @[simp] theorem append_data (arr arr' : Array α) :
    (arr ++ arr').data = arr.data ++ arr'.data 
goal: (arr ++ arr').data = arr.data ++ arr'.data

full_name: Array.appendList_eq_append
code: @[simp] theorem appendList_eq_append
    (arr : Array α) (l : List α) : arr.appendList l = arr ++ l 
goal: arr.appendList l = arr ++ l

full_name: Array.appendList_data
code: @[simp] theorem appendList_data (arr : Array α) (l : List α) :
    (arr ++ l).data = arr.data ++ l 
goal: (arr ++ l).data = arr.data ++ l

full_name: Array.appendList_nil
code: @[simp] theorem appendList_nil (arr : Array α) : arr ++ ([] : List α) = arr 
goal: arr ++ [] = arr

full_name: Array.appendList_cons
code: @[simp] theorem appendList_cons (arr : Array α) (a : α) (l : List α) :
    arr ++ (a :: l) = arr.push a ++ l 
goal: arr ++ a :: l = arr.push a ++ l

full_name: Array.foldl_data_eq_bind
code: theorem foldl_data_eq_bind (l : List α) (acc : Array β)
    (F : Array β → α → Array β) (G : α → List β)
    (H : ∀ acc a, (F acc a).data = acc.data ++ G a) :
    (l.foldl F acc).data = acc.data ++ l.bind G 
goal: (List.foldl F acc l).data = acc.data ++ l.bind G

full_name: Array.foldl_data_eq_map
code: theorem foldl_data_eq_map (l : List α) (acc : Array β) (G : α → β) :
    (l.foldl (fun acc a => acc.push (G a)) acc).data = acc.data ++ l.map G 
goal: (List.foldl (fun acc a => acc.push (G a)) acc l).data = acc.data ++ List.map G l

full_name: Array.size_uset
code: theorem size_uset (a : Array α) (v i h) : (uset a i v h).size = a.size 
goal: (a.uset i v h).size = a.size

full_name: Array.anyM_eq_anyM_loop
code: theorem anyM_eq_anyM_loop [Monad m] (p : α → m Bool) (as : Array α) (start stop) :
    anyM p as start stop = anyM.loop p as (min stop as.size) (Nat.min_le_right ..) start 
goal: Array.anyM p as start stop = Array.anyM.loop p as (min stop as.size) ⋯ start

full_name: Array.anyM_stop_le_start
code: theorem anyM_stop_le_start [Monad m] (p : α → m Bool) (as : Array α) (start stop)
    (h : min stop as.size ≤ start) : anyM p as start stop = pure false 
goal: Array.anyM p as start stop = pure false

full_name: Array.mem_def
code: theorem mem_def (a : α) (as : Array α) : a ∈ as ↔ a ∈ as.data 
goal: a ∈ as ↔ a ∈ as.data

full_name: Array.get_eq_getElem
code: @[simp] theorem get_eq_getElem (a : Array α) (i : Fin _) : a.get i = a[i.1] 
goal: a.get i = a[↑i]

full_name: Array.getElem?_lt
code: theorem getElem?_lt
    (a : Array α) {i : Nat} (h : i < a.size) : a[i]? = some (a[i]) 
goal: a[i]? = some a[i]

full_name: Array.getElem?_ge
code: theorem getElem?_ge
    (a : Array α) {i : Nat} (h : i ≥ a.size) : a[i]? = none 
goal: a[i]? = none

full_name: Array.get?_eq_getElem?
code: @[simp] theorem get?_eq_getElem? (a : Array α) (i : Nat) : a.get? i = a[i]? 
goal: a.get? i = a[i]?

full_name: Array.getElem?_len_le
code: theorem getElem?_len_le (a : Array α) {i : Nat} (h : a.size ≤ i) : a[i]? = none 
goal: a[i]? = none

full_name: Array.getD_get?
code: theorem getD_get? (a : Array α) (i : Nat) (d : α) :
  Option.getD a[i]? d = if p : i < a.size then a[i]'p else d 
goal: a[i]?.getD d = if p : i < a.size then a[i] else d

full_name: Array.getD_eq_get?
code: @[simp] theorem getD_eq_get? (a : Array α) (n d) : a.getD n d = (a[n]?).getD d 
goal: a.getD n d = a[n]?.getD d

full_name: Array.get!_eq_getD
code: theorem get!_eq_getD [Inhabited α] (a : Array α) : a.get! n = a.getD n default 
goal: a.get! n = a.getD n default

full_name: Array.get!_eq_getElem?
code: @[simp] theorem get!_eq_getElem? [Inhabited α] (a : Array α) (i : Nat) : a.get! i = (a.get? i).getD default 
goal: a.get! i = (a.get? i).getD default

full_name: Array.getElem_set_eq
code: @[simp] theorem getElem_set_eq (a : Array α) (i : Fin a.size) (v : α) {j : Nat}
      (eq : i.val = j) (p : j < (a.set i v).size) :
    (a.set i v)[j]'p = v 
goal: (a.set i v)[j] = v

full_name: Array.getElem_set_ne
code: @[simp] theorem getElem_set_ne (a : Array α) (i : Fin a.size) (v : α) {j : Nat} (pj : j < (a.set i v).size)
    (h : i.val ≠ j) : (a.set i v)[j]'pj = a[j]'(size_set a i v ▸ pj) 
goal: (a.set i v)[j] = a[j]

full_name: Array.getElem_set
code: theorem getElem_set (a : Array α) (i : Fin a.size) (v : α) (j : Nat)
    (h : j < (a.set i v).size) :
    (a.set i v)[j]'h = if i = j then v else a[j]'(size_set a i v ▸ h) 
goal: (a.set i v)[j] = if ↑i = j then v else a[j]

full_name: Array.getElem?_set_eq
code: @[simp] theorem getElem?_set_eq (a : Array α) (i : Fin a.size) (v : α) :
    (a.set i v)[i.1]? = v 
goal: (a.set i v)[↑i]? = some v

full_name: Array.getElem?_set_ne
code: @[simp] theorem getElem?_set_ne (a : Array α) (i : Fin a.size) {j : Nat} (v : α)
    (ne : i.val ≠ j) : (a.set i v)[j]? = a[j]? 
goal: (a.set i v)[j]? = a[j]?

full_name: Array.set!_is_setD
code: @[simp] theorem set!_is_setD : @set! = @setD 
goal: @Array.set! = @Array.setD

full_name: Array.size_setD
code: @[simp] theorem size_setD (a : Array α) (index : Nat) (val : α) :
  (Array.setD a index val).size = a.size 
goal: (a.setD index val).size = a.size

full_name: Array.getElem_setD_eq
code: @[simp] theorem getElem_setD_eq (a : Array α) {i : Nat} (v : α) (h : _) :
  (setD a i v)[i]'h = v 
goal: (a.setD i v)[i] = v

full_name: Array.getElem?_setD_eq
code: @[simp]
theorem getElem?_setD_eq (a : Array α) {i : Nat} (p : i < a.size) (v : α) : (a.setD i v)[i]? = some v 
goal: (a.setD i v)[i]? = some v

full_name: Array.getD_get?_setD
code: /-- Simplifies a normal form from `get!` -/
@[simp] theorem getD_get?_setD (a : Array α) (i : Nat) (v d : α) :
  Option.getD (setD a i v)[i]? d = if i < a.size then v else d 
goal: (a.setD i v)[i]?.getD d = if i < a.size then v else d

full_name: Array.size_ofFn_go
code: @[simp] theorem size_ofFn_go {n} (f : Fin n → α) (i acc) :
    (ofFn.go f i acc).size = acc.size + (n - i) 
goal: (Array.ofFn.go f i acc).size = acc.size + (n - i)

full_name: Array.size_ofFn
code: @[simp] theorem size_ofFn (f : Fin n → α) : (ofFn f).size = n 
goal: (Array.ofFn f).size = n

full_name: Array.getElem_ofFn_go
code: theorem getElem_ofFn_go (f : Fin n → α) (i) {acc k}
    (hki : k < n) (hin : i ≤ n) (hi : i = acc.size)
    (hacc : ∀ j, ∀ hj : j < acc.size, acc[j] = f ⟨j, Nat.lt_of_lt_of_le hj (hi ▸ hin)⟩) :
    haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi ▸ hin)
    (ofFn.go f i acc)[k]'(by simp [*]) = f ⟨k, hki⟩ 
goal: (Array.ofFn.go f i acc)[k] = f ⟨k, hki⟩

full_name: Array.getElem_ofFn
code: @[simp] theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h) :
    (ofFn f)[i] = f ⟨i, size_ofFn f ▸ h⟩ 
goal: (Array.ofFn f)[i] = f ⟨i, ⋯⟩

full_name: Array.mkArray_data
code: /-- # mkArray -/

@[simp] theorem mkArray_data (n : Nat) (v : α) : (mkArray n v).data = List.replicate n v 
goal: (mkArray n v).data = List.replicate n v

full_name: Array.getElem_mkArray
code: @[simp] theorem getElem_mkArray (n : Nat) (v : α) (h : i < (mkArray n v).size) :
    (mkArray n v)[i] = v 
goal: (mkArray n v)[i] = v

full_name: Array.mem_data
code: /-- # mem -/

theorem mem_data {a : α} {l : Array α} : a ∈ l.data ↔ a ∈ l 
goal: a ∈ l.data ↔ a ∈ l

full_name: Array.not_mem_nil
code: theorem not_mem_nil (a : α) : ¬ a ∈ #[] 
goal: ¬a ∈ #[]

full_name: Array.getElem?_mem
code: /-- # get lemmas -/

theorem getElem?_mem {l : Array α} {i : Fin l.size} : l[i] ∈ l 
goal: l[i] ∈ l

full_name: Array.getElem_fin_eq_data_get
code: theorem getElem_fin_eq_data_get (a : Array α) (i : Fin _) : a[i] = a.data.get i 
goal: a[i] = a.data.get i

full_name: Array.ugetElem_eq_getElem
code: @[simp] theorem ugetElem_eq_getElem (a : Array α) {i : USize} (h : i.toNat < a.size) :
  a[i] = a[i.toNat] 
goal: a[i] = a[i.toNat]

full_name: Array.getElem?_eq_getElem
code: theorem getElem?_eq_getElem (a : Array α) (i : Nat) (h : i < a.size) : a[i]? = a[i] 
goal: a[i]? = some a[i]

full_name: Array.get?_len_le
code: theorem get?_len_le (a : Array α) (i : Nat) (h : a.size ≤ i) : a[i]? = none 
goal: a[i]? = none

full_name: Array.getElem_mem_data
code: theorem getElem_mem_data (a : Array α) (h : i < a.size) : a[i] ∈ a.data 
goal: a[i] ∈ a.data

full_name: Array.getElem?_eq_data_get?
code: theorem getElem?_eq_data_get? (a : Array α) (i : Nat) : a[i]? = a.data.get? i 
goal: a[i]? = a.data.get? i

full_name: Array.get?_eq_data_get?
code: theorem get?_eq_data_get? (a : Array α) (i : Nat) : a.get? i = a.data.get? i 
goal: a.get? i = a.data.get? i

full_name: Array.get!_eq_get?
code: theorem get!_eq_get? [Inhabited α] (a : Array α) : a.get! n = (a.get? n).getD default 
goal: a.get! n = (a.get? n).getD default

full_name: Array.back_eq_back?
code: @[simp] theorem back_eq_back? [Inhabited α] (a : Array α) : a.back = a.back?.getD default 
goal: a.back = a.back?.getD default

full_name: Array.back?_push
code: @[simp] theorem back?_push (a : Array α) : (a.push x).back? = some x 
goal: (a.push x).back? = some x

full_name: Array.back_push
code: theorem back_push [Inhabited α] (a : Array α) : (a.push x).back = x 
goal: (a.push x).back = x

full_name: Array.get?_push_lt
code: theorem get?_push_lt (a : Array α) (x : α) (i : Nat) (h : i < a.size) :
    (a.push x)[i]? = some a[i] 
goal: (a.push x)[i]? = some a[i]

full_name: Array.get?_push_eq
code: theorem get?_push_eq (a : Array α) (x : α) : (a.push x)[a.size]? = some x 
goal: (a.push x)[a.size]? = some x

full_name: Array.get?_push
code: theorem get?_push {a : Array α} : (a.push x)[i]? = if i = a.size then some x else a[i]? 
goal: (a.push x)[i]? = if i = a.size then some x else a[i]?

full_name: Array.get?_size
code: @[simp] theorem get?_size {a : Array α} : a[a.size]? = none 
goal: a[a.size]? = none

full_name: Array.data_set
code: @[simp] theorem data_set (a : Array α) (i v) : (a.set i v).data = a.data.set i.1 v 
goal: (a.set i v).data = a.data.set (↑i) v

full_name: Array.get_set_eq
code: theorem get_set_eq (a : Array α) (i : Fin a.size) (v : α) :
    (a.set i v)[i.1] = v 
goal: (a.set i v)[↑i] = v

full_name: Array.get?_set_eq
code: theorem get?_set_eq (a : Array α) (i : Fin a.size) (v : α) :
    (a.set i v)[i.1]? = v 
goal: (a.set i v)[↑i]? = some v

full_name: Array.get?_set_ne
code: @[simp] theorem get?_set_ne (a : Array α) (i : Fin a.size) {j : Nat} (v : α)
    (h : i.1 ≠ j) : (a.set i v)[j]? = a[j]? 
goal: (a.set i v)[j]? = a[j]?

full_name: Array.get?_set
code: theorem get?_set (a : Array α) (i : Fin a.size) (j : Nat) (v : α) :
    (a.set i v)[j]? = if i.1 = j then some v else a[j]? 
goal: (a.set i v)[j]? = if ↑i = j then some v else a[j]?

full_name: Array.get_set
code: theorem get_set (a : Array α) (i : Fin a.size) (j : Nat) (hj : j < a.size) (v : α) :
    (a.set i v)[j]'(by simp [*]) = if i = j then v else a[j] 
goal: (a.set i v)[j] = if ↑i = j then v else a[j]

full_name: Array.get_set_ne
code: @[simp] theorem get_set_ne (a : Array α) (i : Fin a.size) {j : Nat} (v : α) (hj : j < a.size)
    (h : i.1 ≠ j) : (a.set i v)[j]'(by simp [*]) = a[j] 
goal: (a.set i v)[j] = a[j]

full_name: Array.getElem_setD
code: theorem getElem_setD (a : Array α) (i : Nat) (v : α) (h : i < (setD a i v).size) :
  (setD a i v)[i] = v 
goal: (a.setD i v)[i] = v

full_name: Array.set_set
code: theorem set_set (a : Array α) (i : Fin a.size) (v v' : α) :
    (a.set i v).set ⟨i, by simp [i.2]⟩ v' = a.set i v' 
goal: (a.set i v).set ⟨↑i, ⋯⟩ v' = a.set i v'

full_name: _private.«.lake».packages.lean4.src.lean.Init.Data.Array.Lemmas.0.Array.fin_cast_val
code: private theorem fin_cast_val (e : n = n') (i : Fin n) : e ▸ i = ⟨i.1, e ▸ i.2⟩ 
goal: e ▸ i = ⟨↑i, ⋯⟩

full_name: Array.swap_def
code: theorem swap_def (a : Array α) (i j : Fin a.size) :
    a.swap i j = (a.set i (a.get j)).set ⟨j.1, by simp [j.2]⟩ (a.get i) 
goal: a.swap i j = (a.set i (a.get j)).set ⟨↑j, ⋯⟩ (a.get i)

full_name: Array.data_swap
code: theorem data_swap (a : Array α) (i j : Fin a.size) :
    (a.swap i j).data = (a.data.set i (a.get j)).set j (a.get i) 
goal: (a.swap i j).data = (a.data.set (↑i) (a.get j)).set (↑j) (a.get i)

full_name: Array.get?_swap
code: theorem get?_swap (a : Array α) (i j : Fin a.size) (k : Nat) : (a.swap i j)[k]? =
    if j = k then some a[i.1] else if i = k then some a[j.1] else a[k]? 
goal: (a.swap i j)[k]? = if ↑j = k then some a[↑i] else if ↑i = k then some a[↑j] else a[k]?

full_name: Array.swapAt_def
code: @[simp] theorem swapAt_def (a : Array α) (i : Fin a.size) (v : α) :
    a.swapAt i v = (a[i.1], a.set i v) 
goal: a.swapAt i v = (a[↑i], a.set i v)

full_name: Array.swapAt!_def
code: theorem swapAt!_def (a : Array α) (i : Nat) (v : α) (h : i < a.size) :
    a.swapAt! i v = (a[i], a.set ⟨i, h⟩ v) 
goal: a.swapAt! i v = (a[i], a.set ⟨i, h⟩ v)

full_name: Array.data_pop
code: @[simp] theorem data_pop (a : Array α) : a.pop.data = a.data.dropLast 
goal: a.pop.data = a.data.dropLast

full_name: Array.pop_empty
code: @[simp] theorem pop_empty : (#[] : Array α).pop = #[] 
goal: #[].pop = #[]

full_name: Array.pop_push
code: @[simp] theorem pop_push (a : Array α) : (a.push x).pop = a 
goal: (a.push x).pop = a

full_name: Array.getElem_pop
code: @[simp] theorem getElem_pop (a : Array α) (i : Nat) (hi : i < a.pop.size) :
    a.pop[i] = a[i]'(Nat.lt_of_lt_of_le (a.size_pop ▸ hi) (Nat.sub_le _ _)) 
goal: a.pop[i] = a[i]

full_name: Array.eq_empty_of_size_eq_zero
code: theorem eq_empty_of_size_eq_zero {as : Array α} (h : as.size = 0) : as = #[] 
goal: as = #[]

full_name: Array.eq_push_pop_back_of_size_ne_zero
code: theorem eq_push_pop_back_of_size_ne_zero [Inhabited α] {as : Array α} (h : as.size ≠ 0) :
    as = as.pop.push as.back 
goal: as = as.pop.push as.back

full_name: Array.eq_push_of_size_ne_zero
code: theorem eq_push_of_size_ne_zero {as : Array α} (h : as.size ≠ 0) :
    ∃ (bs : Array α) (c : α), as = bs.push c 
goal: ∃ bs c, as = bs.push c

full_name: Array.size_eq_length_data
code: theorem size_eq_length_data (as : Array α) : as.size = as.data.length 
goal: as.size = as.data.length

full_name: Array.size_swap!
code: @[simp] theorem size_swap! (a : Array α) (i j) :
    (a.swap! i j).size = a.size 
goal: (a.swap! i j).size = a.size

full_name: Array.size_reverse.go
code: @[simp] theorem size_reverse (a : Array α) : a.reverse.size = a.size 
goal: (Array.reverse.loop as i j).size = as.size

full_name: Array.size_reverse
code: @[simp] theorem size_reverse (a : Array α) : a.reverse.size = a.size 
goal: a.reverse.size = a.size

full_name: Array.size_range
code: @[simp] theorem size_range {n : Nat} : (range n).size = n 
goal: (Array.range n).size = n

full_name: Array.reverse_data.go
code: @[simp] theorem reverse_data (a : Array α) : a.reverse.data = a.data.reverse 
goal: (Array.reverse.loop as i ⟨j, hj⟩).data.get? k = a.data.reverse.get? k

full_name: Array.reverse_data
code: @[simp] theorem reverse_data (a : Array α) : a.reverse.data = a.data.reverse 
goal: a.reverse.data = a.data.reverse

full_name: Array.foldl_induction.go
code: theorem foldl_induction
    {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive 0 init) {f : β → α → β}
    (hf : ∀ i : Fin as.size, ∀ b, motive i.1 b → motive (i.1 + 1) (f b as[i])) :
    motive as.size (as.foldl f init) 
goal: motive as.size (Array.foldlM.loop f as as.size ⋯ i j b)

full_name: Array.foldl_induction
code: theorem foldl_induction
    {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive 0 init) {f : β → α → β}
    (hf : ∀ i : Fin as.size, ∀ b, motive i.1 b → motive (i.1 + 1) (f b as[i])) :
    motive as.size (as.foldl f init) 
goal: motive as.size (Array.foldl f init as 0)

full_name: Array.foldr_induction.go
code: theorem foldr_induction
    {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive as.size init) {f : α → β → β}
    (hf : ∀ i : Fin as.size, ∀ b, motive (i.1 + 1) b → motive i.1 (f as[i] b)) :
    motive 0 (as.foldr f init) 
goal: motive 0 (Array.foldrM.fold f as 0 i hi b)

full_name: Array.foldr_induction
code: theorem foldr_induction
    {as : Array α} (motive : Nat → β → Prop) {init : β} (h0 : motive as.size init) {f : α → β → β}
    (hf : ∀ i : Fin as.size, ∀ b, motive (i.1 + 1) b → motive i.1 (f as[i] b)) :
    motive 0 (as.foldr f init) 
goal: motive 0 (Array.foldr f init as as.size)

full_name: Array.mem_map
code: @[simp] theorem mem_map {f : α → β} {l : Array α} : b ∈ l.map f ↔ ∃ a, a ∈ l ∧ f a = b 
goal: b ∈ Array.map f l ↔ ∃ a, a ∈ l ∧ f a = b

full_name: Array.mapM_eq_mapM_data
code: theorem mapM_eq_mapM_data [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) :
    arr.mapM f = return mk (← arr.data.mapM f) 
goal: Array.mapM f arr = do
  let __do_lift ← List.mapM f arr.data
  pure { data := __do_lift }

full_name: Array.mapM_map_eq_foldl
code: theorem mapM_map_eq_foldl (as : Array α) (f : α → β) (i) :
    mapM.map (m := Id) f as i b = as.foldl (start := i) (fun r a => r.push (f a)) b 
goal: Array.mapM.map f as i b = Array.foldl (fun r a => r.push (f a)) b as i

full_name: Array.map_eq_foldl
code: theorem map_eq_foldl (as : Array α) (f : α → β) :
    as.map f = as.foldl (fun r a => r.push (f a)) #[] 
goal: Array.map f as = Array.foldl (fun r a => r.push (f a)) #[] as 0

full_name: Array.map_induction
code: theorem map_induction (as : Array α) (f : α → β) (motive : Nat → Prop) (h0 : motive 0)
    (p : Fin as.size → β → Prop) (hs : ∀ i, motive i.1 → p i (f as[i]) ∧ motive (i+1)) :
    motive as.size ∧
      ∃ eq : (as.map f).size = as.size, ∀ i h, p ⟨i, h⟩ ((as.map f)[i]) 
goal: motive as.size ∧ ∃ eq, ∀ (i : Nat) (h : i < as.size), p ⟨i, h⟩ (Array.map f as)[i]

full_name: Array.map_spec
code: theorem map_spec (as : Array α) (f : α → β) (p : Fin as.size → β → Prop)
    (hs : ∀ i, p i (f as[i])) :
    ∃ eq : (as.map f).size = as.size, ∀ i h, p ⟨i, h⟩ ((as.map f)[i]) 
goal: ∃ eq, ∀ (i : Nat) (h : i < as.size), p ⟨i, h⟩ (Array.map f as)[i]

full_name: Array.getElem_map
code: @[simp] theorem getElem_map (f : α → β) (as : Array α) (i : Nat) (h) :
    ((as.map f)[i]) = f (as[i]'(size_map .. ▸ h)) 
goal: (Array.map f as)[i] = f as[i]

full_name: Array.mapIdx_induction.go
code: theorem mapIdx_induction (as : Array α) (f : Fin as.size → α → β)
    (motive : Nat → Prop) (h0 : motive 0)
    (p : Fin as.size → β → Prop)
    (hs : ∀ i, motive i.1 → p i (f i as[i]) ∧ motive (i + 1)) :
    motive as.size ∧ ∃ eq : (Array.mapIdx as f).size = as.size,
      ∀ i h, p ⟨i, h⟩ ((Array.mapIdx as f)[i]) 
goal: let arr := Array.mapIdxM.map as f i j h bs;
motive as.size ∧ ∃ eq, ∀ (i_1 : Nat) (h : i_1 < as.size), p ⟨i_1, h⟩ arr[i_1]

full_name: Array.mapIdx_induction
code: theorem mapIdx_induction (as : Array α) (f : Fin as.size → α → β)
    (motive : Nat → Prop) (h0 : motive 0)
    (p : Fin as.size → β → Prop)
    (hs : ∀ i, motive i.1 → p i (f i as[i]) ∧ motive (i + 1)) :
    motive as.size ∧ ∃ eq : (Array.mapIdx as f).size = as.size,
      ∀ i h, p ⟨i, h⟩ ((Array.mapIdx as f)[i]) 
goal: motive as.size ∧ ∃ eq, ∀ (i : Nat) (h : i < as.size), p ⟨i, h⟩ (as.mapIdx f)[i]

full_name: Array.mapIdx_spec
code: theorem mapIdx_spec (as : Array α) (f : Fin as.size → α → β)
    (p : Fin as.size → β → Prop) (hs : ∀ i, p i (f i as[i])) :
    ∃ eq : (Array.mapIdx as f).size = as.size,
      ∀ i h, p ⟨i, h⟩ ((Array.mapIdx as f)[i]) 
goal: ∃ eq, ∀ (i : Nat) (h : i < as.size), p ⟨i, h⟩ (as.mapIdx f)[i]

full_name: Array.size_mapIdx
code: @[simp] theorem size_mapIdx (a : Array α) (f : Fin a.size → α → β) : (a.mapIdx f).size = a.size 
goal: (a.mapIdx f).size = a.size

full_name: Array.size_zipWithIndex
code: @[simp] theorem size_zipWithIndex (as : Array α) : as.zipWithIndex.size = as.size 
goal: as.zipWithIndex.size = as.size

full_name: Array.getElem_mapIdx
code: @[simp] theorem getElem_mapIdx (a : Array α) (f : Fin a.size → α → β) (i : Nat)
    (h : i < (mapIdx a f).size) :
    haveI : i < a.size := by simp_all
    (a.mapIdx f)[i] = f ⟨i, this⟩ a[i] 
goal: (a.mapIdx f)[i] = f ⟨i, ⋯⟩ a[i]

full_name: Array.size_modify
code: @[simp] theorem size_modify (a : Array α) (i : Nat) (f : α → α) : (a.modify i f).size = a.size 
goal: (a.modify i f).size = a.size

full_name: Array.get_modify
code: theorem get_modify {arr : Array α} {x i} (h : i < arr.size) :
    (arr.modify x f).get ⟨i, by simp [h]⟩ =
    if x = i then f (arr.get ⟨i, h⟩) else arr.get ⟨i, h⟩ 
goal: (arr.modify x f).get ⟨i, ⋯⟩ = if x = i then f (arr.get ⟨i, h⟩) else arr.get ⟨i, h⟩

full_name: Array.filter_data
code: @[simp] theorem filter_data (p : α → Bool) (l : Array α) :
    (l.filter p).data = l.data.filter p 
goal: (Array.filter p l 0).data = List.filter p l.data

full_name: Array.filter_filter
code: @[simp] theorem filter_filter (q) (l : Array α) :
    filter p (filter q l) = filter (fun a => p a ∧ q a) l 
goal: Array.filter p (Array.filter q l 0) 0 = Array.filter (fun a => decide (p a = true ∧ q a = true)) l 0

full_name: Array.mem_filter
code: @[simp] theorem mem_filter : x ∈ filter p as ↔ x ∈ as ∧ p x 
goal: ∀ {α : Type u_1} {x : α} {p : α → Bool} {as : Array α}, x ∈ Array.filter p as 0 ↔ x ∈ as ∧ p x = true

full_name: Array.mem_of_mem_filter
code: theorem mem_of_mem_filter {a : α} {l} (h : a ∈ filter p l) : a ∈ l 
goal: a ∈ l

full_name: Array.filterMap_data
code: @[simp] theorem filterMap_data (f : α → Option β) (l : Array α) :
    (l.filterMap f).data = l.data.filterMap f 
goal: (Array.filterMap f l 0).data = List.filterMap f l.data

full_name: Array.mem_filterMap
code: @[simp] theorem mem_filterMap (f : α → Option β) (l : Array α) {b : β} :
    b ∈ filterMap f l ↔ ∃ a, a ∈ l ∧ f a = some b 
goal: b ∈ Array.filterMap f l 0 ↔ ∃ a, a ∈ l ∧ f a = some b

full_name: Array.size_empty
code: theorem size_empty : (#[] : Array α).size = 0 
goal: #[].size = 0

full_name: Array.empty_data
code: theorem empty_data : (#[] : Array α).data = [] 
goal: #[].data = []

full_name: Array.push_eq_append_singleton
code: theorem push_eq_append_singleton (as : Array α) (x) : as.push x = as ++ #[x] 
goal: as.push x = as ++ #[x]

full_name: Array.mem_append
code: @[simp] theorem mem_append {a : α} {s t : Array α} : a ∈ s ++ t ↔ a ∈ s ∨ a ∈ t 
goal: a ∈ s ++ t ↔ a ∈ s ∨ a ∈ t

full_name: Array.size_append
code: theorem size_append (as bs : Array α) : (as ++ bs).size = as.size + bs.size 
goal: (as ++ bs).size = as.size + bs.size

full_name: Array.get_append_left
code: theorem get_append_left {as bs : Array α} {h : i < (as ++ bs).size} (hlt : i < as.size) :
    (as ++ bs)[i] = as[i] 
goal: (as ++ bs)[i] = as[i]

full_name: Array.get_append_right
code: theorem get_append_right {as bs : Array α} {h : i < (as ++ bs).size} (hle : as.size ≤ i)
    (hlt : i - as.size < bs.size := Nat.sub_lt_left_of_lt_add hle (size_append .. ▸ h)) :
    (as ++ bs)[i] = bs[i - as.size] 
goal: (as ++ bs)[i] = bs[i - as.size]

full_name: Array.append_nil
code: @[simp] theorem append_nil (as : Array α) : as ++ #[] = as 
goal: as ++ #[] = as

full_name: Array.nil_append
code: @[simp] theorem nil_append (as : Array α) : #[] ++ as = as 
goal: #[] ++ as = as

full_name: Array.append_assoc
code: theorem append_assoc (as bs cs : Array α) : as ++ bs ++ cs = as ++ (bs ++ cs) 
goal: as ++ bs ++ cs = as ++ (bs ++ cs)

full_name: Array.extract_loop_zero
code: theorem extract_loop_zero (as bs : Array α) (start : Nat) : extract.loop as 0 start bs = bs 
goal: Array.extract.loop as 0 start bs = bs

full_name: Array.extract_loop_succ
code: theorem extract_loop_succ (as bs : Array α) (size start : Nat) (h : start < as.size) :
    extract.loop as (size+1) start bs = extract.loop as size (start+1) (bs.push as[start]) 
goal: Array.extract.loop as (size + 1) start bs = Array.extract.loop as size (start + 1) (bs.push as[start])

full_name: Array.extract_loop_of_ge
code: theorem extract_loop_of_ge (as bs : Array α) (size start : Nat) (h : start ≥ as.size) :
    extract.loop as size start bs = bs 
goal: Array.extract.loop as size start bs = bs

full_name: Array.extract_loop_eq_aux
code: theorem extract_loop_eq_aux (as bs : Array α) (size start : Nat) :
    extract.loop as size start bs = bs ++ extract.loop as size start #[] 
goal: Array.extract.loop as size start bs = bs ++ Array.extract.loop as size start #[]

full_name: Array.extract_loop_eq
code: theorem extract_loop_eq (as bs : Array α) (size start : Nat) (h : start + size ≤ as.size) :
  extract.loop as size start bs = bs ++ as.extract start (start + size) 
goal: Array.extract.loop as size start bs = bs ++ as.extract start (start + size)

full_name: Array.size_extract_loop
code: theorem size_extract_loop (as bs : Array α) (size start : Nat) :
    (extract.loop as size start bs).size = bs.size + min size (as.size - start) 
goal: (Array.extract.loop as size start bs).size = bs.size + min size (as.size - start)

full_name: Array.size_extract
code: @[simp] theorem size_extract (as : Array α) (start stop : Nat) :
    (as.extract start stop).size = min stop as.size - start 
goal: (as.extract start stop).size = min stop as.size - start

full_name: Array.get_extract_loop_lt_aux
code: theorem get_extract_loop_lt_aux (as bs : Array α) (size start : Nat) (hlt : i < bs.size) :
    i < (extract.loop as size start bs).size 
goal: i < (Array.extract.loop as size start bs).size

full_name: Array.get_extract_loop_lt
code: theorem get_extract_loop_lt (as bs : Array α) (size start : Nat) (hlt : i < bs.size)
    (h := get_extract_loop_lt_aux as bs size start hlt) :
    (extract.loop as size start bs)[i] = bs[i] 
goal: (Array.extract.loop as size start bs)[i] = bs[i]

full_name: Array.get_extract_loop_ge_aux
code: theorem get_extract_loop_ge_aux (as bs : Array α) (size start : Nat) (hge : i ≥ bs.size)
    (h : i < (extract.loop as size start bs).size) : start + i - bs.size < as.size 
goal: start + i - bs.size < as.size

full_name: Array.get_extract_loop_ge
code: theorem get_extract_loop_ge (as bs : Array α) (size start : Nat) (hge : i ≥ bs.size)
    (h : i < (extract.loop as size start bs).size)
    (h' := get_extract_loop_ge_aux as bs size start hge h) :
    (extract.loop as size start bs)[i] = as[start + i - bs.size] 
goal: (Array.extract.loop as size start bs)[i] = as[start + i - bs.size]

full_name: Array.get_extract_aux
code: theorem get_extract_aux {as : Array α} {start stop : Nat} (h : i < (as.extract start stop).size) :
    start + i < as.size 
goal: start + i < as.size

full_name: Array.get_extract
code: @[simp] theorem get_extract {as : Array α} {start stop : Nat}
    (h : i < (as.extract start stop).size) :
    (as.extract start stop)[i] = as[start + i]'(get_extract_aux h) 
goal: (as.extract start stop)[i] = as[start + i]

full_name: Array.extract_all
code: @[simp] theorem extract_all (as : Array α) : as.extract 0 as.size = as 
goal: as.extract 0 as.size = as

full_name: Array.extract_empty_of_stop_le_start
code: theorem extract_empty_of_stop_le_start (as : Array α) {start stop : Nat} (h : stop ≤ start) :
    as.extract start stop = #[] 
goal: as.extract start stop = #[]

full_name: Array.extract_empty_of_size_le_start
code: theorem extract_empty_of_size_le_start (as : Array α) {start stop : Nat} (h : as.size ≤ start) :
    as.extract start stop = #[] 
goal: as.extract start stop = #[]

full_name: Array.extract_empty
code: @[simp] theorem extract_empty (start stop : Nat) : (#[] : Array α).extract start stop = #[] 
goal: #[].extract start stop = #[]

full_name: Array.anyM_loop_iff_exists
code: theorem anyM_loop_iff_exists (p : α → Bool) (as : Array α) (start stop) (h : stop ≤ as.size) :
    anyM.loop (m := Id) p as stop h start = true ↔
      ∃ i : Fin as.size, start ≤ ↑i ∧ ↑i < stop ∧ p as[i] = true 
goal: Array.anyM.loop p as stop h start = true ↔ ∃ i, start ≤ ↑i ∧ ↑i < stop ∧ p as[i] = true

full_name: Array.any_iff_exists
code: theorem any_iff_exists (p : α → Bool) (as : Array α) (start stop) :
    any as p start stop ↔ ∃ i : Fin as.size, start ≤ i.1 ∧ i.1 < stop ∧ p as[i] 
goal: as.any p start stop = true ↔ ∃ i, start ≤ ↑i ∧ ↑i < stop ∧ p as[i] = true

full_name: Array.any_eq_true
code: theorem any_eq_true (p : α → Bool) (as : Array α) :
    any as p ↔ ∃ i : Fin as.size, p as[i] 
goal: as.any p 0 = true ↔ ∃ i, p as[i] = true

full_name: Array.any_def
code: theorem any_def {p : α → Bool} (as : Array α) : as.any p = as.data.any p 
goal: as.any p 0 = as.data.any p

full_name: Array.all_eq_not_any_not
code: theorem all_eq_not_any_not (p : α → Bool) (as : Array α) (start stop) :
    all as p start stop = !(any as (!p ·) start stop) 
goal: as.all p start stop = !as.any (fun x => !p x) start stop

full_name: Array.all_iff_forall
code: theorem all_iff_forall (p : α → Bool) (as : Array α) (start stop) :
    all as p start stop ↔ ∀ i : Fin as.size, start ≤ i.1 ∧ i.1 < stop → p as[i] 
goal: as.all p start stop = true ↔ ∀ (i : Fin as.size), start ≤ ↑i ∧ ↑i < stop → p as[i] = true

full_name: Array.all_eq_true
code: theorem all_eq_true (p : α → Bool) (as : Array α) : all as p ↔ ∀ i : Fin as.size, p as[i] 
goal: as.all p 0 = true ↔ ∀ (i : Fin as.size), p as[i] = true

full_name: Array.all_def
code: theorem all_def {p : α → Bool} (as : Array α) : as.all p = as.data.all p 
goal: as.all p 0 = as.data.all p

full_name: Array.all_eq_true_iff_forall_mem
code: theorem all_eq_true_iff_forall_mem {l : Array α} : l.all p ↔ ∀ x, x ∈ l → p x 
goal: l.all p 0 = true ↔ ∀ (x : α), x ∈ l → p x = true

full_name: Array.contains_def
code: theorem contains_def [DecidableEq α] {a : α} {as : Array α} : as.contains a ↔ a ∈ as 
goal: as.contains a = true ↔ a ∈ as

full_name: Array.«instDecidableMemOfDecidableEq_.lake»
code: instance [DecidableEq α] (a : α) (as : Array α) : Decidable (a ∈ as) 
goal: Decidable (a ∈ as)

full_name: Array.get_swap_right
code: @[simp] theorem get_swap_right (a : Array α) {i j : Fin a.size} : (a.swap i j)[j.val] = a[i] 
goal: (a.swap i j)[↑j] = a[i]

full_name: Array.get_swap_left
code: @[simp] theorem get_swap_left (a : Array α) {i j : Fin a.size} : (a.swap i j)[i.val] = a[j] 
goal: (a.swap i j)[↑i] = a[j]

full_name: Array.get_swap_of_ne
code: @[simp] theorem get_swap_of_ne (a : Array α) {i j : Fin a.size} (hp : p < a.size)
    (hi : p ≠ i) (hj : p ≠ j) : (a.swap i j)[p]'(a.size_swap .. |>.symm ▸ hp) = a[p] 
goal: (a.swap i j)[p] = a[p]

full_name: Array.get_swap
code: theorem get_swap (a : Array α) (i j : Fin a.size) (k : Nat) (hk: k < a.size) :
    (a.swap i j)[k]'(by simp_all) = if k = i then a[j] else if k = j then a[i]  else a[k] 
goal: (a.swap i j)[k] = if k = ↑i then a[j] else if k = ↑j then a[i] else a[k]

full_name: Array.get_swap'
code: theorem get_swap' (a : Array α) (i j : Fin a.size) (k : Nat) (hk' : k < (a.swap i j).size) :
    (a.swap i j)[k] = if k = i then a[j] else if k = j then a[i] else a[k]'(by simp_all) 
goal: (a.swap i j)[k] = if k = ↑i then a[j] else if k = ↑j then a[i] else a[k]

full_name: Array.swap_swap
code: @[simp] theorem swap_swap (a : Array α) {i j : Fin a.size} :
    (a.swap i j).swap ⟨i.1, (a.size_swap ..).symm ▸i.2⟩ ⟨j.1, (a.size_swap ..).symm ▸j.2⟩ = a 
goal: (a.swap i j).swap ⟨↑i, ⋯⟩ ⟨↑j, ⋯⟩ = a

full_name: Array.swap_comm
code: theorem swap_comm (a : Array α) {i j : Fin a.size} : a.swap i j = a.swap j i 
goal: a.swap i j = a.swap j i