l3lab/ntp-mathlib huggingface dataset:
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : ¬IsMax a
b : Fin (n + 1)
⊢ a < b ↔ (fun i => if i < last n then i + 1 else i) a ≤ b

Next tactic:
rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a < last n
b : Fin (n + 1)
⊢ a < b ↔ (fun i => if i < last n then i + 1 else i) a ≤ b

Next tactic:
dsimp
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a < last n
b : Fin (n + 1)
⊢ a < b ↔ (if a < last n then a + 1 else a) ≤ b

Next tactic:
rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a < last n
b : Fin (n + 1)
⊢ ↑a < ↑b ↔ ↑a + 1 ≤ ↑b

Next tactic:
exact Nat.lt_iff_add_one_le
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
        exact Nat.lt_iff_add_one_le)
      (by
        

Proof state:
n : ℕ
⊢ ∀ (a : Fin (n + 1)), IsMax a → (fun i => if i < last n then i + 1 else i) a = a

Next tactic:
intro a ha
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
        exact Nat.lt_iff_add_one_le)
      (by
        intro a ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : IsMax a
⊢ (fun i => if i < last n then i + 1 else i) a = a

Next tactic:
rw [isMax_iff_eq_top, top_eq_last] at ha
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
        exact Nat.lt_iff_add_one_le)
      (by
        intro a ha
        rw [isMax_iff_eq_top, top_eq_last] at ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a = last n
⊢ (fun i => if i < last n then i + 1 else i) a = a

Next tactic:
dsimp
instance : ∀ {n : ℕ}, SuccOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    SuccOrder.ofCore (fun i => if i < Fin.last n then i + 1 else i)
      (by
        intro a ha b
        rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
        dsimp
        rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
        exact Nat.lt_iff_add_one_le)
      (by
        intro a ha
        rw [isMax_iff_eq_top, top_eq_last] at ha
        dsimp
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a = last n
⊢ (if a < last n then a + 1 else a) = a

Next tactic:
rw [if_neg ha.not_lt]
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by 

Proof state:
⊢ PredOrder (Fin 0)

Next tactic:
constructor
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> 

Proof state:
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a

Next tactic:
first | assumption | intro a; exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | 

Proof state:
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a

Next tactic:
assumption
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | 

Proof state:
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a

Next tactic:
intro a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; 

Proof state:
case pred_le
a : Fin 0
⊢ ?pred a ≤ a

Next tactic:
exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> 

Proof state:
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a

Next tactic:
first | assumption | intro a; exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | 

Proof state:
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a

Next tactic:
assumption
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | 

Proof state:
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a

Next tactic:
intro a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; 

Proof state:
case min_of_le_pred
a : Fin 0
⊢ a ≤ ?pred a → IsMin a

Next tactic:
exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> 

Proof state:
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b

Next tactic:
first | assumption | intro a; exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | 

Proof state:
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b

Next tactic:
assumption
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | 

Proof state:
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b

Next tactic:
intro a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; 

Proof state:
case le_pred_of_lt
a : Fin 0
⊢ ∀ {b : Fin 0}, a < b → a ≤ ?pred b

Next tactic:
exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> 

Proof state:
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b

Next tactic:
first | assumption | intro a; exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | 

Proof state:
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b

Next tactic:
assumption
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | 

Proof state:
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b

Next tactic:
intro a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; 

Proof state:
case le_of_pred_lt
a : Fin 0
⊢ ∀ {b : Fin 0}, ?pred a < b → a ≤ b

Next tactic:
exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> 

Proof state:
case pred
⊢ Fin 0 → Fin 0

Next tactic:
first | assumption | intro a; exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | 

Proof state:
case pred
⊢ Fin 0 → Fin 0

Next tactic:
assumption
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | 

Proof state:
case pred
⊢ Fin 0 → Fin 0

Next tactic:
intro a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; 

Proof state:
case pred
a : Fin 0
⊢ Fin 0

Next tactic:
exact elim0 a
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        

Proof state:
n : ℕ
⊢ ∀ {a : Fin (n + 1)}, ¬IsMin a → ∀ (b : Fin (n + 1)), b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a

Next tactic:
intro a ha b
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : ¬IsMin a
b : Fin (n + 1)
⊢ b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a

Next tactic:
rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : 0 < a
b : Fin (n + 1)
⊢ b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a

Next tactic:
dsimp
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : 0 < a
b : Fin (n + 1)
⊢ (b ≤ if a = 0 then 0 else a - 1) ↔ b < a

Next tactic:
rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : 0 < a
b : Fin (n + 1)
⊢ ↑b < ↑a ↔ ↑b + 1 ≤ ↑a
n : ℕ a : Fin (n + 1) ha : 0 < a b : Fin (n + 1) ⊢ 1 ≤ ↑a

Next tactic:
exact Nat.lt_iff_add_one_le
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        exact Nat.lt_iff_add_one_le
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : 0 < a
b : Fin (n + 1)
⊢ 1 ≤ ↑a

Next tactic:
exact ha
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        exact Nat.lt_iff_add_one_le
        exact ha)
      (by
        

Proof state:
n : ℕ
⊢ ∀ (a : Fin (n + 1)), IsMin a → (fun x => if x = 0 then 0 else x - 1) a = a

Next tactic:
intro a ha
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        exact Nat.lt_iff_add_one_le
        exact ha)
      (by
        intro a ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : IsMin a
⊢ (fun x => if x = 0 then 0 else x - 1) a = a

Next tactic:
rw [isMin_iff_eq_bot, bot_eq_zero] at ha
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        exact Nat.lt_iff_add_one_le
        exact ha)
      (by
        intro a ha
        rw [isMin_iff_eq_bot, bot_eq_zero] at ha
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a = 0
⊢ (fun x => if x = 0 then 0 else x - 1) a = a

Next tactic:
dsimp
instance : ∀ {n : ℕ}, PredOrder (Fin n)
  | 0 => by constructor <;> first | assumption | intro a; exact elim0 a
  | n + 1 =>
    PredOrder.ofCore (fun x => if x = 0 then 0 else x - 1)
      (by
        intro a ha b
        rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
        dsimp
        rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne',
          le_tsub_iff_right, Iff.comm]
        exact Nat.lt_iff_add_one_le
        exact ha)
      (by
        intro a ha
        rw [isMin_iff_eq_bot, bot_eq_zero] at ha
        dsimp
        

Proof state:
n : ℕ
a : Fin (n + 1)
ha : a = 0
⊢ (if a = 0 then 0 else a - 1) = a

Next tactic:
rwa [if_pos ha, eq_comm]
@[simp]
theorem choose_zero_right (n : ℕ) : choose n 0 = 1 := by 

Proof state:
n : ℕ
⊢ choose n 0 = 1

Next tactic:
cases n
@[simp]
theorem choose_zero_right (n : ℕ) : choose n 0 = 1 := by cases n <;> 

Proof state:
case zero
⊢ choose zero 0 = 1

Next tactic:
rfl
@[simp]
theorem choose_zero_right (n : ℕ) : choose n 0 = 1 := by cases n <;> 

Proof state:
case succ
n✝ : ℕ
⊢ choose (succ n✝) 0 = 1

Next tactic:
rfl
theorem choose_eq_zero_of_lt : ∀ {n k}, n < k → choose n k = 0
  | _, 0, hk => absurd hk (Nat.not_lt_zero _)
  | 0, k + 1, _ => choose_zero_succ _
  | n + 1, k + 1, hk => by
    

Proof state:
n k : ℕ
hk : n + 1 < k + 1
⊢ choose (n + 1) (k + 1) = 0

Next tactic:
have hnk : n < k := lt_of_succ_lt_succ hk
theorem choose_eq_zero_of_lt : ∀ {n k}, n < k → choose n k = 0
  | _, 0, hk => absurd hk (Nat.not_lt_zero _)
  | 0, k + 1, _ => choose_zero_succ _
  | n + 1, k + 1, hk => by
    have hnk : n < k := lt_of_succ_lt_succ hk
    

Proof state:
n k : ℕ
hk : n + 1 < k + 1
hnk : n < k
⊢ choose (n + 1) (k + 1) = 0

Next tactic:
have hnk1 : n < k + 1 := lt_of_succ_lt hk
theorem choose_eq_zero_of_lt : ∀ {n k}, n < k → choose n k = 0
  | _, 0, hk => absurd hk (Nat.not_lt_zero _)
  | 0, k + 1, _ => choose_zero_succ _
  | n + 1, k + 1, hk => by
    have hnk : n < k := lt_of_succ_lt_succ hk
    have hnk1 : n < k + 1 := lt_of_succ_lt hk
    

Proof state:
n k : ℕ
hk : n + 1 < k + 1
hnk : n < k
hnk1 : n < k + 1
⊢ choose (n + 1) (k + 1) = 0

Next tactic:
rw [choose_succ_succ, choose_eq_zero_of_lt hnk, choose_eq_zero_of_lt hnk1]
@[simp]
theorem choose_self (n : ℕ) : choose n n = 1 := by
  

Proof state:
n : ℕ
⊢ choose n n = 1

Next tactic:
induction n
@[simp]
theorem choose_self (n : ℕ) : choose n n = 1 := by
  induction n <;> 

Proof state:
case zero
⊢ choose zero zero = 1

Next tactic:
simp [*, choose, choose_eq_zero_of_lt (lt_succ_self _)]
@[simp]
theorem choose_self (n : ℕ) : choose n n = 1 := by
  induction n <;> 

Proof state:
case succ
n✝ : ℕ
n_ih✝ : choose n✝ n✝ = 1
⊢ choose (succ n✝) (succ n✝) = 1

Next tactic:
simp [*, choose, choose_eq_zero_of_lt (lt_succ_self _)]
@[simp]
theorem choose_one_right (n : ℕ) : choose n 1 = n := by 

Proof state:
n : ℕ
⊢ choose n 1 = n

Next tactic:
induction n
@[simp]
theorem choose_one_right (n : ℕ) : choose n 1 = n := by induction n <;> 

Proof state:
case zero
⊢ choose zero 1 = zero

Next tactic:
simp [*, choose, add_comm]
@[simp]
theorem choose_one_right (n : ℕ) : choose n 1 = n := by induction n <;> 

Proof state:
case succ
n✝ : ℕ
n_ih✝ : choose n✝ 1 = n✝
⊢ choose (succ n✝) 1 = succ n✝

Next tactic:
simp [*, choose, add_comm]
theorem triangle_succ (n : ℕ) : (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n := by
  

Proof state:
n : ℕ
⊢ (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n

Next tactic:
rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
theorem triangle_succ (n : ℕ) : (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n := by
  rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
  

Proof state:
n : ℕ
⊢ n * (n + 1) / 2 = n * (n - 1 + 2) / 2

Next tactic:
cases n
theorem triangle_succ (n : ℕ) : (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n := by
  rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
  cases n <;> 

Proof state:
case zero
⊢ zero * (zero + 1) / 2 = zero * (zero - 1 + 2) / 2

Next tactic:
rfl
theorem triangle_succ (n : ℕ) : (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n := by
  rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
  cases n <;> 

Proof state:
case succ
n✝ : ℕ
⊢ succ n✝ * (succ n✝ + 1) / 2 = succ n✝ * (succ n✝ - 1 + 2) / 2

Next tactic:
rfl
theorem triangle_succ (n : ℕ) : (n + 1) * (n + 1 - 1) / 2 = n * (n - 1) / 2 + n := by
  rw [← add_mul_div_left, mul_comm 2 n, ← mul_add, add_tsub_cancel_right, mul_comm]
  cases n <;> rfl; 

Proof state:
case H
n : ℕ
⊢ 0 < 2

Next tactic:
apply zero_lt_succ
/-- `choose n 2` is the `n`-th triangle number. -/
theorem choose_two_right (n : ℕ) : choose n 2 = n * (n - 1) / 2 := by
  

Proof state:
n : ℕ
⊢ choose n 2 = n * (n - 1) / 2

Next tactic:
induction' n with n ih
/-- `choose n 2` is the `n`-th triangle number. -/
theorem choose_two_right (n : ℕ) : choose n 2 = n * (n - 1) / 2 := by
  induction' n with n ih
  · 

Proof state:
case zero
⊢ choose zero 2 = zero * (zero - 1) / 2

Next tactic:
simp
/-- `choose n 2` is the `n`-th triangle number. -/
theorem choose_two_right (n : ℕ) : choose n 2 = n * (n - 1) / 2 := by
  induction' n with n ih
  · simp
  · 

Proof state:
case succ
n : ℕ
ih : choose n 2 = n * (n - 1) / 2
⊢ choose (succ n) 2 = succ n * (succ n - 1) / 2

Next tactic:
rw [triangle_succ n, choose, ih]
/-- `choose n 2` is the `n`-th triangle number. -/
theorem choose_two_right (n : ℕ) : choose n 2 = n * (n - 1) / 2 := by
  induction' n with n ih
  · simp
  · rw [triangle_succ n, choose, ih]
    

Proof state:
case succ
n : ℕ
ih : choose n 2 = n * (n - 1) / 2
⊢ choose n 1 + n * (n - 1) / 2 = n * (n - 1) / 2 + n

Next tactic:
simp [add_comm]
theorem choose_pos : ∀ {n k}, k ≤ n → 0 < choose n k
  | 0, _, hk => by 

Proof state:
x✝ : ℕ
hk : x✝ ≤ 0
⊢ 0 < choose 0 x✝

Next tactic:
rw [Nat.eq_zero_of_le_zero hk]
theorem choose_pos : ∀ {n k}, k ≤ n → 0 < choose n k
  | 0, _, hk => by rw [Nat.eq_zero_of_le_zero hk]; 

Proof state:
x✝ : ℕ
hk : x✝ ≤ 0
⊢ 0 < choose 0 0

Next tactic:
decide
theorem choose_pos : ∀ {n k}, k ≤ n → 0 < choose n k
  | 0, _, hk => by rw [Nat.eq_zero_of_le_zero hk]; decide
  | n + 1, 0, _ => by 

Proof state:
n : ℕ
x✝ : 0 ≤ n + 1
⊢ 0 < choose (n + 1) 0

Next tactic:
simp
theorem choose_pos : ∀ {n k}, k ≤ n → 0 < choose n k
  | 0, _, hk => by rw [Nat.eq_zero_of_le_zero hk]; decide
  | n + 1, 0, _ => by simp
  | n + 1, k + 1, hk => by
    

Proof state:
n k : ℕ
hk : k + 1 ≤ n + 1
⊢ 0 < choose (n + 1) (k + 1)

Next tactic:
rw [choose_succ_succ]
theorem choose_pos : ∀ {n k}, k ≤ n → 0 < choose n k
  | 0, _, hk => by rw [Nat.eq_zero_of_le_zero hk]; decide
  | n + 1, 0, _ => by simp
  | n + 1, k + 1, hk => by
    rw [choose_succ_succ]
    

Proof state:
n k : ℕ
hk : k + 1 ≤ n + 1
⊢ 0 < choose n k + choose n (succ k)

Next tactic:
exact add_pos_of_pos_of_nonneg (choose_pos (le_of_succ_le_succ hk)) (Nat.zero_le _)
theorem succ_mul_choose_eq : ∀ n k, succ n * choose n k = choose (succ n) (succ k) * succ k
  | 0, 0 => by 

Proof state:
⊢ succ 0 * choose 0 0 = choose (succ 0) (succ 0) * succ 0

Next tactic:
decide
theorem succ_mul_choose_eq : ∀ n k, succ n * choose n k = choose (succ n) (succ k) * succ k
  | 0, 0 => by decide
  | 0, k + 1 => by 

Proof state:
k : ℕ
⊢ succ 0 * choose 0 (k + 1) = choose (succ 0) (succ (k + 1)) * succ (k + 1)

Next tactic:
simp [choose]
theorem succ_mul_choose_eq : ∀ n k, succ n * choose n k = choose (succ n) (succ k) * succ k
  | 0, 0 => by decide
  | 0, k + 1 => by simp [choose]
  | n + 1, 0 => by 

Proof state:
n : ℕ
⊢ succ (n + 1) * choose (n + 1) 0 = choose (succ (n + 1)) (succ 0) * succ 0

Next tactic:
simp [choose, mul_succ, succ_eq_add_one, add_comm]
theorem succ_mul_choose_eq : ∀ n k, succ n * choose n k = choose (succ n) (succ k) * succ k
  | 0, 0 => by decide
  | 0, k + 1 => by simp [choose]
  | n + 1, 0 => by simp [choose, mul_succ, succ_eq_add_one, add_comm]
  | n + 1, k + 1 => by
    

Proof state:
n k : ℕ
⊢ succ (n + 1) * choose (n + 1) (k + 1) = choose (succ (n + 1)) (succ (k + 1)) * succ (k + 1)

Next tactic:
rw [choose_succ_succ (succ n) (succ k), add_mul, ← succ_mul_choose_eq n, mul_succ, ←
      succ_mul_choose_eq n, add_right_comm, ← mul_add, ← choose_succ_succ, ← succ_mul]
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by 

Proof state:
x✝ : ℕ
hk : x✝ ≤ 0
⊢ choose 0 x✝ * x✝! * (0 - x✝)! = 0!

Next tactic:
simp [Nat.eq_zero_of_le_zero hk]
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by simp [Nat.eq_zero_of_le_zero hk]
  | n + 1, 0, _ => by 

Proof state:
n : ℕ
x✝ : 0 ≤ n + 1
⊢ choose (n + 1) 0 * 0! * (n + 1 - 0)! = (n + 1)!

Next tactic:
simp
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by simp [Nat.eq_zero_of_le_zero hk]
  | n + 1, 0, _ => by simp
  | n + 1, succ k, hk => by
    

Proof state:
n k : ℕ
hk : succ k ≤ n + 1
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!

Next tactic:
rcases lt_or_eq_of_le hk with hk₁ | hk₁
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by simp [Nat.eq_zero_of_le_zero hk]
  | n + 1, 0, _ => by simp
  | n + 1, succ k, hk => by
    rcases lt_or_eq_of_le hk with hk₁ | hk₁
    · 

Proof state:
case inl
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose (n + 1) (succ k) * (succ k)! * (n + 1 - succ k)! = (n + 1)!

Next tactic:
have h : choose n k * k.succ ! * (n - k)! = (k + 1) * n ! := by
        rw [← choose_mul_factorial_mul_factorial (le_of_succ_le_succ hk)]
        simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by simp [Nat.eq_zero_of_le_zero hk]
  | n + 1, 0, _ => by simp
  | n + 1, succ k, hk => by
    rcases lt_or_eq_of_le hk with hk₁ | hk₁
    · have h : choose n k * k.succ ! * (n - k)! = (k + 1) * n ! := by
        

Proof state:
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose n k * (succ k)! * (n - k)! = (k + 1) * n !

Next tactic:
rw [← choose_mul_factorial_mul_factorial (le_of_succ_le_succ hk)]
theorem choose_mul_factorial_mul_factorial : ∀ {n k}, k ≤ n → choose n k * k ! * (n - k)! = n !
  | 0, _, hk => by simp [Nat.eq_zero_of_le_zero hk]
  | n + 1, 0, _ => by simp
  | n + 1, succ k, hk => by
    rcases lt_or_eq_of_le hk with hk₁ | hk₁
    · have h : choose n k * k.succ ! * (n - k)! = (k + 1) * n ! := by
        rw [← choose_mul_factorial_mul_factorial (le_of_succ_le_succ hk)]
        

Proof state:
n k : ℕ
hk : succ k ≤ n + 1
hk₁ : succ k < n + 1
⊢ choose n k * (succ k)! * (n - k)! = (k + 1) * (choose n k * k ! * (n - k)!)

Next tactic:
simp [factorial_succ, mul_comm, mul_left_comm, mul_assoc]