l3lab/ntp-mathlib huggingface dataset:
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    

Proof state:
case succ.mk.nil
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
v : Vector β (Nat.succ n)
w : Vector γ (Nat.succ n)
u_property : List.length [] = Nat.succ n
⊢ C { val := [], property := u_property } v w
case succ.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
v : Vector β (Nat.succ n)
w : Vector γ (Nat.succ n)
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
⊢ C { val := a :: u, property := u_property } v w

Next tactic:
cases u_property
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    

Proof state:
case succ.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
v : Vector β (Nat.succ n)
w : Vector γ (Nat.succ n)
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
⊢ C { val := a :: u, property := u_property } v w

Next tactic:
rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
    

Proof state:
case succ.mk.cons.mk.nil
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
w : Vector γ (Nat.succ n)
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
v_property : List.length [] = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := [], property := v_property } w
case succ.mk.cons.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
w : Vector γ (Nat.succ n)
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := b :: v, property := v_property } w

Next tactic:
cases v_property
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
    cases v_property
    

Proof state:
case succ.mk.cons.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
w : Vector γ (Nat.succ n)
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := b :: v, property := v_property } w

Next tactic:
rcases w with ⟨_ | ⟨c, w⟩, w_property⟩
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
    cases v_property
    rcases w with ⟨_ | ⟨c, w⟩, w_property⟩
    

Proof state:
case succ.mk.cons.mk.cons.mk.nil
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
w_property : List.length [] = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := b :: v, property := v_property }
    { val := [], property := w_property }
case succ.mk.cons.mk.cons.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
c : γ
w : List γ
w_property : List.length (c :: w) = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := b :: v, property := v_property }
    { val := c :: w, property := w_property }

Next tactic:
cases w_property
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
    cases v_property
    rcases w with ⟨_ | ⟨c, w⟩, w_property⟩
    cases w_property
    

Proof state:
case succ.mk.cons.mk.cons.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
c : γ
w : List γ
w_property : List.length (c :: w) = Nat.succ n
⊢ C { val := a :: u, property := u_property } { val := b :: v, property := v_property }
    { val := c :: w, property := w_property }

Next tactic:
apply
      @cons n _ _ _ ⟨u, (add_left_inj 1).mp u_property⟩ ⟨v, (add_left_inj 1).mp v_property⟩
        ⟨w, (add_left_inj 1).mp w_property⟩
/-- Define `C u v w` by induction on a triplet of vectors
`u : Vector α n`, `v : Vector β n`, and `w : Vector γ b`. -/
@[elab_as_elim]
def inductionOn₃ {C : ∀ {n}, Vector α n → Vector β n → Vector γ n → Sort*}
    (u : Vector α n) (v : Vector β n) (w : Vector γ n) (nil : C nil nil nil)
    (cons : ∀ {n a b c} {x : Vector α n} {y z}, C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)) :
    C u v w := by
  -- porting notes: removed `generalizing`: already generalized
  induction' n with n ih
  · rcases u with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases v with ⟨_ | ⟨-, -⟩, - | -⟩
    rcases w with ⟨_ | ⟨-, -⟩, - | -⟩
    exact nil
  · rcases u with ⟨_ | ⟨a, u⟩, u_property⟩
    cases u_property
    rcases v with ⟨_ | ⟨b, v⟩, v_property⟩
    cases v_property
    rcases w with ⟨_ | ⟨c, w⟩, w_property⟩
    cases w_property
    apply
      @cons n _ _ _ ⟨u, (add_left_inj 1).mp u_property⟩ ⟨v, (add_left_inj 1).mp v_property⟩
        ⟨w, (add_left_inj 1).mp w_property⟩
    

Proof state:
case succ.mk.cons.mk.cons.mk.cons
n✝ : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
C : {n : ℕ} → Vector α n → Vector β n → Vector γ n → Sort u_4
nil : C Vector.nil Vector.nil Vector.nil
cons :
  {n : ℕ} →
    {a : α} →
      {b : β} →
        {c : γ} → {x : Vector α n} → {y : Vector β n} → {z : Vector γ n} → C x y z → C (a ::ᵥ x) (b ::ᵥ y) (c ::ᵥ z)
