Theorem: Array.reverse_data
File: Std/Data/Array/Lemmas.lean

tactic: simp only [reverse]
state_before: α : Type u_1
a : Array α
⊢ (reverse a).data = List.reverse a.data

tactic: split
state_before: α : Type u_1
a : Array α
⊢ (if h : size a ≤ 1 then a
      else
        reverse.loop a 0 { val := size a - 1, isLt := (_ : Nat.pred (Nat.sub (size a) 0) < Nat.sub (size a) 0) }).data =
    List.reverse a.data

tactic: rw [reverse.loop]
state_before: α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
⊢ List.get? (reverse.loop as i { val := j, isLt := hj }).data k = List.get? (List.reverse a.data) k

tactic: dsimp
state_before: α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
⊢ List.get?
      (if h : i < { val := j, isLt := hj }.val then
          let_fun this := (_ : { val := j, isLt := hj }.val - 1 - (i + 1) < { val := j, isLt := hj }.val - i);
          let as_1 := swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj };
          let_fun this := (_ : { val := j, isLt := hj }.val - 1 < size as_1);
          reverse.loop as_1 (i + 1) { val := { val := j, isLt := hj }.val - 1, isLt := this }
        else as).data
      k =
    List.get? (List.reverse a.data) k

tactic: split <;> rename_i h₁
state_before: α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
⊢ List.get?
      (if h : i < j then
          reverse.loop (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj }) (i + 1)
            { val := j - 1,
              isLt := (_ : j - 1 < size (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj })) }
        else as).data
      k =
    List.get? (List.reverse a.data) k

tactic: have := reverse.termination h₁
state_before: case inl
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : i < j
⊢ List.get?
      (reverse.loop (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj }) (i + 1)
          { val := j - 1,
            isLt :=
              (_ : j - 1 < size (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj })) }).data
      k =
    List.get? (List.reverse a.data) k

tactic: match j with | j+1 => ?_
state_before: case inl
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : i < j
this : j - 1 - (i + 1) < j - i
⊢ List.get?
      (reverse.loop (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj }) (i + 1)
          { val := j - 1,
            isLt :=
              (_ : j - 1 < size (swap as { val := i, isLt := (_ : i < size as) } { val := j, isLt := hj })) }).data
      k =
    List.get? (List.reverse a.data) k

tactic: simp at *
state_before: case inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j + 1 - 1 - (i + 1) < j + 1 - i
⊢ List.get?
      (reverse.loop (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj }) (i + 1)
          { val := j + 1 - 1,
            isLt :=
              (_ :
                j + 1 - 1 < size (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj })) }).data
      k =
    List.get? (List.reverse a.data) k

tactic: simp
state_before: case inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
⊢ List.get?
      (reverse.loop (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj }) (i + 1)
          { val := j,
            isLt :=
              (_ : j < size (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj })) }).data
      k =
    List.get? (List.reverse a.data) k

tactic: rwa [Nat.add_right_comm i]
state_before: case inl.h
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
⊢ i + 1 + j + 1 = size a

tactic: simp [size_swap, h₂]
state_before: case inl.h₂
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
⊢ size (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj }) = size a

tactic: intro k
state_before: case inl.H
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
⊢ ∀ (k : Nat),
    List.get? (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj }).data k =
      if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: rw [← getElem?_eq_data_get?, get?_swap]
state_before: case inl.H
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
⊢ List.get? (swap as { val := i, isLt := (_ : i < size as) } { val := j + 1, isLt := hj }).data k =
    if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: simp [getElem?_eq_data_get?, getElem_eq_data_get, ← List.get?_eq_get, H, Nat.le_of_lt h₁]
state_before: case inl.H
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
⊢ (if { val := j + 1, isLt := hj }.val = k then some as[{ val := i, isLt := (_ : i < size as) }.val]
    else
      if { val := i, isLt := (_ : i < size as) }.val = k then some as[{ val := j + 1, isLt := hj }.val] else as[k]?) =
    if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: split <;> rename_i h₂
state_before: case inl.H
α : Type u_1
a as : Array α
i j✝ : Nat
h₂ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
⊢ (if j + 1 = k then List.get? a.data i
    else
      if i = k then List.get? a.data (j + 1)
      else if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k) =
    if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: split <;> rename_i h₃
state_before: case inl.H.inr
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : ¬j + 1 = k
⊢ (if i = k then List.get? a.data (j + 1)
    else if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k) =
    if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: simp only [Nat.succ_le, Nat.lt_iff_le_and_ne.trans (and_iff_left h₃),
  Nat.lt_succ.symm.trans (Nat.lt_iff_le_and_ne.trans (and_iff_left (Ne.symm h₂)))]
state_before: case inl.H.inr.inr
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : ¬j + 1 = k
h₃ : ¬i = k
⊢ (if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k) =
    if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: simp [← h₂, Nat.not_le.2 (Nat.lt_succ_self _)]
