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

tactic: unfold List.takeWhile₂
state_before: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
⊢ firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop } { byteIdx := p } =
    { byteIdx := p + utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst }
state_after: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
⊢ firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop } { byteIdx := p } =
    {
      byteIdx :=
        p +
          utf8Len
            (match r₁, r₂ with
              | a :: as, b :: bs =>
                if decide (a = b) = true then
                  match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) as bs with
                  | (as', bs') => (a :: as', b :: bs')
                else ([], [])
              | x, x_1 => ([], [])).fst }

tactic: split <;> unfold firstDiffPos.loop
state_before: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
⊢ firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop } { byteIdx := p } =
    {
      byteIdx :=
        p +
          utf8Len
            (match r₁, r₂ with
              | a :: as, b :: bs =>
                if decide (a = b) = true then
                  match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) as bs with
                  | (as', bs') => (a :: as', b :: bs')
                else ([], [])
              | x, x_1 => ([], [])).fst }
state_after: case h_1
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a✝ : Char
as✝ : List Char
b✝ : Char
bs✝ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a✝ :: as✝)) (utf8Len l₂ + utf8Len (b✝ :: bs✝))
⊢ (if h : { byteIdx := p } < { byteIdx := stop } then
      if
          ({ data := l₁ ++ a✝ :: as✝ }.get { byteIdx := p } != { data := l₂ ++ b✝ :: bs✝ }.get { byteIdx := p }) =
            true then
        { byteIdx := p }
      else
        let_fun this := ⋯;
        firstDiffPos.loop { data := l₁ ++ a✝ :: as✝ } { data := l₂ ++ b✝ :: bs✝ } { byteIdx := stop }
          ({ data := l₁ ++ a✝ :: as✝ }.next { byteIdx := p })
    else { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (if decide (a✝ = b✝) = true then
                match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) as✝ bs✝ with
                | (as', bs') => (a✝ :: as', b✝ :: bs')
              else ([], [])).fst }

case h_2
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝² x✝¹ : List Char
x✝ : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
⊢ (if h : { byteIdx := p } < { byteIdx := stop } then
      if ({ data := l₁ ++ r₁ }.get { byteIdx := p } != { data := l₂ ++ r₂ }.get { byteIdx := p }) = true then
        { byteIdx := p }
      else
        let_fun this := ⋯;
        firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop }
          ({ data := l₁ ++ r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    { byteIdx := p + utf8Len ([], []).fst }

tactic: rw [
  dif_pos <| by
    rw [hstop, ← hl₁, ← hl₂]
    refine Nat.lt_min.2 ⟨?_, ?_⟩ <;> exact Nat.lt_add_of_pos_right add_csize_pos,
  show get ⟨l₁ ++ a :: r₁⟩ ⟨p⟩ = a by simp [hl₁, get_of_valid],
  show get ⟨l₂ ++ b :: r₂⟩ ⟨p⟩ = b by simp [hl₂, get_of_valid]]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ (if h : { byteIdx := p } < { byteIdx := stop } then
      if ({ data := l₁ ++ a :: r₁ }.get { byteIdx := p } != { data := l₂ ++ b :: r₂ }.get { byteIdx := p }) = true then
        { byteIdx := p }
      else
        let_fun this := ⋯;
        firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
          ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (if decide (a = b) = true then
                match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂ with
                | (as', bs') => (a :: as', b :: bs')
              else ([], [])).fst }
state_after: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ (if (a != b) = true then { byteIdx := p }
    else
      let_fun this := ⋯;
      firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
        ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p })) =
    {
      byteIdx :=
        p +
          utf8Len
            (if decide (a = b) = true then
                match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂ with
                | (as', bs') => (a :: as', b :: bs')
              else ([], [])).fst }

tactic: simp only [bne_iff_ne, ne_eq, ite_not, decide_eq_true_eq]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ (if (a != b) = true then { byteIdx := p }
    else
      let_fun this := ⋯;
      firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
        ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p })) =
    {
      byteIdx :=
        p +
          utf8Len
            (if decide (a = b) = true then
                match List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂ with
                | (as', bs') => (a :: as', b :: bs')
              else ([], [])).fst }
