l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        

Proof state:
case neg.succ.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
h : ¬succ n✝ < length []
⊢ splitAt.go l [] (succ n✝) acc = (l, [])

Next tactic:
| nil => rw [splitAt.go]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        | nil => 

Proof state:
case neg.succ.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
h : ¬succ n✝ < length []
⊢ splitAt.go l [] (succ n✝) acc = (l, [])

Next tactic:
rw [splitAt.go]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        | nil => rw [splitAt.go]
        

Proof state:
case neg.succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
hd : α
tl : List α
h : ¬succ n✝ < length (hd :: tl)
⊢ splitAt.go l (hd :: tl) (succ n✝) acc = (l, [])

Next tactic:
| cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go]
          exact ih _ _ <| not_imp_not.mpr (Nat.add_lt_add_right · 1) h
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        | nil => rw [splitAt.go]
        | cons hd tl =>
          

Proof state:
case neg.succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
hd : α
tl : List α
h : ¬succ n✝ < length (hd :: tl)
⊢ splitAt.go l (hd :: tl) (succ n✝) acc = (l, [])

Next tactic:
rw [length, succ_eq_add_one] at h
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        | nil => rw [splitAt.go]
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          

Proof state:
case neg.succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
hd : α
tl : List α
h : ¬n✝ + 1 < length tl + 1
⊢ splitAt.go l (hd :: tl) (succ n✝) acc = (l, [])

Next tactic:
rw [splitAt.go]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
where
  go_eq_take_drop (n : ℕ) (l xs : List α) (acc : Array α) : splitAt.go l xs n acc =
      if n < xs.length then (acc.toList ++ take n xs, drop n xs) else (l, []) := by
    split_ifs with h
    · induction n generalizing xs acc with
      | zero =>
        rw [splitAt.go, take, drop, append_nil]
        · intros h₁; rw [h₁] at h; contradiction
        · intros; contradiction
      | succ _ ih =>
        cases xs with
        | nil => contradiction
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go, take, drop, append_cons, Array.toList_eq, ← Array.push_data,
            ← Array.toList_eq]
          exact ih _ _ <| lt_of_add_lt_add_right h
    · induction n generalizing xs acc with
      | zero =>
        rw [zero_eq, not_lt, nonpos_iff_eq_zero] at h
        rw [eq_nil_of_length_eq_zero h, splitAt.go]
      | succ _ ih =>
        cases xs with
        | nil => rw [splitAt.go]
        | cons hd tl =>
          rw [length, succ_eq_add_one] at h
          rw [splitAt.go]
          

Proof state:
case neg.succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l✝ l : List α
n✝ : ℕ
ih : ∀ (xs : List α) (acc : Array α), ¬n✝ < length xs → splitAt.go l xs n✝ acc = (l, [])
acc : Array α
hd : α
tl : List α
h : ¬n✝ + 1 < length tl + 1
⊢ splitAt.go l tl n✝ (Array.push acc hd) = (l, [])

Next tactic:
exact ih _ _ <| not_imp_not.mpr (Nat.add_lt_add_right · 1) h
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
⊢ splitAt n l = (take n l, drop n l)

Next tactic:
by_cases h : n < l.length
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
h : n < length l
⊢ splitAt n l = (take n l, drop n l)

Next tactic:
rw [splitAt, go_eq_take_drop]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
h : ¬n < length l
⊢ splitAt n l = (take n l, drop n l)