n : ℕ
ih : (u : Vector α n) → (v : Vector β n) → (w : Vector γ n) → C u v w
a : α
u : List α
u_property : List.length (a :: u) = Nat.succ n
b : β
v : List β
v_property : List.length (b :: v) = Nat.succ n
c : γ
w : List γ
w_property : List.length (c :: w) = Nat.succ n
⊢ C { val := u, property := (_ : List.length u = n) } { val := v, property := (_ : List.length v = n) }
    { val := w, property := (_ : List.length w = n) }

Next tactic:
apply ih
/-- Cast a vector to an array. -/
def toArray : Vector α n → Array α
  | ⟨xs, _⟩ => cast (by 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
xs : List α
property✝ : List.length xs = n
⊢ Array α = Array α

Next tactic:
rfl
/-- `v.insertNth a i` inserts `a` into the vector `v` at position `i`
(and shifting later components to the right). -/
def insertNth (a : α) (i : Fin (n + 1)) (v : Vector α n) : Vector α (n + 1) :=
  ⟨v.1.insertNth i a, by
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a : α
i : Fin (n + 1)
v : Vector α n
⊢ List.length (List.insertNth (↑i) a ↑v) = n + 1

Next tactic:
rw [List.length_insertNth, v.2]
/-- `v.insertNth a i` inserts `a` into the vector `v` at position `i`
(and shifting later components to the right). -/
def insertNth (a : α) (i : Fin (n + 1)) (v : Vector α n) : Vector α (n + 1) :=
  ⟨v.1.insertNth i a, by
    rw [List.length_insertNth, v.2]
    

Proof state:
case a
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a : α
i : Fin (n + 1)
v : Vector α n
⊢ ↑i ≤ List.length ↑v

Next tactic:
rw [v.2, ← Nat.succ_le_succ_iff]
/-- `v.insertNth a i` inserts `a` into the vector `v` at position `i`
(and shifting later components to the right). -/
def insertNth (a : α) (i : Fin (n + 1)) (v : Vector α n) : Vector α (n + 1) :=
  ⟨v.1.insertNth i a, by
    rw [List.length_insertNth, v.2]
    rw [v.2, ← Nat.succ_le_succ_iff]
    

Proof state:
case a
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a✝ a : α
i : Fin (n + 1)
v : Vector α n
⊢ Nat.succ ↑i ≤ Nat.succ n

Next tactic:
exact i.2
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
⊢ removeNth (Fin.succAbove { val := j, isLt := hj } { val := i, isLt := hi }) (insertNth a { val := j, isLt := hj } v) =
    insertNth a (Fin.predAbove { val := i, isLt := hi } { val := j, isLt := hj }) (removeNth { val := i, isLt := hi } v)

Next tactic:
dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
⊢ {
      val :=
        List.removeNth (List.insertNth j a ↑v)
          ↑(if i < j then { val := i, isLt := (_ : i < Nat.succ (n + 1)) }
            else { val := i + 1, isLt := (_ : Nat.succ i < Nat.succ (n + 1)) }),
      property :=
        (_ :
          List.length
              (List.removeNth (List.insertNth j a ↑v)
                ↑(if i < j then { val := i, isLt := (_ : i < Nat.succ (n + 1)) }
                  else { val := i + 1, isLt := (_ : Nat.succ i < Nat.succ (n + 1)) })) =
            n + 1 + 1 - 1) } =
    {
      val :=
        List.insertNth
          (↑(if h : { val := i, isLt := (_ : i < Nat.succ (n + 1)) } < { val := j, isLt := hj } then
              Fin.pred { val := j, isLt := hj } (_ : { val := j, isLt := hj } ≠ 0)
            else { val := j, isLt := (_ : ↑{ val := j, isLt := hj } < n + 1) }))
          a
          ↑(match v with
            | { val := l, property := p } =>
              { val := List.removeNth l i,
                property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) }),
      property :=
        (_ :
          List.length
              (List.insertNth
                (↑(if h : { val := i, isLt := (_ : i < Nat.succ (n + 1)) } < { val := j, isLt := hj } then
                    Fin.pred { val := j, isLt := hj } (_ : { val := j, isLt := hj } ≠ 0)
                  else { val := j, isLt := (_ : ↑{ val := j, isLt := hj } < n + 1) }))
                a
                ↑(match v with
                  | { val := l, property := p } =>
                    { val := List.removeNth l i,
                      property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })) =
            n + 1) }

