l3lab/ntp-mathlib huggingface dataset:
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    rw [leRecOn_self]

  intro x
  

Proof state:
case step
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
m : ℕ
hnm : Nat.le n m
ih : Function.Surjective (leRecOn hnm fun {k} => next)
x : C (succ m)
⊢ ∃ a, leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) a = x

Next tactic:
rcases Hnext _ x with ⟨w, rfl⟩
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    rw [leRecOn_self]

  intro x
  rcases Hnext _ x with ⟨w, rfl⟩
  

Proof state:
case step.intro
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
m : ℕ
hnm : Nat.le n m
ih : Function.Surjective (leRecOn hnm fun {k} => next)
w : C m
⊢ ∃ a, leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) a = next w

Next tactic:
rcases ih w with ⟨x, rfl⟩
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    rw [leRecOn_self]

  intro x
  rcases Hnext _ x with ⟨w, rfl⟩
  rcases ih w with ⟨x, rfl⟩
  

Proof state:
case step.intro.intro
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
m : ℕ
hnm : Nat.le n m
ih : Function.Surjective (leRecOn hnm fun {k} => next)
x : C n
⊢ ∃ a, leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) a = next (leRecOn hnm (fun {k} => next) x)

Next tactic:
use x
theorem leRecOn_surjective {C : ℕ → Sort u} {n m} (hnm : n ≤ m) (next : ∀ {k}, C k → C (k + 1))
    (Hnext : ∀ n, Function.Surjective (@next n)) :
    Function.Surjective (@leRecOn C n m hnm next) := by
  induction' hnm with m hnm ih
  · intro x
    use x
    rw [leRecOn_self]

  intro x
  rcases Hnext _ x with ⟨w, rfl⟩
  rcases ih w with ⟨x, rfl⟩
  use x
  

Proof state:
case h
m✝¹ n✝ k : ℕ
C : ℕ → Sort u
n m✝ : ℕ
next : {k : ℕ} → C k → C (k + 1)
Hnext : ∀ (n : ℕ), Function.Surjective next
m : ℕ
hnm : Nat.le n m
ih : Function.Surjective (leRecOn hnm fun {k} => next)
x : C n
⊢ leRecOn (_ : Nat.le n (succ m)) (fun {k} => next) x = next (leRecOn hnm (fun {k} => next) x)

Next tactic:
rw [leRecOn_succ]
theorem strongRecOn'_beta {P : ℕ → Sort*} {h} {n : ℕ} :
    (strongRecOn' n h : P n) = h n fun m _ => (strongRecOn' m h : P m) := by
  

Proof state:
m n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → ((m : ℕ) → m < n → P m) → P n
n : ℕ
⊢ strongRecOn' n h = h n fun m x => strongRecOn' m h

Next tactic:
simp only [strongRecOn']
theorem strongRecOn'_beta {P : ℕ → Sort*} {h} {n : ℕ} :
    (strongRecOn' n h : P n) = h n fun m _ => (strongRecOn' m h : P m) := by
  simp only [strongRecOn']
  

Proof state:
m n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → ((m : ℕ) → m < n → P m) → P n
n : ℕ
⊢ Nat.strongRec' h n = h n fun m x => Nat.strongRec' h m

Next tactic:
rw [Nat.strongRec']
/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
for `induction'`). -/
@[elab_as_elim]
theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
  

Proof state:
m✝ n k m : ℕ
P : (n : ℕ) → m ≤ n → Prop
base : P m (_ : m ≤ m)
succ : ∀ (n : ℕ) (hn : m ≤ n), P n hn → P (n + 1) (_ : m ≤ n + 1)
⊢ ∀ (n : ℕ) (hn : m ≤ n), P n hn

Next tactic:
apply Nat.le.rec
/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
for `induction'`). -/
@[elab_as_elim]
theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
  apply Nat.le.rec
  · 

Proof state:
case refl
m✝ n k m : ℕ
P : (n : ℕ) → m ≤ n → Prop
base : P m (_ : m ≤ m)
succ : ∀ (n : ℕ) (hn : m ≤ n), P n hn → P (n + 1) (_ : m ≤ n + 1)
⊢ P m (_ : Nat.le m m)

Next tactic:
exact base
/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
for `induction'`). -/
@[elab_as_elim]
theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
  apply Nat.le.rec
  · exact base
  · 

