l3lab/ntp-mathlib huggingface dataset:
theorem indexOf_append_of_mem {a : α} (h : a ∈ l₁) : indexOf a (l₁ ++ l₂) = indexOf a l₁ := by
  induction' l₁ with d₁ t₁ ih
  · exfalso
    exact not_mem_nil a h
  rw [List.cons_append]
  by_cases hh : d₁ = a
  · iterate 2 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : DecidableEq α
a d₁ : α
t₁ : List α
ih : a ∈ t₁ → indexOf a (t₁ ++ l₂) = indexOf a t₁
h : a ∈ d₁ :: t₁
hh : d₁ = a
⊢ 0 = indexOf a (d₁ :: t₁)

Next tactic:
rw [indexOf_cons_eq _ hh]
theorem indexOf_append_of_mem {a : α} (h : a ∈ l₁) : indexOf a (l₁ ++ l₂) = indexOf a l₁ := by
  induction' l₁ with d₁ t₁ ih
  · exfalso
    exact not_mem_nil a h
  rw [List.cons_append]
  by_cases hh : d₁ = a
  · iterate 2 rw [indexOf_cons_eq _ hh]
  

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : DecidableEq α
a d₁ : α
t₁ : List α
ih : a ∈ t₁ → indexOf a (t₁ ++ l₂) = indexOf a t₁
h : a ∈ d₁ :: t₁
hh : ¬d₁ = a
⊢ indexOf a (d₁ :: (t₁ ++ l₂)) = indexOf a (d₁ :: t₁)

Next tactic:
rw [indexOf_cons_ne _ hh, indexOf_cons_ne _ hh, ih (mem_of_ne_of_mem (Ne.symm hh) h)]
theorem indexOf_append_of_not_mem {a : α} (h : a ∉ l₁) :
    indexOf a (l₁ ++ l₂) = l₁.length + indexOf a l₂ := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
h : ¬a ∈ l₁
⊢ indexOf a (l₁ ++ l₂) = length l₁ + indexOf a l₂

Next tactic:
induction' l₁ with d₁ t₁ ih
theorem indexOf_append_of_not_mem {a : α} (h : a ∉ l₁) :
    indexOf a (l₁ ++ l₂) = l₁.length + indexOf a l₂ := by
  induction' l₁ with d₁ t₁ ih
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : DecidableEq α
a : α
h : ¬a ∈ []
⊢ indexOf a ([] ++ l₂) = length [] + indexOf a l₂

Next tactic:
rw [List.nil_append, List.length, zero_add]
theorem indexOf_append_of_not_mem {a : α} (h : a ∉ l₁) :
    indexOf a (l₁ ++ l₂) = l₁.length + indexOf a l₂ := by
  induction' l₁ with d₁ t₁ ih
  · rw [List.nil_append, List.length, zero_add]
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : DecidableEq α
a d₁ : α
t₁ : List α
ih : ¬a ∈ t₁ → indexOf a (t₁ ++ l₂) = length t₁ + indexOf a l₂
h : ¬a ∈ d₁ :: t₁
⊢ indexOf a (d₁ :: t₁ ++ l₂) = length (d₁ :: t₁) + indexOf a l₂

Next tactic:
rw [List.cons_append, indexOf_cons_ne _ (ne_of_not_mem_cons h).symm, List.length,
    ih (not_mem_of_not_mem_cons h), Nat.succ_add]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
xs : List α
i j : ℕ
h₀ : i < length xs
h₁ : Nodup xs
h₂ : get? xs i = get? xs j
⊢ i = j

Next tactic:
induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; cases' h₁ with _ _ h h')
    · cases (h x (mem_iff_get?.mpr ⟨_, h₂.symm⟩) rfl)
    · cases (h x (mem_iff_get?.mpr ⟨_, h₂⟩) rfl)
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  

Proof state:
case nil
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
i j : ℕ
h₀ : i < length []
h₁ : Nodup []
h₂ : get? [] i = get? [] j
⊢ i = j

Next tactic:
| nil => cases h₀
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => 

Proof state:
case nil
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
i j : ℕ
h₀ : i < length []
h₁ : Nodup []
h₂ : get? [] i = get? [] j
⊢ i = j

Next tactic:
cases h₀
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  

Proof state:
case cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
i j : ℕ
h₀ : i < length (x :: xs)
h₁ : Nodup (x :: xs)
h₂ : get? (x :: xs) i = get? (x :: xs) j
⊢ i = j

