Module docstring
{"### modifyHead ","### modifyTailIdx ","### modify "}
{"### modifyHead ","### modifyTailIdx ","### modify "}
List.length_modifyHead
      theorem
     {f : α → α} {l : List α} : (l.modifyHead f).length = l.length
        @[simp] theorem length_modifyHead {f : α → α} {l : List α} : (l.modifyHead f).length = l.length := by
  cases l <;> simp [modifyHead]
        List.modifyHead_eq_set
      theorem
     [Inhabited α] (f : α → α) (l : List α) : l.modifyHead f = l.set 0 (f (l[0]?.getD default))
        theorem modifyHead_eq_set [Inhabited α] (f : α → α) (l : List α) :
    l.modifyHead f = l.set 0 (f (l[0]?.getD default)) := by cases l <;> simp [modifyHead]
        List.modifyHead_eq_nil_iff
      theorem
     {f : α → α} {l : List α} : l.modifyHead f = [] ↔ l = []
        @[simp] theorem modifyHead_eq_nil_iff {f : α → α} {l : List α} :
    l.modifyHead f = [] ↔ l = [] := by cases l <;> simp [modifyHead]
        List.modifyHead_modifyHead
      theorem
     {l : List α} {f g : α → α} : (l.modifyHead f).modifyHead g = l.modifyHead (g ∘ f)
        @[simp] theorem modifyHead_modifyHead {l : List α} {f g : α → α} :
    (l.modifyHead f).modifyHead g = l.modifyHead (g ∘ f) := by cases l <;> simp [modifyHead]
        List.getElem_modifyHead
      theorem
     {l : List α} {f : α → α} {i} (h : i < (l.modifyHead f).length) :
  (l.modifyHead f)[i] = if h' : i = 0 then f (l[0]'(by simp at h; omega)) else l[i]'(by simpa using h)
        theorem getElem_modifyHead {l : List α} {f : α → α} {i} (h : i < (l.modifyHead f).length) :
    (l.modifyHead f)[i] = if h' : i = 0 then f (l[0]'(by simp at h; omega)) else l[i]'(by simpa using h) := by
  cases l with
  | nil => simp at h
  | cons hd tl => cases i <;> simp
        List.getElem_modifyHead_zero
      theorem
     {l : List α} {f : α → α} {h} : (l.modifyHead f)[0] = f (l[0]'(by simpa using h))
        @[simp] theorem getElem_modifyHead_zero {l : List α} {f : α → α} {h} :
    (l.modifyHead f)[0] = f (l[0]'(by simpa using h)) := by simp [getElem_modifyHead]
        List.getElem_modifyHead_succ
      theorem
     {l : List α} {f : α → α} {n} (h : n + 1 < (l.modifyHead f).length) :
  (l.modifyHead f)[n + 1] = l[n + 1]'(by simpa using h)
        @[simp] theorem getElem_modifyHead_succ {l : List α} {f : α → α} {n} (h : n + 1 < (l.modifyHead f).length) :
    (l.modifyHead f)[n + 1] = l[n + 1]'(by simpa using h) := by simp [getElem_modifyHead]
        List.getElem?_modifyHead
      theorem
     {l : List α} {f : α → α} {i} : (l.modifyHead f)[i]? = if i = 0 then l[i]?.map f else l[i]?
        theorem getElem?_modifyHead {l : List α} {f : α → α} {i} :
    (l.modifyHead f)[i]? = if i = 0 then l[i]?.map f else l[i]? := by
  cases l with
  | nil => simp
  | cons hd tl => cases i <;> simp
        List.getElem?_modifyHead_zero
      theorem
     {l : List α} {f : α → α} : (l.modifyHead f)[0]? = l[0]?.map f
        @[simp] theorem getElem?_modifyHead_zero {l : List α} {f : α → α} :
    (l.modifyHead f)[0]? = l[0]?.map f := by simp [getElem?_modifyHead]
        List.getElem?_modifyHead_succ
      theorem
     {l : List α} {f : α → α} {n} : (l.modifyHead f)[n + 1]? = l[n + 1]?
        @[simp] theorem getElem?_modifyHead_succ {l : List α} {f : α → α} {n} :
    (l.modifyHead f)[n + 1]? = l[n + 1]? := by simp [getElem?_modifyHead]
        List.head_modifyHead
      theorem
     (f : α → α) (l : List α) (h) : (l.modifyHead f).head h = f (l.head (by simpa using h))
        @[simp] theorem head_modifyHead (f : α → α) (l : List α) (h) :
    (l.modifyHead f).head h = f (l.head (by simpa using h)) := by
  cases l with
  | nil => simp at h
  | cons hd tl => simp
        List.head?_modifyHead
      theorem
     {l : List α} {f : α → α} : (l.modifyHead f).head? = l.head?.map f
        @[simp] theorem head?_modifyHead {l : List α} {f : α → α} :
    (l.modifyHead f).head? = l.head?.map f := by cases l <;> simp
        List.tail_modifyHead
      theorem
     {f : α → α} {l : List α} : (l.modifyHead f).tail = l.tail
        @[simp] theorem tail_modifyHead {f : α → α} {l : List α} :
    (l.modifyHead f).tail = l.tail := by cases l <;> simp
        List.take_modifyHead
      theorem
     {f : α → α} {l : List α} {i} : (l.modifyHead f).take i = (l.take i).modifyHead f
        @[simp] theorem take_modifyHead {f : α → α} {l : List α} {i} :
    (l.modifyHead f).take i = (l.take i).modifyHead f := by
  cases l <;> cases i <;> simp
        List.drop_modifyHead_of_pos
      theorem
     {f : α → α} {l : List α} {i} (h : 0 < i) : (l.modifyHead f).drop i = l.drop i
        @[simp] theorem drop_modifyHead_of_pos {f : α → α} {l : List α} {i} (h : 0 < i) :
    (l.modifyHead f).drop i = l.drop i := by
  cases l <;> cases i <;> simp_all
        List.eraseIdx_modifyHead_zero
      theorem
     {f : α → α} {l : List α} : (l.modifyHead f).eraseIdx 0 = l.eraseIdx 0
        theorem eraseIdx_modifyHead_zero {f : α → α} {l : List α} :
    (l.modifyHead f).eraseIdx 0 = l.eraseIdx 0 := by simp
        List.eraseIdx_modifyHead_of_pos
      theorem
     {f : α → α} {l : List α} {i} (h : 0 < i) : (l.modifyHead f).eraseIdx i = (l.eraseIdx i).modifyHead f
        @[simp] theorem eraseIdx_modifyHead_of_pos {f : α → α} {l : List α} {i} (h : 0 < i) :
    (l.modifyHead f).eraseIdx i = (l.eraseIdx i).modifyHead f := by cases l <;> cases i <;> simp_all
        List.modifyHead_id
      theorem
     : modifyHead (id : α → α) = id
        @[simp] theorem modifyHead_id : modifyHead (id : α → α) = id := by funext l; cases l <;> simp
        List.modifyHead_dropLast
      theorem
     {l : List α} {f : α → α} : l.dropLast.modifyHead f = (l.modifyHead f).dropLast
        @[simp] theorem modifyHead_dropLast {l : List α} {f : α → α} :
    l.dropLast.modifyHead f = (l.modifyHead f).dropLast := by
  rcases l with _|⟨a, l⟩
  · simp
  · rcases l with _|⟨b, l⟩ <;> simp
        List.modifyTailIdx_id
      theorem
     : ∀ i (l : List α), l.modifyTailIdx i id = l
        @[simp] theorem modifyTailIdx_id : ∀ i (l : List α), l.modifyTailIdx i id = l
  | 0, _ => rfl
  | _+1, [] => rfl
  | n+1, a :: l => congrArg (cons a) (modifyTailIdx_id n l)
        List.eraseIdx_eq_modifyTailIdx
      theorem
     : ∀ i (l : List α), eraseIdx l i = l.modifyTailIdx i tail
        theorem eraseIdx_eq_modifyTailIdx : ∀ i (l : List α), eraseIdx l i = l.modifyTailIdx i tail
  | 0, l => by cases l <;> rfl
  | _+1, [] => rfl
  | _+1, _ :: _ => congrArg (cons _) (eraseIdx_eq_modifyTailIdx _ _)
        List.length_modifyTailIdx
      theorem
     (f : List α → List α) (H : ∀ l, (f l).length = l.length) : ∀ (l : List α) i, (l.modifyTailIdx i f).length = l.length
        
      List.modifyTailIdx_add
      theorem
     (f : List α → List α) (i) (l₁ l₂ : List α) : (l₁ ++ l₂).modifyTailIdx (l₁.length + i) f = l₁ ++ l₂.modifyTailIdx i f
        theorem modifyTailIdx_add (f : List α → List α) (i) (l₁ l₂ : List α) :
    (l₁ ++ l₂).modifyTailIdx (l₁.length + i) f = l₁ ++ l₂.modifyTailIdx i f := by
  induction l₁ <;> simp [*, Nat.succ_add]
        List.modifyTailIdx_eq_take_drop
      theorem
     (f : List α → List α) (H : f [] = []) : ∀ (l : List α) i, l.modifyTailIdx i f = l.take i ++ f (l.drop i)
        
      List.exists_of_modifyTailIdx
      theorem
     (f : List α → List α) {i} {l : List α} (h : i ≤ l.length) :
  ∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.length = i ∧ l.modifyTailIdx i f = l₁ ++ f l₂
        theorem exists_of_modifyTailIdx (f : List α → List α) {i} {l : List α} (h : i ≤ l.length) :
    ∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.length = i ∧ l.modifyTailIdx i f = l₁ ++ f l₂ := by
  obtain ⟨l₁, l₂, rfl, rfl⟩ : ∃ l₁ l₂, l = l₁ ++ l₂ ∧ l₁.length = i :=
    ⟨_, _, (take_append_drop i l).symm, length_take_of_le h⟩
  exact ⟨l₁, l₂, rfl, rfl, modifyTailIdx_add f 0 l₁ l₂⟩
        List.modifyTailIdx_modifyTailIdx
      theorem
     {f g : List α → List α} (i : Nat) :
  ∀ (j) (l : List α),
    (l.modifyTailIdx j f).modifyTailIdx (i + j) g = l.modifyTailIdx j (fun l => (f l).modifyTailIdx i g)
        theorem modifyTailIdx_modifyTailIdx {f g : List α → List α} (i : Nat) :
    ∀ (j) (l : List α),
      (l.modifyTailIdx j f).modifyTailIdx (i + j) g =
        l.modifyTailIdx j (fun l => (f l).modifyTailIdx i g)
  | 0, _ => rfl
  | _ + 1, [] => rfl
  | n + 1, a :: l => congrArg (List.cons a) (modifyTailIdx_modifyTailIdx i n l)
        List.modifyTailIdx_modifyTailIdx_le
      theorem
     {f g : List α → List α} (i j : Nat) (l : List α) (h : j ≤ i) :
  (l.modifyTailIdx j f).modifyTailIdx i g = l.modifyTailIdx j (fun l => (f l).modifyTailIdx (i - j) g)
        theorem modifyTailIdx_modifyTailIdx_le {f g : List α → List α} (i j : Nat) (l : List α)
    (h : j ≤ i) :
    (l.modifyTailIdx j f).modifyTailIdx i g =
      l.modifyTailIdx j (fun l => (f l).modifyTailIdx (i - j) g) := by
  rcases Nat.exists_eq_add_of_le h with ⟨m, rfl⟩
  rw [Nat.add_comm, modifyTailIdx_modifyTailIdx, Nat.add_sub_cancel]
        List.modifyTailIdx_modifyTailIdx_self
      theorem
     {f g : List α → List α} (i : Nat) (l : List α) : (l.modifyTailIdx i f).modifyTailIdx i g = l.modifyTailIdx i (g ∘ f)
        theorem modifyTailIdx_modifyTailIdx_self {f g : List α → List α} (i : Nat) (l : List α) :
    (l.modifyTailIdx i f).modifyTailIdx i g = l.modifyTailIdx i (g ∘ f) := by
  rw [modifyTailIdx_modifyTailIdx_le i i l (Nat.le_refl i), Nat.sub_self]; rfl
        List.modify_nil
      theorem
     (f : α → α) (i) : [].modify i f = []
        @[simp] theorem modify_nil (f : α → α) (i) : [].modify i f = [] := by cases i <;> rfl
        List.modify_zero_cons
      theorem
     (f : α → α) (a : α) (l : List α) : (a :: l).modify 0 f = f a :: l
        
      List.modify_succ_cons
      theorem
     (f : α → α) (a : α) (l : List α) (i) : (a :: l).modify (i + 1) f = a :: l.modify i f
        @[simp] theorem modify_succ_cons (f : α → α) (a : α) (l : List α) (i) :
    (a :: l).modify (i + 1) f = a :: l.modify i f := by rfl
        List.modifyHead_eq_modify_zero
      theorem
     (f : α → α) (l : List α) : l.modifyHead f = l.modify 0 f
        theorem modifyHead_eq_modify_zero (f : α → α) (l : List α) :
    l.modifyHead f = l.modify 0 f := by cases l <;> simp
        List.modify_eq_nil_iff
      theorem
     {f : α → α} {i} {l : List α} : l.modify i f = [] ↔ l = []
        @[simp] theorem modify_eq_nil_iff {f : α → α} {i} {l : List α} :
    l.modify i f = [] ↔ l = [] := by cases l <;> cases i <;> simp
        List.getElem?_modify
      theorem
     (f : α → α) : ∀ i (l : List α) j, (l.modify i f)[j]? = (fun a => if i = j then f a else a) <$> l[j]?
        theorem getElem?_modify (f : α → α) :
    ∀ i (l : List α) j, (l.modify i f)[j]? = (fun a => if i = j then f a else a) <$> l[j]?
  | n, l, 0 => by cases l <;> cases n <;> simp
  | n, [], _+1 => by cases n <;> rfl
  | 0, _ :: l, j+1 => by cases h : l[j]? <;> simp [h, modify, j.succ_ne_zero.symm]
  | i+1, a :: l, j+1 => by
    simp only [modify_succ_cons, getElem?_cons_succ, Nat.reduceEqDiff, Option.map_eq_map]
    refine (getElem?_modify f i l j).trans ?_
    cases h' : l[j]? <;> by_cases h : i = j <;>
      simp [h, if_pos, if_neg, Option.map, mt Nat.succ.inj, not_false_iff, h']
        List.length_modify
      theorem
     (f : α → α) : ∀ (l : List α) i, (l.modify i f).length = l.length
        @[simp] theorem length_modify (f : α → α) : ∀ (l : List α) i, (l.modify i f).length = l.length :=
  length_modifyTailIdx _ fun l => by cases l <;> rfl
        List.getElem?_modify_eq
      theorem
     (f : α → α) (i) (l : List α) : (l.modify i f)[i]? = f <$> l[i]?
        @[simp] theorem getElem?_modify_eq (f : α → α) (i) (l : List α) :
    (l.modify i f)[i]? = f <$> l[i]? := by
  simp only [getElem?_modify, if_pos]
        List.getElem?_modify_ne
      theorem
     (f : α → α) {i j} (l : List α) (h : i ≠ j) : (l.modify i f)[j]? = l[j]?
        @[simp] theorem getElem?_modify_ne (f : α → α) {i j} (l : List α) (h : i ≠ j) :
    (l.modify i f)[j]? = l[j]? := by
  simp only [getElem?_modify, if_neg h, id_map']
        List.getElem_modify
      theorem
     (f : α → α) (i) (l : List α) (j) (h : j < (l.modify i f).length) :
  (l.modify i f)[j] = if i = j then f (l[j]'(by simp at h; omega)) else l[j]'(by simp at h; omega)
        theorem getElem_modify (f : α → α) (i) (l : List α) (j) (h : j < (l.modify i f).length) :
    (l.modify i f)[j] =
      if i = j then f (l[j]'(by simp at h; omega)) else l[j]'(by simp at h; omega) := by
  rw [getElem_eq_iff, getElem?_modify]
  simp at h
  simp [h]
        List.getElem_modify_eq
      theorem
     (f : α → α) (i) (l : List α) (h) : (l.modify i f)[i] = f (l[i]'(by simpa using h))
        @[simp] theorem getElem_modify_eq (f : α → α) (i) (l : List α) (h) :
    (l.modify i f)[i] = f (l[i]'(by simpa using h)) := by simp [getElem_modify]
        List.getElem_modify_ne
      theorem
     (f : α → α) {i j} (l : List α) (h : i ≠ j) (h') : (l.modify i f)[j] = l[j]'(by simpa using h')
        @[simp] theorem getElem_modify_ne (f : α → α) {i j} (l : List α) (h : i ≠ j) (h') :
    (l.modify i f)[j] = l[j]'(by simpa using h') := by simp [getElem_modify, h]
        List.modify_eq_self
      theorem
     {f : α → α} {i} {l : List α} (h : l.length ≤ i) : l.modify i f = l
        theorem modify_eq_self {f : α → α} {i} {l : List α} (h : l.length ≤ i) :
    l.modify i f = l := by
  apply ext_getElem
  · simp
  · intro m h₁ h₂
    simp only [getElem_modify, ite_eq_right_iff]
    intro h
    omega
        List.modify_modify_eq
      theorem
     (f g : α → α) (i) (l : List α) : (l.modify i f).modify i g = l.modify i (g ∘ f)
        theorem modify_modify_eq (f g : α → α) (i) (l : List α) :
    (l.modify i f).modify i g = l.modify i (g ∘ f) := by
  apply ext_getElem
  · simp
  · intro m h₁ h₂
    simp only [getElem_modify, Function.comp_apply]
    split <;> simp
        List.modify_modify_ne
      theorem
     (f g : α → α) {i j} (l : List α) (h : i ≠ j) : (l.modify i f).modify j g = (l.modify j g).modify i f
        theorem modify_modify_ne (f g : α → α) {i j} (l : List α) (h : i ≠ j) :
    (l.modify i f).modify j g = (l.modify j g).modify i f := by
  apply ext_getElem
  · simp
  · intro m' h₁ h₂
    simp only [getElem_modify, getElem_modify_ne, h₂]
    split <;> split <;> first | rfl | omega
        List.modify_eq_set
      theorem
     [Inhabited α] (f : α → α) (i) (l : List α) : l.modify i f = l.set i (f (l[i]?.getD default))
        theorem modify_eq_set [Inhabited α] (f : α → α) (i) (l : List α) :
    l.modify i f = l.set i (f (l[i]?.getD default)) := by
  apply ext_getElem
  · simp
  · intro m h₁ h₂
    simp [getElem_modify, getElem_set, h₂]
    split <;> rename_i h
    · subst h
      simp only [length_modify] at h₁
      simp [h₁]
    · rfl
        List.modify_eq_take_drop
      theorem
     (f : α → α) : ∀ (l : List α) i, l.modify i f = l.take i ++ modifyHead f (l.drop i)
        theorem modify_eq_take_drop (f : α → α) :
    ∀ (l : List α) i, l.modify i f = l.take i ++ modifyHead f (l.drop i) :=
  modifyTailIdx_eq_take_drop _ rfl
        List.modify_eq_take_cons_drop
      theorem
     {f : α → α} {i} {l : List α} (h : i < l.length) : l.modify i f = l.take i ++ f l[i] :: l.drop (i + 1)
        theorem modify_eq_take_cons_drop {f : α → α} {i} {l : List α} (h : i < l.length) :
    l.modify i f = l.take i ++ f l[i] :: l.drop (i + 1) := by
  rw [modify_eq_take_drop, drop_eq_getElem_cons h]; rfl
        List.exists_of_modify
      theorem
     (f : α → α) {i} {l : List α} (h : i < l.length) :
  ∃ l₁ a l₂, l = l₁ ++ a :: l₂ ∧ l₁.length = i ∧ l.modify i f = l₁ ++ f a :: l₂
        theorem exists_of_modify (f : α → α) {i} {l : List α} (h : i < l.length) :
    ∃ l₁ a l₂, l = l₁ ++ a :: l₂ ∧ l₁.length = i ∧ l.modify i f = l₁ ++ f a :: l₂ :=
  match exists_of_modifyTailIdx _ (Nat.le_of_lt h) with
  | ⟨_, _::_, eq, hl, H⟩ => ⟨_, _, _, eq, hl, H⟩
  | ⟨_, [], eq, hl, _⟩ => nomatch Nat.ne_of_gt h (eq ▸ append_nil _ ▸ hl)
        List.modify_id
      theorem
     (i) (l : List α) : l.modify i id = l
        
      List.take_modify
      theorem
     (f : α → α) (i j) (l : List α) : (l.modify i f).take j = (l.take j).modify i f
        
      List.drop_modify_of_lt
      theorem
     (f : α → α) (i j) (l : List α) (h : i < j) : (l.modify i f).drop j = l.drop j
        theorem drop_modify_of_lt (f : α → α) (i j) (l : List α) (h : i < j) :
    (l.modify i f).drop j = l.drop j := by
  apply ext_getElem
  · simp
  · intro m' h₁ h₂
    simp only [getElem_drop, getElem_modify, ite_eq_right_iff]
    intro h'
    omega
        List.drop_modify_of_ge
      theorem
     (f : α → α) (i j) (l : List α) (h : i ≥ j) : (l.modify i f).drop j = (l.drop j).modify (i - j) f
        theorem drop_modify_of_ge (f : α → α) (i j) (l : List α) (h : i ≥ j) :
    (l.modify i f).drop j = (l.drop j).modify (i - j) f  := by
  apply ext_getElem
  · simp
  · intro m' h₁ h₂
    simp [getElem_drop, getElem_modify, ite_eq_right_iff]
    split <;> split <;> first | rfl | omega
        List.eraseIdx_modify_of_eq
      theorem
     (f : α → α) (i) (l : List α) : (l.modify i f).eraseIdx i = l.eraseIdx i
        theorem eraseIdx_modify_of_eq (f : α → α) (i) (l : List α) :
    (l.modify i f).eraseIdx i = l.eraseIdx i := by
  apply ext_getElem
  · simp [length_eraseIdx]
  · intro m h₁ h₂
    simp only [getElem_eraseIdx, getElem_modify]
    split <;> split <;> first | rfl | omega
        List.eraseIdx_modify_of_lt
      theorem
     (f : α → α) (i j) (l : List α) (h : j < i) : (l.modify i f).eraseIdx j = (l.eraseIdx j).modify (i - 1) f
        theorem eraseIdx_modify_of_lt (f : α → α) (i j) (l : List α) (h : j < i) :
    (l.modify i f).eraseIdx j = (l.eraseIdx j).modify (i - 1) f := by
  apply ext_getElem
  · simp [length_eraseIdx]
  · intro k h₁ h₂
    simp only [getElem_eraseIdx, getElem_modify]
    by_cases h' : i - 1 = k
    repeat' split
    all_goals (first | rfl | omega)
        List.eraseIdx_modify_of_gt
      theorem
     (f : α → α) (i j) (l : List α) (h : j > i) : (l.modify i f).eraseIdx j = (l.eraseIdx j).modify i f
        theorem eraseIdx_modify_of_gt (f : α → α) (i j) (l : List α) (h : j > i) :
    (l.modify i f).eraseIdx j = (l.eraseIdx j).modify i f := by
  apply ext_getElem
  · simp [length_eraseIdx]
  · intro k h₁ h₂
    simp only [getElem_eraseIdx, getElem_modify]
    by_cases h' : i = k
    repeat' split
    all_goals (first | rfl | omega)
        List.modify_eraseIdx_of_lt
      theorem
     (f : α → α) (i j) (l : List α) (h : j < i) : (l.eraseIdx i).modify j f = (l.modify j f).eraseIdx i
        theorem modify_eraseIdx_of_lt (f : α → α) (i j) (l : List α) (h : j < i) :
    (l.eraseIdx i).modify j f = (l.modify j f).eraseIdx i := by
  apply ext_getElem
  · simp [length_eraseIdx]
  · intro k h₁ h₂
    simp only [getElem_eraseIdx, getElem_modify]
    by_cases h' : j = k + 1
    repeat' split
    all_goals (first | rfl | omega)
        List.modify_eraseIdx_of_ge
      theorem
     (f : α → α) (i j) (l : List α) (h : j ≥ i) : (l.eraseIdx i).modify j f = (l.modify (j + 1) f).eraseIdx i
        theorem modify_eraseIdx_of_ge (f : α → α) (i j) (l : List α) (h : j ≥ i) :
    (l.eraseIdx i).modify j f = (l.modify (j + 1) f).eraseIdx i := by
  apply ext_getElem
  · simp [length_eraseIdx]
  · intro k h₁ h₂
    simp only [getElem_eraseIdx, getElem_modify]
    by_cases h' : j + 1 = k + 1
    repeat' split
    all_goals (first | rfl | omega)