Proof state:
case step
m✝ n k m : ℕ
P : (n : ℕ) → m ≤ n → Prop
base : P m (_ : m ≤ m)
succ : ∀ (n : ℕ) (hn : m ≤ n), P n hn → P (n + 1) (_ : m ≤ n + 1)
⊢ ∀ {m_1 : ℕ} (a : Nat.le m m_1), P m_1 a → P (Nat.succ m_1) (_ : Nat.le m (Nat.succ m_1))

Next tactic:
intros n hn
/-- Induction principle starting at a non-zero number. For maps to a `Sort*` see `le_rec_on`.
To use in an induction proof, the syntax is `induction n, hn using Nat.le_induction` (or the same
for `induction'`). -/
@[elab_as_elim]
theorem le_induction {m} {P : ∀ (n : Nat) (_ : m ≤ n), Prop} (base : P m le_rfl)
    (succ : ∀ (n : Nat) (hn : m ≤ n), P n hn → P (n + 1) (hn.trans <| Nat.le_succ _)) :
    ∀ (n : Nat) (hn : m ≤ n), P n hn := by
  apply Nat.le.rec
  · exact base
  · intros n hn
    

Proof state:
case step
m✝ n✝ k m : ℕ
P : (n : ℕ) → m ≤ n → Prop
base : P m (_ : m ≤ m)
succ : ∀ (n : ℕ) (hn : m ≤ n), P n hn → P (n + 1) (_ : m ≤ n + 1)
n : ℕ
hn : Nat.le m n
⊢ P n hn → P (Nat.succ n) (_ : Nat.le m (Nat.succ n))

Next tactic:
apply succ n hn
@[simp]
theorem decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
    (hP : P n) :
    (decreasingInduction h nn hP : P n) = hP := by
  

Proof state:
m n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
n : ℕ
nn : n ≤ n
hP : P n
⊢ decreasingInduction h nn hP = hP