Next tactic:
rw [Subtype.mk_eq_mk]
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
⊢ List.removeNth (List.insertNth j a ↑v)
      ↑(if i < j then { val := i, isLt := (_ : i < Nat.succ (n + 1)) }
        else { val := i + 1, isLt := (_ : Nat.succ i < Nat.succ (n + 1)) }) =
    List.insertNth
      (↑(if h : { val := i, isLt := (_ : i < Nat.succ (n + 1)) } < { val := j, isLt := hj } then
          Fin.pred { val := j, isLt := hj } (_ : { val := j, isLt := hj } ≠ 0)
        else { val := j, isLt := (_ : ↑{ val := j, isLt := hj } < n + 1) }))
      a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
simp only [Fin.lt_iff_val_lt_val]
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
⊢ List.removeNth (List.insertNth j a ↑v)
      ↑(if i < j then { val := i, isLt := (_ : i < Nat.succ (n + 1)) }
        else { val := i + 1, isLt := (_ : Nat.succ i < Nat.succ (n + 1)) }) =
    List.insertNth
      (↑(if h : i < j then Fin.pred { val := j, isLt := hj } (_ : { val := j, isLt := hj } ≠ 0)
        else { val := j, isLt := (_ : ↑{ val := j, isLt := hj } < n + 1) }))
      a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
split_ifs with hij
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · 

Proof state:
case pos
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : j < n + 2
hij : i < j
⊢ List.removeNth (List.insertNth j a ↑v) ↑{ val := i, isLt := (_ : i < Nat.succ (n + 1)) } =
    List.insertNth (↑(Fin.pred { val := j, isLt := hj } (_ : { val := j, isLt := hj } ≠ 0))) a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      

Proof state:
case pos.intro
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : Nat.succ j < n + 2
hij : i < Nat.succ j
⊢ List.removeNth (List.insertNth (Nat.succ j) a ↑v) ↑{ val := i, isLt := (_ : i < Nat.succ (n + 1)) } =
    List.insertNth (↑(Fin.pred { val := Nat.succ j, isLt := hj } (_ : { val := Nat.succ j, isLt := hj } ≠ 0))) a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
rw [← List.insertNth_removeNth_of_ge]
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · 

Proof state:
case pos.intro
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : Nat.succ j < n + 2
hij : i < Nat.succ j
⊢ List.insertNth j a (List.removeNth ↑v ↑{ val := i, isLt := (_ : i < Nat.succ (n + 1)) }) =
    List.insertNth (↑(Fin.pred { val := Nat.succ j, isLt := hj } (_ : { val := Nat.succ j, isLt := hj } ≠ 0))) a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
simp
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; 

Proof state:
case pos.intro
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : Nat.succ j < n + 2
hij : i < Nat.succ j
⊢ List.insertNth j a (List.removeNth (↑v) i) =
    List.insertNth j a
      ↑(match v with
        | { val := l, property := p } =>
          { val := List.removeNth l i,
            property := (_ : List.length (List.removeNth l ↑{ val := i, isLt := hi }) = n + 1 - 1) })

Next tactic:
rfl
theorem removeNth_insertNth' {v : Vector α (n + 1)} :
    ∀ {i : Fin (n + 1)} {j : Fin (n + 2)},
      removeNth (j.succAbove i) (insertNth a j v) = insertNth a (i.predAbove j) (removeNth i v)
  | ⟨i, hi⟩, ⟨j, hj⟩ => by
    dsimp [insertNth, removeNth, Fin.succAbove, Fin.predAbove]
    rw [Subtype.mk_eq_mk]
    simp only [Fin.lt_iff_val_lt_val]
    split_ifs with hij
    · rcases Nat.exists_eq_succ_of_ne_zero
        (Nat.pos_iff_ne_zero.1 (lt_of_le_of_lt (Nat.zero_le _) hij)) with ⟨j, rfl⟩
      rw [← List.insertNth_removeNth_of_ge]
      · simp; rfl
      · 

Proof state:
case pos.intro.a
n : ℕ
α : Type u_1
β : Type u_2
γ : Type u_3
a : α
v : Vector α (n + 1)
i : ℕ
hi : i < n + 1
j : ℕ
hj : Nat.succ j < n + 2
hij : i < Nat.succ j
⊢ ↑{ val := i, isLt := (_ : i < Nat.succ (n + 1)) } < List.length ↑v

Next tactic:
simpa