l3lab/ntp-mathlib huggingface dataset:
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
    { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c }

Next tactic:
rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (

Proof state:
case base₁
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝¹ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = false
⊢ ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
conv => lhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝¹ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝¹ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝¹ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
    { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c }

Next tactic:
rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (

Proof state:
case base₂
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = false
⊢ ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
conv => lhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
      { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
lhs
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = false
| ltb { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c }
    { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c }

Next tactic:
rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (

Proof state:
case ind
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝³ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝² : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝¹ : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
a✝ :
  ltb
      { s := { data := c :: (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i + c }
      { s := { data := c :: (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i + c } =
    ltb
      { s := { data := (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i }
      { s := { data := (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i }
⊢ (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
conv => rhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝³ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝² : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝¹ : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
a✝ :
  ltb
      { s := { data := c :: (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i + c }
      { s := { data := c :: (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i + c } =
    ltb
      { s := { data := (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i }
      { s := { data := (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i }
| (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝³ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝² : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝¹ : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
a✝ :
  ltb
      { s := { data := c :: (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i + c }
      { s := { data := c :: (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i + c } =
    ltb
      { s := { data := (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i }
      { s := { data := (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i }
| (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rhs
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => rhs; 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝³ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝² : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝¹ : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
a✝ :
  ltb
      { s := { data := c :: (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i + c }
      { s := { data := c :: (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i + c } =
    ltb
      { s := { data := (Iterator.next { s := { data := cs₁ }, i := i₁ }).1.data },
        i := (Iterator.next { s := { data := cs₁ }, i := i₁ }).i }
      { s := { data := (Iterator.next { s := { data := cs₂ }, i := i₂ }).1.data },
        i := (Iterator.next { s := { data := cs₂ }, i := i₂ }).i }
| ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (

Proof state:
case eq
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
⊢ (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
conv => rhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rhs; rw [ltb]
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| (if Iterator.hasNext { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } = true then
      if Iterator.hasNext { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } = true then
        if
            Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } =
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c } then
          ltb (Iterator.next { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c })
            (Iterator.next { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
        else
          decide
            (Iterator.curr { s := { data := c :: { data := cs₁ }.data }, i := i₁ + c } <
              Iterator.curr { s := { data := c :: { data := cs₂ }.data }, i := i₂ + c })
      else true
    else false) =
    ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rhs
theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) :
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ = ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ := by
  apply ltb.inductionOn ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ (motive := fun ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩ ↦
    ltb ⟨⟨c :: cs₁⟩, i₁ + c⟩ ⟨⟨c :: cs₂⟩, i₂ + c⟩ =
    ltb ⟨⟨cs₁⟩, i₁⟩ ⟨⟨cs₂⟩, i₂⟩) <;> simp <;>
  intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;>
  intros <;>
  (conv => lhs; rw [ltb]) <;> (conv => rhs; 

Proof state:
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
a✝² : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
a✝¹ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
a✝ : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
| ltb { s := { data := { data := cs₁ }.data }, i := i₁ } { s := { data := { data := cs₂ }.data }, i := i₂ }

Next tactic:
rw [ltb]