Next tactic:
| cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; cases' h₁ with _ _ h h')
    · cases (h x (mem_iff_get?.mpr ⟨_, h₂.symm⟩) rfl)
    · cases (h x (mem_iff_get?.mpr ⟨_, h₂⟩) rfl)
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    

Proof state:
case cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
i j : ℕ
h₀ : i < length (x :: xs)
h₁ : Nodup (x :: xs)
h₂ : get? (x :: xs) i = get? (x :: xs) j
⊢ i = j

Next tactic:
cases i
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> 

Proof state:
case cons.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
j : ℕ
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
h₂ : get? (x :: xs) zero = get? (x :: xs) j
⊢ zero = j

Next tactic:
cases j
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> 

Proof state:
case cons.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
j : ℕ
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? (x :: xs) (succ n✝) = get? (x :: xs) j
⊢ succ n✝ = j

Next tactic:
cases j
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    

Proof state:
case cons.zero.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
h₂ : get? (x :: xs) zero = get? (x :: xs) zero
⊢ zero = zero
case cons.zero.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) zero = get? (x :: xs) (succ n✝)
⊢ zero = succ n✝
case cons.succ.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? (x :: xs) (succ n✝) = get? (x :: xs) zero
⊢ succ n✝ = zero
case cons.succ.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
⊢ succ n✝¹ = succ n✝

Next tactic:
case zero.zero => rfl
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
h₂ : get? (x :: xs) zero = get? (x :: xs) zero
⊢ zero = zero

Next tactic:
case zero.zero => rfl
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => 

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
h₂ : get? (x :: xs) zero = get? (x :: xs) zero
⊢ zero = zero

Next tactic:
rfl
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    

Proof state:
case cons.zero.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) zero = get? (x :: xs) (succ n✝)
⊢ zero = succ n✝
case cons.succ.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? (x :: xs) (succ n✝) = get? (x :: xs) zero
⊢ succ n✝ = zero
case cons.succ.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
⊢ succ n✝¹ = succ n✝

Next tactic:
case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
⊢ succ n✝¹ = succ n✝

Next tactic:
case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
⊢ succ n✝¹ = succ n✝

Next tactic:
congr
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; 

Proof state:
case e_n
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
⊢ n✝¹ = n✝

Next tactic:
cases h₁
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      

Proof state:
case e_n.cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
a✝¹ : Pairwise (fun x x_1 => x ≠ x_1) xs
a✝ : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ n✝¹ = n✝

Next tactic:
apply tail_ih
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> 

Proof state:
case e_n.cons.h₀
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
a✝¹ : Pairwise (fun x x_1 => x ≠ x_1) xs
a✝ : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ n✝¹ < length xs

Next tactic:
solve_by_elim [lt_of_succ_lt_succ]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> 

Proof state:
case e_n.cons.h₁
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
a✝¹ : Pairwise (fun x x_1 => x ≠ x_1) xs
a✝ : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ Nodup xs

Next tactic:
solve_by_elim [lt_of_succ_lt_succ]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> 

Proof state:
case e_n.cons.h₂
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
n✝¹ : ℕ
h₀ : succ n✝¹ < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) (succ n✝¹) = get? (x :: xs) (succ n✝)
a✝¹ : Pairwise (fun x x_1 => x ≠ x_1) xs
a✝ : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ get? xs n✝¹ = get? xs n✝

Next tactic:
solve_by_elim [lt_of_succ_lt_succ]
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    

Proof state:
case cons.zero.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) zero = get? (x :: xs) (succ n✝)
⊢ zero = succ n✝
case cons.succ.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? (x :: xs) (succ n✝) = get? (x :: xs) zero
⊢ succ n✝ = zero