state_after: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ (if a = b then
      firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
        ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (if a = b then
                (a :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst,
                  b :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).snd)
              else ([], [])).fst }

tactic: split
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ (if a = b then
      firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
        ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (if a = b then
                (a :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst,
                  b :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).snd)
              else ([], [])).fst }
state_after: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : a = b
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (a :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst,
                b :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).snd).fst }

case isFalse
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : ¬a = b
⊢ { byteIdx := p } = { byteIdx := p + utf8Len ([], []).fst }

tactic: rw [hstop, ← hl₁, ← hl₂]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ { byteIdx := p } < { byteIdx := stop }
state_after: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ { byteIdx := p } < { byteIdx := min (p + utf8Len (a :: r₁)) (p + utf8Len (b :: r₂)) }

tactic: refine Nat.lt_min.2 ⟨?_, ?_⟩ <;> exact Nat.lt_add_of_pos_right add_csize_pos
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ { byteIdx := p } < { byteIdx := min (p + utf8Len (a :: r₁)) (p + utf8Len (b :: r₂)) }
state_after: no goals

tactic: simp [hl₁, get_of_valid]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ { data := l₁ ++ a :: r₁ }.get { byteIdx := p } = a
state_after: no goals

tactic: simp [hl₂, get_of_valid]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
⊢ { data := l₂ ++ b :: r₂ }.get { byteIdx := p } = b
state_after: no goals

tactic: simp only [utf8Len_cons]
state_before: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : a = b
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    {
      byteIdx :=
        p +
          utf8Len
            (a :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst,
                b :: (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).snd).fst }
state_after: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : a = b
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }

tactic: subst b
state_before: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : a = b
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ b :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }
state_after: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ a :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }

tactic: rw [show next ⟨l₁ ++ a :: r₁⟩ ⟨p⟩ = ⟨utf8Len l₁ + a.utf8Size⟩ by simp [hl₁, next_of_valid]]
state_before: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ a :: r₂ } { byteIdx := stop }
      ({ data := l₁ ++ a :: r₁ }.next { byteIdx := p }) =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }
state_after: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ a :: r₂ } { byteIdx := stop }
      { byteIdx := utf8Len l₁ + a.utf8Size } =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }

tactic: simpa [← hl₁, ← Nat.add_assoc, Nat.add_right_comm] using
  firstDiffPos_loop_eq (l₁ ++ [a]) (l₂ ++ [a]) r₁ r₂ stop (p + a.utf8Size)
    (by simp [hl₁]) (by simp [hl₂]) (by simp [hstop, ← Nat.add_assoc, Nat.add_right_comm])
state_before: case isTrue
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ firstDiffPos.loop { data := l₁ ++ a :: r₁ } { data := l₂ ++ a :: r₂ } { byteIdx := stop }
      { byteIdx := utf8Len l₁ + a.utf8Size } =
    { byteIdx := p + (utf8Len (List.takeWhile₂ (fun x x_1 => decide (x = x_1)) r₁ r₂).fst + a.utf8Size) }
state_after: no goals

tactic: simp [hl₁, next_of_valid]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ { data := l₁ ++ a :: r₁ }.next { byteIdx := p } = { byteIdx := utf8Len l₁ + a.utf8Size }
state_after: no goals

tactic: simp [hl₁]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ p + a.utf8Size = utf8Len (l₁ ++ [a])
state_after: no goals

tactic: simp [hl₂]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ p + a.utf8Size = utf8Len (l₂ ++ [a])
state_after: no goals

tactic: simp [hstop, ← Nat.add_assoc, Nat.add_right_comm]
state_before: l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (a :: r₂))
⊢ stop = min (utf8Len (l₁ ++ [a]) + utf8Len r₁) (utf8Len (l₂ ++ [a]) + utf8Len r₂)
state_after: no goals

tactic: simp
state_before: case isFalse
l₁ l₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
x✝¹ x✝ : List Char
a : Char
r₁ : List Char
b : Char
r₂ : List Char
hstop : stop = min (utf8Len l₁ + utf8Len (a :: r₁)) (utf8Len l₂ + utf8Len (b :: r₂))
h✝ : ¬a = b
⊢ { byteIdx := p } = { byteIdx := p + utf8Len ([], []).fst }
state_after: no goals

