Theorem: Nat.Primrec'.sqrt
File: Mathlib/Computability/Primrec.lean

tactic: introv
state_before: ⊢ ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
state_after: n : ℕ
⊢ n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n

tactic: symm
state_before: n : ℕ
⊢ n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
state_after: n : ℕ
⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt

tactic: induction' n with n IH
state_before: n : ℕ
⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
state_after: case zero

⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) 0 = Nat.sqrt 0

case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) (n + 1) = (n + 1).sqrt

tactic: dsimp
state_before: case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) (n + 1) = (n + 1).sqrt
state_after: case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ (if
        n + 1 <
          (Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) *
            (Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) then
      Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n
    else Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) =
    (n + 1).sqrt

tactic: rw [IH]
state_before: case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ (if
        n + 1 <
          (Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) *
            (Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) then
      Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n
    else Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) n + 1) =
    (n + 1).sqrt
state_after: case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ (if n + 1 < (n.sqrt + 1) * (n.sqrt + 1) then n.sqrt else n.sqrt + 1) = (n + 1).sqrt

tactic: split_ifs with h
state_before: case succ
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
⊢ (if n + 1 < (n.sqrt + 1) * (n.sqrt + 1) then n.sqrt else n.sqrt + 1) = (n + 1).sqrt
state_after: case pos
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
h : n + 1 < (n.sqrt + 1) * (n.sqrt + 1)
⊢ n.sqrt = (n + 1).sqrt

case neg
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
h : ¬n + 1 < (n.sqrt + 1) * (n.sqrt + 1)
⊢ n.sqrt + 1 = (n + 1).sqrt

tactic: simp [H]
state_before: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
⊢ Primrec' fun v => v.head.sqrt
state_after: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
⊢ Primrec' fun v => Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) v.head

tactic: have :=
  @prec' 1 _ _
    (fun v => by
      have x := v.head; have y := v.tail.head;
        exact if x.succ < y.succ * y.succ then y else y.succ)
    head (const 0) ?_
state_before: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
⊢ Primrec' fun v => Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) v.head
state_after: case refine_2
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
this :
  Primrec' fun v =>
    Nat.rec 0
      (fun y IH =>
        (fun v =>
            let_fun x := v.head;
            let_fun y := v.tail.head;
            if x.succ < y.succ * y.succ then y else y.succ)
          (y ::ᵥ IH ::ᵥ v))
      v.head
⊢ Primrec' fun v => Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) v.head

case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ

tactic: have x1 : @Primrec' 3 fun v => v.head.succ := succ.comp₁ _ head
state_before: case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ
state_after: case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
x1 : Primrec' fun v => v.head.succ
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ

tactic: have y1 : @Primrec' 3 fun v => v.tail.head.succ := succ.comp₁ _ (tail head)
state_before: case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
x1 : Primrec' fun v => v.head.succ
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ
state_after: case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
x1 : Primrec' fun v => v.head.succ
y1 : Primrec' fun v => v.tail.head.succ
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ

tactic: exact if_lt x1 (mul.comp₂ _ y1 y1) (tail head) y1
state_before: case refine_1
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
x1 : Primrec' fun v => v.head.succ
y1 : Primrec' fun v => v.tail.head.succ
⊢ Primrec' fun v =>
    let_fun x := v.head;
    let_fun y := v.tail.head;
    if x.succ < y.succ * y.succ then y else y.succ
state_after: no goals

tactic: have x := v.head
state_before: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
v : Vector ℕ (1 + 2)
⊢ ℕ
state_after: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
v : Vector ℕ (1 + 2)
x : ℕ
⊢ ℕ

tactic: have y := v.tail.head
state_before: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
v : Vector ℕ (1 + 2)
x : ℕ
⊢ ℕ
state_after: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
v : Vector ℕ (1 + 2)
x y : ℕ
⊢ ℕ

tactic: exact if x.succ < y.succ * y.succ then y else y.succ
state_before: H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
v : Vector ℕ (1 + 2)
x y : ℕ
⊢ ℕ
state_after: no goals

tactic: exact this
state_before: case refine_2
H : ∀ (n : ℕ), n.sqrt = Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n
this :
  Primrec' fun v =>
    Nat.rec 0
      (fun y IH =>
        (fun v =>
            let_fun x := v.head;
            let_fun y := v.tail.head;
            if x.succ < y.succ * y.succ then y else y.succ)
          (y ::ᵥ IH ::ᵥ v))
      v.head
⊢ Primrec' fun v => Nat.rec 0 (fun x y => if x + 1 < (y + 1) * (y + 1) then y else y + 1) v.head
state_after: no goals

tactic: simp
state_before: case zero

⊢ Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) 0 = Nat.sqrt 0
state_after: no goals

tactic: exact le_antisymm (Nat.sqrt_le_sqrt (Nat.le_succ _)) (Nat.lt_succ_iff.1 <| Nat.sqrt_lt.2 h)
state_before: case pos
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
h : n + 1 < (n.sqrt + 1) * (n.sqrt + 1)
⊢ n.sqrt = (n + 1).sqrt
state_after: no goals

tactic: exact
  Nat.eq_sqrt.2 ⟨not_lt.1 h, Nat.sqrt_lt.1 <| Nat.lt_succ_iff.2 <| Nat.sqrt_succ_le_succ_sqrt _⟩
state_before: case neg
n : ℕ
IH : Nat.rec 0 (fun x y => if x.succ < y.succ * y.succ then y else y.succ) n = n.sqrt
h : ¬n + 1 < (n.sqrt + 1) * (n.sqrt + 1)
⊢ n.sqrt + 1 = (n + 1).sqrt
state_after: no goals