Theorem: UFModel.Agrees.push
File: Mathlib/Data/UnionFind.lean

tactic: cases H
state_before: α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
n : ℕ
m : Fin n → β
H : Agrees arr f m
k : ℕ
hk : k = n + 1
x : α
m' : Fin k → β
hm₁ : ∀ (i : Fin k) (h : ↑i < n), m' i = m { val := ↑i, isLt := h }
hm₂ : ∀ (h : n < k), f x = m' { val := n, isLt := h }
⊢ Agrees (Array.push arr x) f m'

tactic: have : k = (arr.push x).size := by simp [hk]
state_before: case mk
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
⊢ Agrees (Array.push arr x) f m'

tactic: refine mk' this fun i h₁ h₂ ↦ ?_
state_before: case mk
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
this : k = Array.size (Array.push arr x)
⊢ Agrees (Array.push arr x) f m'

tactic: simp [Array.get_push]
state_before: case mk
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
⊢ f (Array.get (Array.push arr x) { val := i, isLt := h₁ }) = m' { val := i, isLt := h₂ }

tactic: split <;> (rename_i h; simp at hm₁ ⊢)
state_before: case mk
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
⊢ f (if h : i < Array.size arr then arr[i] else x) = m' { val := i, isLt := h₂ }

tactic: simp [hk]
state_before: α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
⊢ k = Array.size (Array.push arr x)

tactic: rename_i h
state_before: case mk.inr
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h✝ : ¬i < Array.size arr
⊢ f x = m' { val := i, isLt := h₂ }

tactic: simp at hm₁ ⊢
state_before: case mk.inr
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = (fun i => f (Array.get arr i)) { val := ↑i, isLt := h }
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h : ¬i < Array.size arr
⊢ f x = m' { val := i, isLt := h₂ }

tactic: rw [← hm₁ ⟨i, h₂⟩]
state_before: case mk.inl
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = f arr[↑i]
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h : i < Array.size arr
⊢ f arr[i] = m' { val := i, isLt := h₂ }

tactic: assumption
state_before: case mk.inl
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = f arr[↑i]
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h : i < Array.size arr
⊢ ↑{ val := i, isLt := h₂ } < Array.size arr

tactic: cases show i = arr.size by apply le_antisymm <;> simp_all [Nat.lt_succ]
state_before: case mk.inr
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = f arr[↑i]
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h : ¬i < Array.size arr
⊢ f x = m' { val := i, isLt := h₂ }

tactic: rw [hm₂]
state_before: case mk.inr.refl
α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = f arr[↑i]
this : k = Array.size (Array.push arr x)
h₁ : Array.size arr < Array.size (Array.push arr x)
h₂ : Array.size arr < k
h : ¬Array.size arr < Array.size arr
⊢ f x = m' { val := Array.size arr, isLt := h₂ }

tactic: apply le_antisymm <;> simp_all [Nat.lt_succ]
state_before: α : Type u_1
β : Sort u_2
f : α → β
arr : Array α
k : ℕ
x : α
m' : Fin k → β
hk : k = Array.size arr + 1
hm₂ : ∀ (h : Array.size arr < k), f x = m' { val := Array.size arr, isLt := h }
hm₁ : ∀ (i : Fin k) (h : ↑i < Array.size arr), m' i = f arr[↑i]
this : k = Array.size (Array.push arr x)
i : ℕ
h₁ : i < Array.size (Array.push arr x)
h₂ : i < k
h : ¬i < Array.size arr
⊢ i = Array.size arr