l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem ack_three (n : ℕ) : ack 3 n = 2 ^ (n + 3) - 3 := by
  induction' n with n IH
  · rfl
  · rw [ack_succ_succ, IH, ack_two, Nat.succ_add, Nat.pow_succ 2 (n + 3), mul_comm _ 2,
        Nat.mul_sub_left_distrib, ← Nat.sub_add_comm, two_mul 3, Nat.add_sub_add_right]
    have H : 2 * 3 ≤ 2 * 2 ^ 3 := by norm_num
    apply H.trans
    simp [pow_le_pow_right (show 1 ≤ 2 by 

Proof state:
n : ℕ
IH : ack 3 n = 2 ^ (n + 3) - 3
H : 2 * 3 ≤ 2 * 2 ^ 3
⊢ 1 ≤ 2

Next tactic:
norm_num
theorem ack_pos : ∀ m n, 0 < ack m n
  | 0, n => by 

Proof state:
n : ℕ
⊢ 0 < ack 0 n

Next tactic:
simp
theorem ack_pos : ∀ m n, 0 < ack m n
  | 0, n => by simp
  | m + 1, 0 => by
    

Proof state:
m : ℕ
⊢ 0 < ack (m + 1) 0

Next tactic:
rw [ack_succ_zero]
theorem ack_pos : ∀ m n, 0 < ack m n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    

Proof state:
m : ℕ
⊢ 0 < ack m 1

Next tactic:
apply ack_pos
theorem ack_pos : ∀ m n, 0 < ack m n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    apply ack_pos
  | m + 1, n + 1 => by
    

Proof state:
m n : ℕ
⊢ 0 < ack (m + 1) (n + 1)

Next tactic:
rw [ack_succ_succ]
theorem ack_pos : ∀ m n, 0 < ack m n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    apply ack_pos
  | m + 1, n + 1 => by
    rw [ack_succ_succ]
    

Proof state:
m n : ℕ
⊢ 0 < ack m (ack (m + 1) n)

Next tactic:
apply ack_pos
theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  | 0, n => by 

Proof state:
n : ℕ
⊢ 1 < ack (0 + 1) n

Next tactic:
simp
theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  | 0, n => by simp
  | m + 1, 0 => by
    

Proof state:
m : ℕ
⊢ 1 < ack (m + 1 + 1) 0

Next tactic:
rw [ack_succ_zero]
theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    

Proof state:
m : ℕ
⊢ 1 < ack (m + 1) 1

Next tactic:
apply one_lt_ack_succ_left
theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    apply one_lt_ack_succ_left
  | m + 1, n + 1 => by
    

Proof state:
m n : ℕ
⊢ 1 < ack (m + 1 + 1) (n + 1)

Next tactic:
rw [ack_succ_succ]
theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  | 0, n => by simp
  | m + 1, 0 => by
    rw [ack_succ_zero]
    apply one_lt_ack_succ_left
  | m + 1, n + 1 => by
    rw [ack_succ_succ]
    

Proof state:
m n : ℕ
⊢ 1 < ack (m + 1) (ack (m + 1 + 1) n)

Next tactic:
apply one_lt_ack_succ_left
theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  | 0, n => by 

Proof state:
n : ℕ
⊢ 1 < ack 0 (n + 1)

Next tactic:
simp
theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  | 0, n => by simp
  | m + 1, n => by
    

Proof state:
m n : ℕ
⊢ 1 < ack (m + 1) (n + 1)

Next tactic:
rw [ack_succ_succ]
theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  | 0, n => by simp
  | m + 1, n => by
    rw [ack_succ_succ]
    

Proof state:
m n : ℕ
⊢ 1 < ack m (ack (m + 1) n)

Next tactic:
cases' exists_eq_succ_of_ne_zero (ack_pos (m + 1) n).ne' with h h
theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  | 0, n => by simp
  | m + 1, n => by
    rw [ack_succ_succ]
    cases' exists_eq_succ_of_ne_zero (ack_pos (m + 1) n).ne' with h h
    

Proof state:
case intro
m n h✝ : ℕ
h : ack (m + 1) n = succ h✝
⊢ 1 < ack m (ack (m + 1) n)

Next tactic:
rw [h]
theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  | 0, n => by simp
  | m + 1, n => by
    rw [ack_succ_succ]
    cases' exists_eq_succ_of_ne_zero (ack_pos (m + 1) n).ne' with h h
    rw [h]
    

Proof state:
case intro
m n h✝ : ℕ
h : ack (m + 1) n = succ h✝
⊢ 1 < ack m (succ h✝)

Next tactic:
apply one_lt_ack_succ_right
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by 

Proof state:
n₁ n₂ : ℕ
h : n₁ < n₂
⊢ ack 0 n₁ < ack 0 n₂

Next tactic:
simpa using h
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by simpa using h
  | m + 1, 0, n + 1, _h => by
    

Proof state:
m n : ℕ
_h : 0 < n + 1
⊢ ack (m + 1) 0 < ack (m + 1) (n + 1)

Next tactic:
rw [ack_succ_zero, ack_succ_succ]
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by simpa using h
  | m + 1, 0, n + 1, _h => by
    rw [ack_succ_zero, ack_succ_succ]
    

Proof state:
m n : ℕ
_h : 0 < n + 1
⊢ ack m 1 < ack m (ack (m + 1) n)

Next tactic:
exact ack_strictMono_right _ (one_lt_ack_succ_left m n)
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by simpa using h
  | m + 1, 0, n + 1, _h => by
    rw [ack_succ_zero, ack_succ_succ]
    exact ack_strictMono_right _ (one_lt_ack_succ_left m n)
  | m + 1, n₁ + 1, n₂ + 1, h => by
    

Proof state:
m n₁ n₂ : ℕ
h : n₁ + 1 < n₂ + 1
⊢ ack (m + 1) (n₁ + 1) < ack (m + 1) (n₂ + 1)

Next tactic:
rw [ack_succ_succ, ack_succ_succ]
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by simpa using h
  | m + 1, 0, n + 1, _h => by
    rw [ack_succ_zero, ack_succ_succ]
    exact ack_strictMono_right _ (one_lt_ack_succ_left m n)
  | m + 1, n₁ + 1, n₂ + 1, h => by
    rw [ack_succ_succ, ack_succ_succ]
    

Proof state:
m n₁ n₂ : ℕ
h : n₁ + 1 < n₂ + 1
⊢ ack m (ack (m + 1) n₁) < ack m (ack (m + 1) n₂)

Next tactic:
apply ack_strictMono_right _ (ack_strictMono_right _ _)
theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  | 0, n₁, n₂, h => by simpa using h
  | m + 1, 0, n + 1, _h => by
    rw [ack_succ_zero, ack_succ_succ]
    exact ack_strictMono_right _ (one_lt_ack_succ_left m n)
  | m + 1, n₁ + 1, n₂ + 1, h => by
    rw [ack_succ_succ, ack_succ_succ]
    apply ack_strictMono_right _ (ack_strictMono_right _ _)
    

Proof state:
m n₁ n₂ : ℕ
h : n₁ + 1 < n₂ + 1
⊢ n₁ < n₂

Next tactic:
rwa [add_lt_add_iff_right] at h
theorem add_lt_ack : ∀ m n, m + n < ack m n
  | 0, n => by 

Proof state:
n : ℕ
⊢ 0 + n < ack 0 n

Next tactic:
simp
theorem add_lt_ack : ∀ m n, m + n < ack m n
  | 0, n => by simp
  | m + 1, 0 => by 

Proof state:
m : ℕ
⊢ m + 1 + 0 < ack (m + 1) 0

Next tactic:
simpa using add_lt_ack m 1
theorem add_lt_ack : ∀ m n, m + n < ack m n
  | 0, n => by simp
  | m + 1, 0 => by simpa using add_lt_ack m 1
  | m + 1, n + 1 =>
    calc
      m + 1 + n + 1 ≤ m + (m + n + 2) := by 

Proof state:
m n : ℕ
⊢ m + 1 + n + 1 ≤ m + (m + n + 2)

Next tactic:
linarith
theorem add_lt_ack : ∀ m n, m + n < ack m n
  | 0, n => by simp
  | m + 1, 0 => by simpa using add_lt_ack m 1
  | m + 1, n + 1 =>
    calc
      m + 1 + n + 1 ≤ m + (m + n + 2) := by linarith
      _ < ack m (m + n + 2) := add_lt_ack _ _
      _ ≤ ack m (ack (m + 1) n) :=
        ack_mono_right m <| le_of_eq_of_le (by 

Proof state:
m n : ℕ
⊢ m + n + 2 = succ (m + 1 + n)

Next tactic:
rw [succ_eq_add_one]
theorem add_lt_ack : ∀ m n, m + n < ack m n
  | 0, n => by simp
  | m + 1, 0 => by simpa using add_lt_ack m 1
  | m + 1, n + 1 =>
    calc
      m + 1 + n + 1 ≤ m + (m + n + 2) := by linarith
      _ < ack m (m + n + 2) := add_lt_ack _ _
      _ ≤ ack m (ack (m + 1) n) :=
        ack_mono_right m <| le_of_eq_of_le (by rw [succ_eq_add_one]; 

Proof state:
m n : ℕ
⊢ m + n + 2 = m + 1 + n + 1

Next tactic:
ring_nf
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by 

Proof state:
m : ℕ
_h : 0 < m + 1
⊢ ack 0 0 < ack (m + 1) 0

Next tactic:
simpa using one_lt_ack_succ_right m 0
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    

Proof state:
m n : ℕ
h : 0 < m + 1
⊢ ack 0 (n + 1) < ack (m + 1) (n + 1)

Next tactic:
rw [ack_zero, ack_succ_succ]
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    rw [ack_zero, ack_succ_succ]
    

Proof state:
m n : ℕ
h : 0 < m + 1
⊢ n + 1 + 1 < ack m (ack (m + 1) n)

Next tactic:
apply lt_of_le_of_lt (le_trans _ <| add_le_add_left (add_add_one_le_ack _ _) m) (add_lt_ack _ _)
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    rw [ack_zero, ack_succ_succ]
    apply lt_of_le_of_lt (le_trans _ <| add_le_add_left (add_add_one_le_ack _ _) m) (add_lt_ack _ _)
    

Proof state:
m n : ℕ
h : 0 < m + 1
⊢ n + 1 + 1 ≤ m + (m + 1 + n + 1)

Next tactic:
linarith
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    rw [ack_zero, ack_succ_succ]
    apply lt_of_le_of_lt (le_trans _ <| add_le_add_left (add_add_one_le_ack _ _) m) (add_lt_ack _ _)
    linarith
  | m₁ + 1, m₂ + 1, 0 => fun h => by
    

Proof state:
m₁ m₂ : ℕ
h : m₁ + 1 < m₂ + 1
⊢ ack (m₁ + 1) 0 < ack (m₂ + 1) 0

Next tactic:
simpa using ack_strict_mono_left' 1 ((add_lt_add_iff_right 1).1 h)
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    rw [ack_zero, ack_succ_succ]
    apply lt_of_le_of_lt (le_trans _ <| add_le_add_left (add_add_one_le_ack _ _) m) (add_lt_ack _ _)
    linarith
  | m₁ + 1, m₂ + 1, 0 => fun h => by
    simpa using ack_strict_mono_left' 1 ((add_lt_add_iff_right 1).1 h)
  | m₁ + 1, m₂ + 1, n + 1 => fun h => by
    

Proof state:
m₁ m₂ n : ℕ
h : m₁ + 1 < m₂ + 1
⊢ ack (m₁ + 1) (n + 1) < ack (m₂ + 1) (n + 1)

Next tactic:
rw [ack_succ_succ, ack_succ_succ]
private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  | m, 0, n => fun h => (not_lt_zero m h).elim
  | 0, m + 1, 0 => fun _h => by simpa using one_lt_ack_succ_right m 0
  | 0, m + 1, n + 1 => fun h => by
    rw [ack_zero, ack_succ_succ]
    apply lt_of_le_of_lt (le_trans _ <| add_le_add_left (add_add_one_le_ack _ _) m) (add_lt_ack _ _)
    linarith
  | m₁ + 1, m₂ + 1, 0 => fun h => by
    simpa using ack_strict_mono_left' 1 ((add_lt_add_iff_right 1).1 h)
  | m₁ + 1, m₂ + 1, n + 1 => fun h => by
    rw [ack_succ_succ, ack_succ_succ]
    

Proof state:
m₁ m₂ n : ℕ
h : m₁ + 1 < m₂ + 1
⊢ ack m₁ (ack (m₁ + 1) n) < ack m₂ (ack (m₂ + 1) n)

Next tactic:
exact
      (ack_strict_mono_left' _ <| (add_lt_add_iff_right 1).1 h).trans
        (ack_strictMono_right _ <| ack_strict_mono_left' n h)
theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n := by
  

Proof state:
m n : ℕ
⊢ ack m (n + 1) ≤ ack (m + 1) n

Next tactic:
cases' n with n n
theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n := by
  cases' n with n n
  · 

Proof state:
case zero
m : ℕ
⊢ ack m (zero + 1) ≤ ack (m + 1) zero

Next tactic:
simp
theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n := by
  cases' n with n n
  · simp
  · 

Proof state:
case succ
m n : ℕ
⊢ ack m (succ n + 1) ≤ ack (m + 1) (succ n)

Next tactic:
rw [ack_succ_succ, succ_eq_add_one]
theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n := by
  cases' n with n n
  · simp
  · rw [ack_succ_succ, succ_eq_add_one]
    

Proof state:
case succ
m n : ℕ
⊢ ack m (n + 1 + 1) ≤ ack m (ack (m + 1) n)

Next tactic:
apply ack_mono_right m (le_trans _ <| add_add_one_le_ack _ n)
theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n := by
  cases' n with n n
  · simp
  · rw [ack_succ_succ, succ_eq_add_one]
    apply ack_mono_right m (le_trans _ <| add_add_one_le_ack _ n)
    

Proof state:
m n : ℕ
⊢ n + 1 + 1 ≤ m + 1 + n + 1

Next tactic:
linarith
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  

Proof state:
n : ℕ
⊢ n ^ 2 ≤ 2 ^ (n + 1) - 3

Next tactic:
induction' n with k hk
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · 

Proof state:
case zero
⊢ zero ^ 2 ≤ 2 ^ (zero + 1) - 3

Next tactic:
norm_num
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · 

Proof state:
case succ
k : ℕ
hk : k ^ 2 ≤ 2 ^ (k + 1) - 3
⊢ succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3

Next tactic:
cases' k with k k
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · 

Proof state:
case succ.zero
hk : zero ^ 2 ≤ 2 ^ (zero + 1) - 3
⊢ succ zero ^ 2 ≤ 2 ^ (succ zero + 1) - 3

Next tactic:
norm_num
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · 

Proof state:
case succ.succ
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ succ (succ k) ^ 2 ≤ 2 ^ (succ (succ k) + 1) - 3

Next tactic:
rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · 

Proof state:
case succ.succ
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ (k + 1) ^ 2 + (2 * (k + 1) * 1 + 1 ^ 2) ≤ 2 ^ (k + 2) - 3 + 2 ^ (k + 2)

Next tactic:
apply Nat.add_le_add hk
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        

Proof state:
case succ.succ
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ 2 * (k + 1) * 1 + 1 ^ 2 ≤ 2 ^ (k + 2)

Next tactic:
norm_num
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        norm_num
        

Proof state:
case succ.succ
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ 2 * (k + 1) + 1 ≤ 2 ^ (k + 2)

Next tactic:
apply succ_le_of_lt
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        norm_num
        apply succ_le_of_lt
        

Proof state:
case succ.succ.h
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ 2 * (k + 1) < 2 ^ (k + 2)

Next tactic:
rw [Nat.pow_succ, mul_comm _ 2, mul_lt_mul_left (zero_lt_two' ℕ)]
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        norm_num
        apply succ_le_of_lt
        rw [Nat.pow_succ, mul_comm _ 2, mul_lt_mul_left (zero_lt_two' ℕ)]
        

Proof state:
case succ.succ.h
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ k + 1 < 2 ^ (k + 1)

Next tactic:
apply lt_two_pow
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        norm_num
        apply succ_le_of_lt
        rw [Nat.pow_succ, mul_comm _ 2, mul_lt_mul_left (zero_lt_two' ℕ)]
        apply lt_two_pow
      · 

Proof state:
case succ.succ.h
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ 3 ≤ 2 ^ (k + 2)

Next tactic:
rw [Nat.pow_succ, Nat.pow_succ]
private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 := by
  induction' n with k hk
  · norm_num
  · cases' k with k k
    · norm_num
    · rw [succ_eq_add_one, add_sq, Nat.pow_succ 2, mul_comm _ 2, two_mul (2 ^ _),
          add_tsub_assoc_of_le, add_comm (2 ^ _), add_assoc]
      · apply Nat.add_le_add hk
        norm_num
        apply succ_le_of_lt
        rw [Nat.pow_succ, mul_comm _ 2, mul_lt_mul_left (zero_lt_two' ℕ)]
        apply lt_two_pow
      · rw [Nat.pow_succ, Nat.pow_succ]
        

Proof state:
case succ.succ.h
k : ℕ
hk : succ k ^ 2 ≤ 2 ^ (succ k + 1) - 3
⊢ 3 ≤ 2 ^ k * 2 * 2

Next tactic:
linarith [one_le_pow k 2 zero_lt_two]
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by 

Proof state:
n : ℕ
⊢ (ack 0 n + 1) ^ 2 ≤ ack (0 + 3) n

Next tactic:
simpa using sq_le_two_pow_add_one_minus_three (n + 2)
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by simpa using sq_le_two_pow_add_one_minus_three (n + 2)
  | m + 1, 0 => by
    

Proof state:
m : ℕ
⊢ (ack (m + 1) 0 + 1) ^ 2 ≤ ack (m + 1 + 3) 0

Next tactic:
rw [ack_succ_zero, ack_succ_zero]
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by simpa using sq_le_two_pow_add_one_minus_three (n + 2)
  | m + 1, 0 => by
    rw [ack_succ_zero, ack_succ_zero]
    

Proof state:
m : ℕ
⊢ (ack m 1 + 1) ^ 2 ≤ ack (m + 3) 1

Next tactic:
apply ack_add_one_sq_lt_ack_add_three
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by simpa using sq_le_two_pow_add_one_minus_three (n + 2)
  | m + 1, 0 => by
    rw [ack_succ_zero, ack_succ_zero]
    apply ack_add_one_sq_lt_ack_add_three
  | m + 1, n + 1 => by
    

Proof state:
m n : ℕ
⊢ (ack (m + 1) (n + 1) + 1) ^ 2 ≤ ack (m + 1 + 3) (n + 1)

Next tactic:
rw [ack_succ_succ, ack_succ_succ]
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by simpa using sq_le_two_pow_add_one_minus_three (n + 2)
  | m + 1, 0 => by
    rw [ack_succ_zero, ack_succ_zero]
    apply ack_add_one_sq_lt_ack_add_three
  | m + 1, n + 1 => by
    rw [ack_succ_succ, ack_succ_succ]
    

Proof state:
m n : ℕ
⊢ (ack m (ack (m + 1) n) + 1) ^ 2 ≤ ack (m + 3) (ack (m + 3 + 1) n)

Next tactic:
apply (ack_add_one_sq_lt_ack_add_three _ _).trans (ack_mono_right _ <| ack_mono_left _ _)
theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  | 0, n => by simpa using sq_le_two_pow_add_one_minus_three (n + 2)
  | m + 1, 0 => by
    rw [ack_succ_zero, ack_succ_zero]
    apply ack_add_one_sq_lt_ack_add_three
  | m + 1, n + 1 => by
    rw [ack_succ_succ, ack_succ_succ]
    apply (ack_add_one_sq_lt_ack_add_three _ _).trans (ack_mono_right _ <| ack_mono_left _ _)
    

Proof state:
m n : ℕ
⊢ m + 1 ≤ m + 3 + 1

Next tactic:
linarith
theorem ack_add_one_sq_lt_ack_add_four (m n : ℕ) : ack m ((n + 1) ^ 2) < ack (m + 4) n :=
  calc
    ack m ((n + 1) ^ 2) < ack m ((ack m n + 1) ^ 2) :=
      ack_strictMono_right m <| Nat.pow_lt_pow_left (succ_lt_succ <| lt_ack_right m n) two_ne_zero
    _ ≤ ack m (ack (m + 3) n) := ack_mono_right m <| ack_add_one_sq_lt_ack_add_three m n
    _ ≤ ack (m + 2) (ack (m + 3) n) := ack_mono_left _ <| by 

Proof state:
m n : ℕ
⊢ m ≤ m + 2

Next tactic:
linarith
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  

Proof state:
f : ℕ → ℕ
hf : Nat.Primrec f
⊢ ∃ m, ∀ (n : ℕ), f n < ack m n

Next tactic:
induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · 

Proof state:
case zero
f : ℕ → ℕ
⊢ ∃ m, ∀ (n : ℕ), (fun x => 0) n < ack m n

Next tactic:
exact ⟨0, ack_pos 0⟩
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · 

Proof state:
case succ
f : ℕ → ℕ
⊢ ∃ m, ∀ (n : ℕ), succ n < ack m n

Next tactic:
refine' ⟨1, fun n => _⟩
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · refine' ⟨1, fun n => _⟩
    

Proof state:
case succ
f : ℕ → ℕ
n : ℕ
⊢ succ n < ack 1 n

Next tactic:
rw [succ_eq_one_add]
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · refine' ⟨1, fun n => _⟩
    rw [succ_eq_one_add]
    

Proof state:
case succ
f : ℕ → ℕ
n : ℕ
⊢ 1 + n < ack 1 n

Next tactic:
apply add_lt_ack
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · refine' ⟨1, fun n => _⟩
    rw [succ_eq_one_add]
    apply add_lt_ack
  -- Left projection:
  · 

Proof state:
case left
f : ℕ → ℕ
⊢ ∃ m, ∀ (n : ℕ), (fun n => (unpair n).1) n < ack m n

Next tactic:
refine' ⟨0, fun n => _⟩
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · refine' ⟨1, fun n => _⟩
    rw [succ_eq_one_add]
    apply add_lt_ack
  -- Left projection:
  · refine' ⟨0, fun n => _⟩
    

Proof state:
case left
f : ℕ → ℕ
n : ℕ
⊢ (fun n => (unpair n).1) n < ack 0 n

Next tactic:
rw [ack_zero, lt_succ_iff]
/-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n := by
  induction' hf with f g hf hg IHf IHg f g hf hg IHf IHg f g hf hg IHf IHg
  -- Zero function:
  · exact ⟨0, ack_pos 0⟩
  -- Successor function:
  · refine' ⟨1, fun n => _⟩
    rw [succ_eq_one_add]
    apply add_lt_ack
  -- Left projection:
  · refine' ⟨0, fun n => _⟩
    rw [ack_zero, lt_succ_iff]
    

Proof state:
case left
f : ℕ → ℕ
n : ℕ
⊢ (fun n => (unpair n).1) n ≤ n

Next tactic:
exact unpair_left_le n