Theorem: String.ltb_cons_addChar
File: Mathlib/Data/String/Basic.lean

tactic: 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; rw [ltb]) <;>
simp [Iterator.hasNext_cons_addChar, *]
state_before: c : Char
cs₁ cs₂ : List Char
i₁ i₂ : Pos
⊢ ltb { s := { data := c :: cs₁ }, i := i₁ + c } { s := { data := c :: cs₂ }, i := i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ } { s := { data := cs₂ }, i := i₂ }

tactic: conv => lhs; rw [ltb]
state_before: 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₂ }

tactic: conv => rhs; rw [ltb]
state_before: 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
⊢ (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₂ }

tactic: rename_i h₂ h₁ heq ih
state_before: 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.curr { s := { data := c :: cs₁ }, i := i₁ + c } =
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c } then
      ltb (Iterator.next { s := { data := c :: cs₁ }, i := i₁ + c })
        (Iterator.next { s := { data := c :: cs₂ }, i := i₂ + c })
    else
      decide
        (Iterator.curr { s := { data := c :: cs₁ }, i := i₁ + c } <
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c })) =
    if Iterator.curr { s := { data := cs₁ }, i := i₁ } = Iterator.curr { s := { data := cs₂ }, i := i₂ } then
      ltb (Iterator.next { s := { data := cs₁ }, i := i₁ }) (Iterator.next { s := { data := cs₂ }, i := i₂ })
    else decide (Iterator.curr { s := { data := cs₁ }, i := i₁ } < Iterator.curr { s := { data := cs₂ }, i := i₂ })

tactic: simp [Iterator.curr, get_cons_addChar, Iterator.next, next, *] at *
state_before: case ind
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
h₂ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
h₁ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
heq : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
ih :
  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.curr { s := { data := c :: cs₁ }, i := i₁ + c } =
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c } then
      ltb (Iterator.next { s := { data := c :: cs₁ }, i := i₁ + c })
        (Iterator.next { s := { data := c :: cs₂ }, i := i₂ + c })
    else
      decide
        (Iterator.curr { s := { data := c :: cs₁ }, i := i₁ + c } <
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c })) =
    if Iterator.curr { s := { data := cs₁ }, i := i₁ } = Iterator.curr { s := { data := cs₂ }, i := i₂ } then
      ltb (Iterator.next { s := { data := cs₁ }, i := i₁ }) (Iterator.next { s := { data := cs₂ }, i := i₂ })
    else decide (Iterator.curr { s := { data := cs₁ }, i := i₁ } < Iterator.curr { s := { data := cs₂ }, i := i₂ })

tactic: repeat rw [Pos.addChar_right_comm _ c]
state_before: case ind
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
h₂ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
h₁ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
heq : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
ih :
  ltb { s := { data := c :: cs₁ }, i := i₁ + get { data := cs₂ } i₂ + c }
      { s := { data := c :: cs₂ }, i := i₂ + get { data := cs₂ } i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }
⊢ ltb { s := { data := c :: cs₁ }, i := i₁ + c + get { data := cs₂ } i₂ }
      { s := { data := c :: cs₂ }, i := i₂ + c + get { data := cs₂ } i₂ } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }

tactic: exact ih
state_before: case ind
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
h₂ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
h₁ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
heq : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
ih :
  ltb { s := { data := c :: cs₁ }, i := i₁ + get { data := cs₂ } i₂ + c }
      { s := { data := c :: cs₂ }, i := i₂ + get { data := cs₂ } i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }
⊢ ltb { s := { data := c :: cs₁ }, i := i₁ + get { data := cs₂ } i₂ + c }
      { s := { data := c :: cs₂ }, i := i₂ + get { data := cs₂ } i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }

tactic: rw [Pos.addChar_right_comm _ c]
state_before: case ind
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
h₂ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
h₁ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
heq : get { data := cs₁ } i₁ = get { data := cs₂ } i₂
ih :
  ltb { s := { data := c :: cs₁ }, i := i₁ + get { data := cs₂ } i₂ + c }
      { s := { data := c :: cs₂ }, i := i₂ + get { data := cs₂ } i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }
⊢ ltb { s := { data := c :: cs₁ }, i := i₁ + get { data := cs₂ } i₂ + c }
      { s := { data := c :: cs₂ }, i := i₂ + get { data := cs₂ } i₂ + c } =
    ltb { s := { data := cs₁ }, i := i₁ + get { data := cs₂ } i₂ }
      { s := { data := cs₂ }, i := i₂ + get { data := cs₂ } i₂ }

tactic: rename_i h₂ h₁ hne
state_before: 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.curr { s := { data := c :: cs₁ }, i := i₁ + c } =
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c } then
      ltb (Iterator.next { s := { data := c :: cs₁ }, i := i₁ + c })
        (Iterator.next { s := { data := c :: cs₂ }, i := i₂ + c })
    else
      decide
        (Iterator.curr { s := { data := c :: cs₁ }, i := i₁ + c } <
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c })) =
    if Iterator.curr { s := { data := cs₁ }, i := i₁ } = Iterator.curr { s := { data := cs₂ }, i := i₂ } then
      ltb (Iterator.next { s := { data := cs₁ }, i := i₁ }) (Iterator.next { s := { data := cs₂ }, i := i₂ })
    else decide (Iterator.curr { s := { data := cs₁ }, i := i₁ } < Iterator.curr { s := { data := cs₂ }, i := i₂ })

tactic: simp [Iterator.curr, get_cons_addChar, *]
state_before: case eq
c : Char
cs₁✝ cs₂✝ : List Char
i₁✝ i₂✝ : Pos
cs₁ cs₂ : List Char
i₁ i₂ : Pos
h₂ : Iterator.hasNext { s := { data := cs₂ }, i := i₂ } = true
h₁ : Iterator.hasNext { s := { data := cs₁ }, i := i₁ } = true
hne : ¬get { data := cs₁ } i₁ = get { data := cs₂ } i₂
⊢ (if
        Iterator.curr { s := { data := c :: cs₁ }, i := i₁ + c } =
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c } then
      ltb (Iterator.next { s := { data := c :: cs₁ }, i := i₁ + c })
        (Iterator.next { s := { data := c :: cs₂ }, i := i₂ + c })
    else
      decide
        (Iterator.curr { s := { data := c :: cs₁ }, i := i₁ + c } <
          Iterator.curr { s := { data := c :: cs₂ }, i := i₂ + c })) =
    if Iterator.curr { s := { data := cs₁ }, i := i₁ } = Iterator.curr { s := { data := cs₂ }, i := i₂ } then
      ltb (Iterator.next { s := { data := cs₁ }, i := i₁ }) (Iterator.next { s := { data := cs₂ }, i := i₂ })
    else decide (Iterator.curr { s := { data := cs₁ }, i := i₁ } < Iterator.curr { s := { data := cs₂ }, i := i₂ })