Next tactic:
rw [splitAt, go_eq_take_drop]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
h : n < length l
⊢ (if n < length l then (Array.toList #[] ++ take n l, drop n l) else (l, [])) = (take n l, drop n l)

Next tactic:
rw [if_pos h]
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
h : n < length l
⊢ (Array.toList #[] ++ take n l, drop n l) = (take n l, drop n l)

Next tactic:
rfl
@[simp]
theorem splitAt_eq_take_drop (n : ℕ) (l : List α) : splitAt n l = (take n l, drop n l) := by
  by_cases h : n < l.length <;> rw [splitAt, go_eq_take_drop]
  · rw [if_pos h]; rfl
  · 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
n : ℕ
l : List α
h : ¬n < length l
⊢ (if n < length l then (Array.toList #[] ++ take n l, drop n l) else (l, [])) = (take n l, drop n l)

Next tactic:
rw [if_neg h, take_all_of_le <| le_of_not_lt h, drop_eq_nil_of_le <| le_of_not_lt h]
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
xs acc : List α
⊢ go p xs acc ≠ []

Next tactic:
induction xs generalizing acc
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  induction xs generalizing acc <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
acc : List α
⊢ go p [] acc ≠ []

Next tactic:
simp [go]
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  induction xs generalizing acc <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (acc : List α), go p tail✝ acc ≠ []
acc : List α
⊢ go p (head✝ :: tail✝) acc ≠ []

Next tactic:
simp [go]
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  induction xs generalizing acc <;> simp [go]; 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (acc : List α), go p tail✝ acc ≠ []
acc : List α
⊢ ¬(if p head✝ = true then reverse acc :: go p tail✝ [] else go p tail✝ (head✝ :: acc)) = []

Next tactic:
split
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  induction xs generalizing acc <;> simp [go]; split <;> 

Proof state:
case cons.inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (acc : List α), go p tail✝ acc ≠ []
acc : List α
h✝ : p head✝ = true
⊢ ¬False

Next tactic:
simp [*]
theorem splitOnP.go_ne_nil (xs acc : List α) : splitOnP.go p xs acc ≠ [] := by
  induction xs generalizing acc <;> simp [go]; split <;> 

Proof state:
case cons.inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (acc : List α), go p tail✝ acc ≠ []
acc : List α
h✝ : ¬p head✝ = true
⊢ ¬go p tail✝ (head✝ :: acc) = []

Next tactic:
simp [*]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
xs acc : List α
⊢ go p xs acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p xs)

Next tactic:
induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      congr; funext x; simp only [reverse_cons, append_assoc]; rfl
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
acc : List α
⊢ go p [] acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p [])

Next tactic:
| nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
acc : List α
⊢ go p [] acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p [])

Next tactic:
simp only [go, modifyHead, splitOnP_nil, append_nil]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
⊢ go p (hd :: tl) acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p (hd :: tl))

Next tactic:
| cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      congr; funext x; simp only [reverse_cons, append_assoc]; rfl
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
⊢ go p (hd :: tl) acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p (hd :: tl))

Next tactic:
simp only [splitOnP, go]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
⊢ (if p hd = true then reverse acc :: go p tl [] else go p tl (hd :: acc)) =
    modifyHead (fun x => reverse acc ++ x) (if p hd = true then reverse [] :: go p tl [] else go p tl [hd])

Next tactic:
split
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · 

Proof state:
case cons.inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : p hd = true
⊢ reverse acc :: go p tl [] = modifyHead (fun x => reverse acc ++ x) (reverse [] :: go p tl [])

Next tactic:
simp only [modifyHead, reverse_nil, append_nil]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · 

Proof state:
case cons.inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : ¬p hd = true
⊢ go p tl (hd :: acc) = modifyHead (fun x => reverse acc ++ x) (go p tl [hd])

Next tactic:
rw [ih [hd], modifyHead_modifyHead, ih]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      

Proof state:
case cons.inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : ¬p hd = true
⊢ modifyHead (fun x => reverse (hd :: acc) ++ x) (splitOnP p tl) =
    modifyHead ((fun x => reverse acc ++ x) ∘ fun x => reverse [hd] ++ x) (splitOnP p tl)

Next tactic:
congr
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      congr; 

Proof state:
case cons.inr.e_f
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : ¬p hd = true
⊢ (fun x => reverse (hd :: acc) ++ x) = (fun x => reverse acc ++ x) ∘ fun x => reverse [hd] ++ x

Next tactic:
funext x
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      congr; funext x; 

Proof state:
case cons.inr.e_f.h
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : ¬p hd = true
x : List α
⊢ reverse (hd :: acc) ++ x = ((fun x => reverse acc ++ x) ∘ fun x => reverse [hd] ++ x) x

Next tactic:
simp only [reverse_cons, append_assoc]
theorem splitOnP.go_acc (xs acc : List α) :
    splitOnP.go p xs acc = modifyHead (acc.reverse ++ ·) (splitOnP p xs) := by
  induction xs generalizing acc with
  | nil => simp only [go, modifyHead, splitOnP_nil, append_nil]
  | cons hd tl ih =>
    simp only [splitOnP, go]; split
    · simp only [modifyHead, reverse_nil, append_nil]
    · rw [ih [hd], modifyHead_modifyHead, ih]
      congr; funext x; simp only [reverse_cons, append_assoc]; 

Proof state:
case cons.inr.e_f.h
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
hd : α
tl : List α
ih : ∀ (acc : List α), go p tl acc = modifyHead (fun x => reverse acc ++ x) (splitOnP p tl)
acc : List α
h✝ : ¬p hd = true
x : List α
⊢ reverse acc ++ ([hd] ++ x) = ((fun x => reverse acc ++ x) ∘ fun x => reverse [] ++ ([hd] ++ x)) x

Next tactic:
rfl
@[simp]
theorem splitOnP_cons (x : α) (xs : List α) :
    (x :: xs).splitOnP p =
      if p x then [] :: xs.splitOnP p else (xs.splitOnP p).modifyHead (cons x) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
x : α
xs : List α
⊢ splitOnP p (x :: xs) = if p x = true then [] :: splitOnP p xs else modifyHead (cons x) (splitOnP p xs)

Next tactic:
rw [splitOnP, splitOnP.go]