Next tactic:
all_goals (dsimp at h₂; cases' h₁ with _ _ h h')
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (

Proof state:
case cons.zero.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : get? (x :: xs) zero = get? (x :: xs) (succ n✝)
⊢ zero = succ n✝

Next tactic:
dsimp at h₂
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; 

Proof state:
case cons.zero.succ
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : some x = get? xs n✝
⊢ zero = succ n✝

Next tactic:
cases' h₁ with _ _ h h'
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (

Proof state:
case cons.succ.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? (x :: xs) (succ n✝) = get? (x :: xs) zero
⊢ succ n✝ = zero

Next tactic:
dsimp at h₂
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; 

Proof state:
case cons.succ.zero
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₁ : Nodup (x :: xs)
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? xs n✝ = some x
⊢ succ n✝ = zero

Next tactic:
cases' h₁ with _ _ h h'
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; cases' h₁ with _ _ h h')
    · 

Proof state:
case cons.zero.succ.cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
h₀ : zero < length (x :: xs)
n✝ : ℕ
h₂ : some x = get? xs n✝
h' : Pairwise (fun x x_1 => x ≠ x_1) xs
h : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ zero = succ n✝

Next tactic:
cases (h x (mem_iff_get?.mpr ⟨_, h₂.symm⟩) rfl)
theorem get?_injective {α : Type u} {xs : List α} {i j : ℕ} (h₀ : i < xs.length) (h₁ : Nodup xs)
    (h₂ : xs.get? i = xs.get? j) : i = j := by
  induction xs generalizing i j with
  | nil => cases h₀
  | cons x xs tail_ih =>
    cases i <;> cases j
    case zero.zero => rfl
    case succ.succ =>
      congr; cases h₁
      apply tail_ih <;> solve_by_elim [lt_of_succ_lt_succ]
    all_goals (dsimp at h₂; cases' h₁ with _ _ h h')
    · cases (h x (mem_iff_get?.mpr ⟨_, h₂.symm⟩) rfl)
    · 

Proof state:
case cons.succ.zero.cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u
x : α
xs : List α
tail_ih : ∀ {i j : ℕ}, i < length xs → Nodup xs → get? xs i = get? xs j → i = j
n✝ : ℕ
h₀ : succ n✝ < length (x :: xs)
h₂ : get? xs n✝ = some x
h' : Pairwise (fun x x_1 => x ≠ x_1) xs
h : ∀ (a' : α), a' ∈ xs → x ≠ a'
⊢ succ n✝ = zero

Next tactic:
cases (h x (mem_iff_get?.mpr ⟨_, h₂⟩) rfl)
/-- If one has `nthLe L i hi` in a formula and `h : L = L'`, one can not `rw h` in the formula as
`hi` gives `i < L.length` and not `i < L'.length`. The lemma `nth_le_of_eq` can be used to make
such a rewrite, with `rw (nth_le_of_eq h)`. -/
@[deprecated get_of_eq]
theorem nthLe_of_eq {L L' : List α} (h : L = L') {i : ℕ} (hi : i < L.length) :
    nthLe L i hi = nthLe L' i (h ▸ hi) := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L L' : List α
h : L = L'
i : ℕ
hi : i < length L
⊢ nthLe L i hi = nthLe L' i (_ : i < length L')

Next tactic:
congr
@[deprecated] -- FIXME: replacement -- it's not `get_zero` and it's not `get?_zero`
theorem nthLe_zero [Inhabited α] {L : List α} (h : 0 < L.length) : List.nthLe L 0 h = L.head! := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : Inhabited α
L : List α
h : 0 < length L
⊢ nthLe L 0 h = head! L

Next tactic:
cases L
@[deprecated] -- FIXME: replacement -- it's not `get_zero` and it's not `get?_zero`
theorem nthLe_zero [Inhabited α] {L : List α} (h : 0 < L.length) : List.nthLe L 0 h = L.head! := by
  cases L
  

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : Inhabited α
h : 0 < length []
⊢ nthLe [] 0 h = head! []
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : Inhabited α
head✝ : α
tail✝ : List α
h : 0 < length (head✝ :: tail✝)
⊢ nthLe (head✝ :: tail✝) 0 h = head! (head✝ :: tail✝)

Next tactic:
cases h
@[deprecated] -- FIXME: replacement -- it's not `get_zero` and it's not `get?_zero`
theorem nthLe_zero [Inhabited α] {L : List α} (h : 0 < L.length) : List.nthLe L 0 h = L.head! := by
  cases L
  cases h
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : Inhabited α
head✝ : α
tail✝ : List α
h : 0 < length (head✝ :: tail✝)
⊢ nthLe (head✝ :: tail✝) 0 h = head! (head✝ :: tail✝)

Next tactic:
simp [nthLe]
theorem get_length_sub_one {l : List α} (h : l.length - 1 < l.length) :
    l.get ⟨l.length - 1, h⟩ = l.getLast (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
h : length l - 1 < length l
⊢ l ≠ []

Next tactic:
rintro rfl
theorem get_length_sub_one {l : List α} (h : l.length - 1 < l.length) :
    l.get ⟨l.length - 1, h⟩ = l.getLast (by rintro rfl; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
h : length [] - 1 < length []
⊢ False

Next tactic:
exact Nat.lt_irrefl 0 h