Theorem: String.revFindAux_of_valid
File: .lake/packages/batteries/Batteries/Data/String/Lemmas.lean

Proof steps:
state_before: p : Char → Bool
r : List Char
⊢ { data := [].reverse ++ r }.revFindAux p { byteIdx := utf8Len [] } =
    Option.map (fun x => { byteIdx := utf8Len x }) (List.dropWhile (fun x => !p x) []).tail?
state_after: p : Char → Bool
r : List Char
⊢ (if h : { byteIdx := utf8Len [] } = 0 then none
    else
      let_fun this := ⋯;
      let pos := { data := [].reverse ++ r }.prev { byteIdx := utf8Len [] };
      if p ({ data := [].reverse ++ r }.get pos) = true then some pos
      else { data := [].reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x }) [].tail?
tactic: unfold revFindAux List.dropWhile
state_before: p : Char → Bool
r : List Char
⊢ (if h : { byteIdx := utf8Len [] } = 0 then none
    else
      let_fun this := ⋯;
      let pos := { data := [].reverse ++ r }.prev { byteIdx := utf8Len [] };
      if p ({ data := [].reverse ++ r }.get pos) = true then some pos
      else { data := [].reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x }) [].tail?
state_after: no goals
tactic: simp
state_before: p : Char → Bool
c : Char
l r : List Char
⊢ { data := (c :: l).reverse ++ r }.revFindAux p { byteIdx := utf8Len (c :: l) } =
    Option.map (fun x => { byteIdx := utf8Len x }) (List.dropWhile (fun x => !p x) (c :: l)).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
⊢ (if h : { byteIdx := utf8Len (c :: l) } = 0 then none
    else
      let_fun this := ⋯;
      let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
      if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
      else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: unfold revFindAux List.dropWhile
state_before: p : Char → Bool
c : Char
l r : List Char
⊢ (if h : { byteIdx := utf8Len (c :: l) } = 0 then none
    else
      let_fun this := ⋯;
      let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
      if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
      else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: rw [dif_neg (by exact Pos.ne_of_gt add_csize_pos)]
state_before: p : Char → Bool
c : Char
l r : List Char
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l.reverse } = (c :: r).headD default
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: have h1 := get_of_valid l.reverse (c::r)
state_before: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l.reverse } = (c :: r).headD default
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l.reverse } = (c :: r).headD default
h2 :
  { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l.reverse + c.utf8Size } = { byteIdx := utf8Len l.reverse }
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: have h2 := prev_of_valid l.reverse c r
state_before: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l.reverse } = (c :: r).headD default
h2 :
  { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l.reverse + c.utf8Size } = { byteIdx := utf8Len l.reverse }
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: simp only [utf8Len_reverse, Char.reduceDefault, List.headD_cons] at h1 h2
state_before: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ (let_fun this := ⋯;
    let pos := { data := (c :: l).reverse ++ r }.prev { byteIdx := utf8Len (c :: l) };
    if p ({ data := (c :: l).reverse ++ r }.get pos) = true then some pos
    else { data := (c :: l).reverse ++ r }.revFindAux p pos) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ (if p c = true then some { byteIdx := utf8Len l }
    else { data := l.reverse ++ c :: r }.revFindAux p { byteIdx := utf8Len l }) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
tactic: simp only [List.reverse_cons, List.append_assoc, List.singleton_append, utf8Len_cons, h2, h1]
state_before: p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ (if p c = true then some { byteIdx := utf8Len l }
    else { data := l.reverse ++ c :: r }.revFindAux p { byteIdx := utf8Len l }) =
    Option.map (fun x => { byteIdx := utf8Len x })
      (match !p c with
        | true => List.dropWhile (fun x => !p x) l
        | false => c :: l).tail?
state_after: case false
p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ { data := l.reverse ++ c :: r }.revFindAux p { byteIdx := utf8Len l } =
    Option.map (fun x => { byteIdx := utf8Len x }) (List.dropWhile (fun x => !p x) l).tail?
tactic: cases p c <;> simp only [Bool.false_eq_true, ↓reduceIte, Bool.not_false, Bool.not_true,
      List.tail?_cons, Option.map_some']
state_before: case false
p : Char → Bool
c : Char
l r : List Char
h1 : { data := l.reverse ++ c :: r }.get { byteIdx := utf8Len l } = c
h2 : { data := l.reverse ++ c :: r }.prev { byteIdx := utf8Len l + c.utf8Size } = { byteIdx := utf8Len l }
⊢ { data := l.reverse ++ c :: r }.revFindAux p { byteIdx := utf8Len l } =
    Option.map (fun x => { byteIdx := utf8Len x }) (List.dropWhile (fun x => !p x) l).tail?
state_after: no goals
tactic: exact revFindAux_of_valid p l (c::r)