Next tactic:
dsimp only [decreasingInduction]
@[simp]
theorem decreasingInduction_self {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {n : ℕ} (nn : n ≤ n)
    (hP : P n) :
    (decreasingInduction h nn hP : P n) = hP := by
  dsimp only [decreasingInduction]
  

Proof state:
m n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
n : ℕ
nn : n ≤ n
hP : P n
⊢ leRecOn nn (fun {k} ih hsk => ih (h k hsk)) (fun h => h) hP = hP

Next tactic:
rw [leRecOn_self]
theorem decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
    (msn : m ≤ n + 1) (hP : P (n + 1)) :
    (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by
  

Proof state:
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n : ℕ
mn : m ≤ n
msn : m ≤ n + 1
hP : P (n + 1)
⊢ decreasingInduction h msn hP = decreasingInduction h mn (h n hP)

Next tactic:
dsimp only [decreasingInduction]
theorem decreasingInduction_succ {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ} (mn : m ≤ n)
    (msn : m ≤ n + 1) (hP : P (n + 1)) :
    (decreasingInduction h msn hP : P m) = decreasingInduction h mn (h n hP) := by
  dsimp only [decreasingInduction]
  

Proof state:
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n : ℕ
mn : m ≤ n
msn : m ≤ n + 1
hP : P (n + 1)
⊢ leRecOn msn (fun {k} ih hsk => ih (h k hsk)) (fun h => h) hP =
    leRecOn mn (fun {k} ih hsk => ih (h k hsk)) (fun h => h) (h n hP)

Next tactic:
rw [leRecOn_succ]
@[simp]
theorem decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
    (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by
  

Proof state:
m✝ n k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m : ℕ
msm : m ≤ m + 1
hP : P (m + 1)
⊢ decreasingInduction h msm hP = h m hP

Next tactic:
dsimp only [decreasingInduction]
@[simp]
theorem decreasingInduction_succ' {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m : ℕ}
    (msm : m ≤ m + 1) (hP : P (m + 1)) : (decreasingInduction h msm hP : P m) = h m hP := by
  dsimp only [decreasingInduction]
  

Proof state:
m✝ n k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m : ℕ
msm : m ≤ m + 1
hP : P (m + 1)
⊢ leRecOn msm (fun {k} ih hsk => ih (h k hsk)) (fun h => h) hP = h m hP

Next tactic:
rw [leRecOn_succ']
theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
    (mn : m ≤ n) (nk : n ≤ k) (hP : P k) :
    (decreasingInduction h (le_trans mn nk) hP : P m) =
    decreasingInduction h mn (decreasingInduction h nk hP) := by
  

Proof state:
m✝ n✝ k✝ : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n k : ℕ
mn : m ≤ n
nk : n ≤ k
hP : P k
⊢ decreasingInduction h (_ : m ≤ k) hP = decreasingInduction h mn (decreasingInduction h nk hP)

Next tactic:
induction' nk with k nk ih
theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
    (mn : m ≤ n) (nk : n ≤ k) (hP : P k) :
    (decreasingInduction h (le_trans mn nk) hP : P m) =
    decreasingInduction h mn (decreasingInduction h nk hP) := by
  induction' nk with k nk ih
  · 

Proof state:
case refl
m✝ n✝ k✝ : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n k : ℕ
mn : m ≤ n
hP : P n
⊢ decreasingInduction h (_ : m ≤ n) hP = decreasingInduction h mn (decreasingInduction h (_ : Nat.le n n) hP)

Next tactic:
rw [decreasingInduction_self]
theorem decreasingInduction_trans {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n k : ℕ}
    (mn : m ≤ n) (nk : n ≤ k) (hP : P k) :
    (decreasingInduction h (le_trans mn nk) hP : P m) =
    decreasingInduction h mn (decreasingInduction h nk hP) := by
  induction' nk with k nk ih
  · rw [decreasingInduction_self]
  · 

Proof state:
case step
m✝ n✝ k✝¹ : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n k✝ : ℕ
mn : m ≤ n
k : ℕ
nk : Nat.le n k
ih : ∀ (hP : P k), decreasingInduction h (_ : m ≤ k) hP = decreasingInduction h mn (decreasingInduction h nk hP)
hP : P (succ k)
⊢ decreasingInduction h (_ : m ≤ succ k) hP =
    decreasingInduction h mn (decreasingInduction h (_ : Nat.le n (succ k)) hP)

Next tactic:
rw [decreasingInduction_succ h (le_trans mn nk), ih, decreasingInduction_succ]
theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ}
    (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) :
    (decreasingInduction h mn hP : P m) = h m (decreasingInduction h smn hP) := by
  

Proof state:
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n : ℕ
smn : m + 1 ≤ n
mn : m ≤ n
hP : P n
⊢ decreasingInduction h mn hP = h m (decreasingInduction h smn hP)

Next tactic:
rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans,
    decreasingInduction_succ']
theorem decreasingInduction_succ_left {P : ℕ → Sort*} (h : ∀ n, P (n + 1) → P n) {m n : ℕ}
    (smn : m + 1 ≤ n) (mn : m ≤ n) (hP : P n) :
    (decreasingInduction h mn hP : P m) = h m (decreasingInduction h smn hP) := by
  rw [Subsingleton.elim mn (le_trans (le_succ m) smn), decreasingInduction_trans,
    decreasingInduction_succ']
  

Proof state:
case msm
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
h : (n : ℕ) → P (n + 1) → P n
m n : ℕ
smn : m + 1 ≤ n
mn : m ≤ n
hP : P n
⊢ m ≤ m + 1

Next tactic:
apply Nat.le_succ
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  

Proof state:
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
m n : ℕ
h : (k : ℕ) → k < n → m ≤ k → P (k + 1) → P k
mn : m ≤ n
hP : P n
⊢ P m

Next tactic:
revert h hP
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  

Proof state:
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
m n : ℕ
mn : m ≤ n
⊢ ((k : ℕ) → k < n → m ≤ k → P (k + 1) → P k) → P n → P m

Next tactic:
refine' leRecOn' mn _ _
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · 

Proof state:
case refine'_1
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
m n : ℕ
mn : m ≤ n
⊢ ⦃k : ℕ⦄ →
    m ≤ k →
      (((k_1 : ℕ) → k_1 < k → m ≤ k_1 → P (k_1 + 1) → P k_1) → P k → P m) →
        ((k_1 : ℕ) → k_1 < k + 1 → m ≤ k_1 → P (k_1 + 1) → P k_1) → P (k + 1) → P m

Next tactic:
intro n mn ih h hP
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · intro n mn ih h hP
    

Proof state:
case refine'_1
m✝ n✝¹ k : ℕ
P : ℕ → Sort u_1
m n✝ : ℕ
mn✝ : m ≤ n✝
n : ℕ
mn : m ≤ n
ih : ((k : ℕ) → k < n → m ≤ k → P (k + 1) → P k) → P n → P m
h : (k : ℕ) → k < n + 1 → m ≤ k → P (k + 1) → P k
hP : P (n + 1)
⊢ P m

Next tactic:
apply ih
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · intro n mn ih h hP
    apply ih
    · 

Proof state:
case refine'_1.h
m✝ n✝¹ k : ℕ
P : ℕ → Sort u_1
m n✝ : ℕ
mn✝ : m ≤ n✝
n : ℕ
mn : m ≤ n
ih : ((k : ℕ) → k < n → m ≤ k → P (k + 1) → P k) → P n → P m
h : (k : ℕ) → k < n + 1 → m ≤ k → P (k + 1) → P k
hP : P (n + 1)
⊢ (k : ℕ) → k < n → m ≤ k → P (k + 1) → P k

Next tactic:
exact fun k hk => h k (Nat.lt.step hk)
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · intro n mn ih h hP
    apply ih
    · exact fun k hk => h k (Nat.lt.step hk)
    · 

Proof state:
case refine'_1.hP
m✝ n✝¹ k : ℕ
P : ℕ → Sort u_1
m n✝ : ℕ
mn✝ : m ≤ n✝
n : ℕ
mn : m ≤ n
ih : ((k : ℕ) → k < n → m ≤ k → P (k + 1) → P k) → P n → P m
h : (k : ℕ) → k < n + 1 → m ≤ k → P (k + 1) → P k
hP : P (n + 1)
⊢ P n

Next tactic:
exact h n (lt_succ_self n) mn hP
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · intro n mn ih h hP
    apply ih
    · exact fun k hk => h k (Nat.lt.step hk)
    · exact h n (lt_succ_self n) mn hP
  · 

Proof state:
case refine'_2
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
m n : ℕ
mn : m ≤ n
⊢ ((k : ℕ) → k < m → m ≤ k → P (k + 1) → P k) → P m → P m

Next tactic:
intro _ hP
/-- Decreasing induction: if `P (k+1)` implies `P k` for all `m ≤ k < n`, then `P n` implies `P m`.
Also works for functions to `Sort*`. Weakens the assumptions of `decreasing_induction`. -/
@[elab_as_elim]
def decreasingInduction' {P : ℕ → Sort*} {m n : ℕ} (h : ∀ k < n, m ≤ k → P (k + 1) → P k)
    (mn : m ≤ n) (hP : P n) :
    P m := by
  revert h hP
  refine' leRecOn' mn _ _
  · intro n mn ih h hP
    apply ih
    · exact fun k hk => h k (Nat.lt.step hk)
    · exact h n (lt_succ_self n) mn hP
  · intro _ hP
    

Proof state:
case refine'_2
m✝ n✝ k : ℕ
P : ℕ → Sort u_1
m n : ℕ
mn : m ≤ n
h✝ : (k : ℕ) → k < m → m ≤ k → P (k + 1) → P k
hP : P m
⊢ P m

Next tactic:
exact hP
theorem one_le_div_iff {a b : ℕ} (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by
  

Proof state:
m n k a b : ℕ
hb : 0 < b
⊢ 1 ≤ a / b ↔ b ≤ a

Next tactic:
rw [le_div_iff_mul_le hb, one_mul]
protected theorem div_le_div_right {n m : ℕ} (h : n ≤ m) {k : ℕ} : n / k ≤ m / k :=
  ((Nat.eq_zero_or_pos k).elim fun k0 => by 

Proof state:
m✝ n✝ k✝ n m : ℕ
h : n ≤ m
k : ℕ
k0 : k = 0
⊢ n / k ≤ m / k

Next tactic:
simp [k0]
protected theorem div_pos {a b : ℕ} (hba : b ≤ a) (hb : 0 < b) : 0 < a / b :=
  Nat.pos_of_ne_zero fun h =>
    lt_irrefl a
      (calc
        a = a % b := by 

Proof state:
m n k a b : ℕ
hba : b ≤ a
hb : 0 < b
h : a / b = 0
⊢ a = a % b

Next tactic:
simpa [h] using (mod_add_div a b).symm
theorem mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c :=
  if hc0 : c = 0 then by 

Proof state:
m n k a b c : ℕ
hc0 : c = 0
⊢ a * (b / c) ≤ a * b / c

Next tactic:
simp [hc0]
theorem mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c :=
  if hc0 : c = 0 then by simp [hc0]
  else
    (Nat.le_div_iff_mul_le (Nat.pos_of_ne_zero hc0)).2
      (by 

Proof state:
m n k a b c : ℕ
hc0 : ¬c = 0
⊢ a * (b / c) * c ≤ a * b

Next tactic:
rw [mul_assoc]
theorem mul_div_le_mul_div_assoc (a b c : ℕ) : a * (b / c) ≤ a * b / c :=
  if hc0 : c = 0 then by simp [hc0]
  else
    (Nat.le_div_iff_mul_le (Nat.pos_of_ne_zero hc0)).2
      (by rw [mul_assoc]; 

Proof state:
m n k a b c : ℕ
hc0 : ¬c = 0
⊢ a * (b / c * c) ≤ a * b

Next tactic:
exact Nat.mul_le_mul_left _ (Nat.div_mul_le_self _ _)
protected theorem eq_mul_of_div_eq_right {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by
  

Proof state:
m n k a b c : ℕ
H1 : b ∣ a
H2 : a / b = c
⊢ a = b * c

Next tactic:
rw [← H2, Nat.mul_div_cancel' H1]
protected theorem div_eq_iff_eq_mul_left {a b c : ℕ} (H : 0 < b) (H' : b ∣ a) :
    a / b = c ↔ a = c * b := by
  

Proof state:
m n k a b c : ℕ
H : 0 < b
H' : b ∣ a
⊢ a / b = c ↔ a = c * b

Next tactic:
rw [mul_comm]
protected theorem div_eq_iff_eq_mul_left {a b c : ℕ} (H : 0 < b) (H' : b ∣ a) :
    a / b = c ↔ a = c * b := by
  rw [mul_comm]
  

Proof state:
m n k a b c : ℕ
H : 0 < b
H' : b ∣ a
⊢ a / b = c ↔ a = b * c

Next tactic:
exact Nat.div_eq_iff_eq_mul_right H H'
protected theorem eq_mul_of_div_eq_left {a b c : ℕ} (H1 : b ∣ a) (H2 : a / b = c) : a = c * b := by
  

Proof state:
m n k a b c : ℕ
H1 : b ∣ a
H2 : a / b = c
⊢ a = c * b

Next tactic:
rw [mul_comm, Nat.eq_mul_of_div_eq_right H1 H2]
protected theorem mul_div_cancel_left' {a b : ℕ} (Hd : a ∣ b) : a * (b / a) = b := by
  

Proof state:
m n k a b : ℕ
Hd : a ∣ b
⊢ a * (b / a) = b

Next tactic:
rw [mul_comm, Nat.div_mul_cancel Hd]
theorem lt_div_mul_add {a b : ℕ} (hb : 0 < b) : a < a / b * b + b := by
  

Proof state:
m n k a b : ℕ
hb : 0 < b
⊢ a < a / b * b + b

Next tactic:
rw [← Nat.succ_mul, ← Nat.div_lt_iff_lt_mul hb]
theorem lt_div_mul_add {a b : ℕ} (hb : 0 < b) : a < a / b * b + b := by
  rw [← Nat.succ_mul, ← Nat.div_lt_iff_lt_mul hb]
  

Proof state:
m n k a b : ℕ
hb : 0 < b
⊢ a / b < succ (a / b)

Next tactic:
exact Nat.lt_succ_self _
@[simp]
protected theorem div_left_inj {a b d : ℕ} (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by
  

Proof state:
m n k a b d : ℕ
hda : d ∣ a
hdb : d ∣ b
⊢ a / d = b / d ↔ a = b

Next tactic:
refine ⟨fun h => ?_, congr_arg fun n => n / d⟩
@[simp]
protected theorem div_left_inj {a b d : ℕ} (hda : d ∣ a) (hdb : d ∣ b) : a / d = b / d ↔ a = b := by
  refine ⟨fun h => ?_, congr_arg fun n => n / d⟩
  

Proof state:
m n k a b d : ℕ
hda : d ∣ a
hdb : d ∣ b
h : a / d = b / d
⊢ a = b

Next tactic:
rw [← Nat.mul_div_cancel' hda, ← Nat.mul_div_cancel' hdb, h]
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  

Proof state:
m n k l : ℕ
hmn : n ∣ m
hkl : l ∣ k
⊢ m / n * (k / l) = m * k / (n * l)

Next tactic:
obtain ⟨x, rfl⟩ := hmn
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  

Proof state:
case intro
n k l : ℕ
hkl : l ∣ k
x : ℕ
⊢ n * x / n * (k / l) = n * x * k / (n * l)

Next tactic:
obtain ⟨y, rfl⟩ := hkl
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  obtain ⟨y, rfl⟩ := hkl
  

Proof state:
case intro.intro
n l x y : ℕ
⊢ n * x / n * (l * y / l) = n * x * (l * y) / (n * l)

Next tactic:
rcases n.eq_zero_or_pos with rfl | hn
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  obtain ⟨y, rfl⟩ := hkl
  rcases n.eq_zero_or_pos with rfl | hn
  · 

Proof state:
case intro.intro.inl
l x y : ℕ
⊢ 0 * x / 0 * (l * y / l) = 0 * x * (l * y) / (0 * l)

Next tactic:
simp
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  obtain ⟨y, rfl⟩ := hkl
  rcases n.eq_zero_or_pos with rfl | hn
  · simp
  

Proof state:
case intro.intro.inr
n l x y : ℕ
hn : n > 0
⊢ n * x / n * (l * y / l) = n * x * (l * y) / (n * l)

Next tactic:
rcases l.eq_zero_or_pos with rfl | hl
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  obtain ⟨y, rfl⟩ := hkl
  rcases n.eq_zero_or_pos with rfl | hn
  · simp
  rcases l.eq_zero_or_pos with rfl | hl
  · 

Proof state:
case intro.intro.inr.inl
n x y : ℕ
hn : n > 0
⊢ n * x / n * (0 * y / 0) = n * x * (0 * y) / (n * 0)

Next tactic:
simp
theorem div_mul_div_comm {l : ℕ} (hmn : n ∣ m) (hkl : l ∣ k) :
    (m / n) * (k / l) = (m * k) / (n * l) := by
  obtain ⟨x, rfl⟩ := hmn
  obtain ⟨y, rfl⟩ := hkl
  rcases n.eq_zero_or_pos with rfl | hn
  · simp
  rcases l.eq_zero_or_pos with rfl | hl
  · simp
  

Proof state:
case intro.intro.inr.inr
n l x y : ℕ
hn : n > 0
hl : l > 0
⊢ n * x / n * (l * y / l) = n * x * (l * y) / (n * l)

Next tactic:
rw [Nat.mul_div_cancel_left _ hn, Nat.mul_div_cancel_left _ hl, mul_assoc n, Nat.mul_left_comm x,
    ← mul_assoc n, Nat.mul_div_cancel_left _ (Nat.mul_pos hn hl)]
protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
  

Proof state:
m n k a b c : ℕ
h : a ∣ b
⊢ (b / a) ^ c = b ^ c / a ^ c

Next tactic:
rcases c.eq_zero_or_pos with rfl | hc
protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
  rcases c.eq_zero_or_pos with rfl | hc
  · 

Proof state:
case inl
m n k a b : ℕ
h : a ∣ b
⊢ (b / a) ^ 0 = b ^ 0 / a ^ 0

Next tactic:
simp
protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
  rcases c.eq_zero_or_pos with rfl | hc
  · simp
  

Proof state:
case inr
m n k a b c : ℕ
h : a ∣ b
hc : c > 0
⊢ (b / a) ^ c = b ^ c / a ^ c

Next tactic:
rcases a.eq_zero_or_pos with rfl | ha
protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
  rcases c.eq_zero_or_pos with rfl | hc
  · simp
  rcases a.eq_zero_or_pos with rfl | ha
  · 

Proof state:
case inr.inl
m n k b c : ℕ
hc : c > 0
h : 0 ∣ b
⊢ (b / 0) ^ c = b ^ c / 0 ^ c

Next tactic:
simp [Nat.zero_pow hc]
protected theorem div_pow {a b c : ℕ} (h : a ∣ b) : (b / a) ^ c = b ^ c / a ^ c := by
  rcases c.eq_zero_or_pos with rfl | hc
  · simp
  rcases a.eq_zero_or_pos with rfl | ha
  · simp [Nat.zero_pow hc]
  

Proof state:
case inr.inr
m n k a b c : ℕ
h : a ∣ b
hc : c > 0
ha : a > 0
⊢ (b / a) ^ c = b ^ c / a ^ c

Next tactic:
refine (Nat.div_eq_of_eq_mul_right (pos_pow_of_pos c ha) ?_).symm