state_before: case inl.H.inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : j + 1 = k
⊢ List.get? a.data i = if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: exact (List.get?_reverse' _ _ (Eq.trans (by simp_arith) h)).symm
state_before: case inl.H.inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : j + 1 = k
⊢ List.get? a.data i = List.get? (List.reverse a.data) (j + 1)

tactic: simp_arith
state_before: α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : j + 1 = k
⊢ j + 1 + i + 1 = i + (j + 1) + 1

tactic: simp [← h₃, Nat.not_le.2 (Nat.lt_succ_self _)]
state_before: case inl.H.inr.inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : ¬j + 1 = k
h₃ : i = k
⊢ List.get? a.data (j + 1) = if i + 1 ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: exact (List.get?_reverse' _ _ (Eq.trans (by simp_arith) h)).symm
state_before: case inl.H.inr.inl
α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : ¬j + 1 = k
h₃ : i = k
⊢ List.get? a.data (j + 1) = List.get? (List.reverse a.data) i

tactic: simp_arith
state_before: α : Type u_1
a as : Array α
i j✝ : Nat
h₂✝ : size as = size a
k✝ j : Nat
hj : j + 1 < size as
h : i + (j + 1) + 1 = size a
H :
  ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j + 1 then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : i < j + 1
this : j - (i + 1) < j + 1 - i
k : Nat
h₂ : ¬j + 1 = k
h₃ : i = k
⊢ i + (j + 1) + 1 = i + (j + 1) + 1

tactic: rw [H]
state_before: case inr
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : ¬i < j
⊢ List.get? as.data k = List.get? (List.reverse a.data) k

tactic: split <;> rename_i h₂
state_before: case inr
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : ¬i < j
⊢ (if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k) = List.get? (List.reverse a.data) k

tactic: cases Nat.le_antisymm (Nat.not_lt.1 h₁) (Nat.le_trans h₂.1 h₂.2)
state_before: case inr.inl
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂✝ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : ¬i < j
h₂ : i ≤ k ∧ k ≤ j
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: cases Nat.le_antisymm h₂.1 h₂.2
state_before: case inr.inl.refl
α : Type u_1
a as : Array α
i : Nat
h₂✝ : size as = size a
k : Nat
hj : i < size as
h : i + i + 1 = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ i then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : ¬i < i
h₂ : i ≤ k ∧ k ≤ i
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: exact (List.get?_reverse' _ _ h).symm
state_before: case inr.inl.refl.refl
α : Type u_1
a as : Array α
i : Nat
h₂✝ : size as = size a
hj : i < size as
h : i + i + 1 = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ i then List.get? a.data k else List.get? (List.reverse a.data) k
h₁ : ¬i < i
h₂ : i ≤ i ∧ i ≤ i
⊢ List.get? a.data i = List.get? (List.reverse a.data) i

tactic: rfl
state_before: case inr.inr
α : Type u_1
a as : Array α
i j : Nat
hj : j < size as
h : i + j + 1 = size a
h₂✝ : size as = size a
H : ∀ (k : Nat), List.get? as.data k = if i ≤ k ∧ k ≤ j then List.get? a.data k else List.get? (List.reverse a.data) k
k : Nat
h₁ : ¬i < j
h₂ : ¬(i ≤ k ∧ k ≤ j)
⊢ List.get? (List.reverse a.data) k = List.get? (List.reverse a.data) k

tactic: match a with | ⟨[]⟩ | ⟨[_]⟩ => rfl
state_before: case inl
α : Type u_1
a : Array α
h✝ : size a ≤ 1
⊢ a.data = List.reverse a.data

tactic: rfl
state_before: α : Type u_1
a : Array α
head✝ : α
h✝ : size { data := [head✝] } ≤ 1
⊢ { data := [head✝] }.data = List.reverse { data := [head✝] }.data

tactic: have := Nat.sub_add_cancel (Nat.le_of_not_le ‹_›)
state_before: case inr
α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
⊢ (reverse.loop a 0 { val := size a - 1, isLt := (_ : Nat.pred (Nat.sub (size a) 0) < Nat.sub (size a) 0) }).data =
    List.reverse a.data

tactic: refine List.ext <| go _ _ _ _ (by simp [this]) rfl fun k => ?_
state_before: case inr
α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
⊢ (reverse.loop a 0 { val := size a - 1, isLt := (_ : Nat.pred (Nat.sub (size a) 0) < Nat.sub (size a) 0) }).data =
    List.reverse a.data

tactic: split
state_before: case inr
α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
⊢ List.get? a.data k = if 0 ≤ k ∧ k ≤ size a - 1 then List.get? a.data k else List.get? (List.reverse a.data) k

tactic: {rfl}
state_before: case inr.inl
α : Type u_1
a : Array α
h✝¹ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
h✝ : 0 ≤ k ∧ k ≤ size a - 1
⊢ List.get? a.data k = List.get? a.data k

case inr.inr
α : Type u_1
a : Array α
h✝¹ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
h✝ : ¬(0 ≤ k ∧ k ≤ size a - 1)
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: rename_i h
state_before: case inr.inr
α : Type u_1
a : Array α
h✝¹ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
h✝ : ¬(0 ≤ k ∧ k ≤ size a - 1)
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: simp [← show k < _ + 1 ↔ _ from Nat.lt_succ (n := a.size - 1), this] at h
state_before: case inr.inr
α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
h : ¬(0 ≤ k ∧ k ≤ size a - 1)
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: rw [List.get?_eq_none.2 ‹_›, List.get?_eq_none.2 (a.data.length_reverse ▸ ‹_›)]
state_before: case inr.inr
α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
k : Nat
h : size a ≤ k
⊢ List.get? a.data k = List.get? (List.reverse a.data) k

tactic: simp [this]
state_before: α : Type u_1
a : Array α
h✝ : ¬size a ≤ 1
this : size a - 1 + 1 = size a
⊢ 0 + (size a - 1) + 1 = size a