tactic: next h =>
rw [dif_neg] <;> simp [hstop, ← hl₁, ← hl₂, -Nat.not_lt, Nat.lt_min]
intro h₁ h₂
have : ∀ {cs}, p < p + utf8Len cs → cs ≠ [] := by rintro _ h rfl; simp at h
obtain ⟨a, as, e₁⟩ := List.exists_cons_of_ne_nil (this h₁)
obtain ⟨b, bs, e₂⟩ := List.exists_cons_of_ne_nil (this h₂)
exact h _ _ _ _ e₁ e₂
state_before: case h_2
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝² x✝¹ : List Char
x✝ : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
⊢ (if h : { byteIdx := p } < { byteIdx := stop } then
      if ({ data := l₁ ++ r₁ }.get { byteIdx := p } != { data := l₂ ++ r₂ }.get { byteIdx := p }) = true then
        { byteIdx := p }
      else
        let_fun this := ⋯;
        firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop }
          ({ data := l₁ ++ r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    { byteIdx := p + utf8Len ([], []).fst }
state_after: no goals

tactic: rw [dif_neg] <;> simp [hstop, ← hl₁, ← hl₂, -Nat.not_lt, Nat.lt_min]
state_before: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
⊢ (if h : { byteIdx := p } < { byteIdx := stop } then
      if ({ data := l₁ ++ r₁ }.get { byteIdx := p } != { data := l₂ ++ r₂ }.get { byteIdx := p }) = true then
        { byteIdx := p }
      else
        let_fun this := ⋯;
        firstDiffPos.loop { data := l₁ ++ r₁ } { data := l₂ ++ r₂ } { byteIdx := stop }
          ({ data := l₁ ++ r₁ }.next { byteIdx := p })
    else { byteIdx := p }) =
    { byteIdx := p + utf8Len ([], []).fst }
state_after: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
⊢ p < p + utf8Len r₁ → ¬p < p + utf8Len r₂

tactic: intro h₁ h₂
state_before: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
⊢ p < p + utf8Len r₁ → ¬p < p + utf8Len r₂
state_after: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
⊢ False

tactic: have : ∀ {cs}, p < p + utf8Len cs → cs ≠ [] := by rintro _ h rfl; simp at h
state_before: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
⊢ False
state_after: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
⊢ False

tactic: obtain ⟨a, as, e₁⟩ := List.exists_cons_of_ne_nil (this h₁)
state_before: case hnc
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
⊢ False
state_after: case hnc.intro.intro
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
a : Char
as : List Char
e₁ : r₁ = a :: as
⊢ False

tactic: obtain ⟨b, bs, e₂⟩ := List.exists_cons_of_ne_nil (this h₂)
state_before: case hnc.intro.intro
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
a : Char
as : List Char
e₁ : r₁ = a :: as
⊢ False
state_after: case hnc.intro.intro.intro.intro
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
a : Char
as : List Char
e₁ : r₁ = a :: as
b : Char
bs : List Char
e₂ : r₂ = b :: bs
⊢ False

tactic: exact h _ _ _ _ e₁ e₂
state_before: case hnc.intro.intro.intro.intro
l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
this : ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
a : Char
as : List Char
e₁ : r₁ = a :: as
b : Char
bs : List Char
e₂ : r₂ = b :: bs
⊢ False
state_after: no goals

tactic: rintro _ h rfl
state_before: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
⊢ ∀ {cs : List Char}, p < p + utf8Len cs → cs ≠ []
state_after: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h✝ : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
h : p < p + utf8Len []
⊢ False

tactic: simp at h
state_before: l₁ l₂ r₁ r₂ : List Char
stop p : Nat
hl₁ : p = utf8Len l₁
hl₂ : p = utf8Len l₂
hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)
x✝¹ x✝ : List Char
h✝ : ∀ (a : Char) (as : List Char) (b : Char) (bs : List Char), r₁ = a :: as → r₂ = b :: bs → False
h₁ : p < p + utf8Len r₁
h₂ : p < p + utf8Len r₂
h : p < p + utf8Len []
⊢ False
state_after: no goals