l3lab/ntp-mathlib huggingface dataset:
theorem sSup_le {A : C} (s : Set (Subobject A)) (f : Subobject A) (k : ∀ g ∈ s, g ≤ f) :
    sSup s ≤ f := by
  fapply le_of_comm
  · refine'(underlyingIso _).hom ≫ image.lift ⟨_, f.arrow, _, _⟩
    · refine' Sigma.desc _
      rintro ⟨g, m⟩
      refine' underlying.map (homOfLE (k _ _))
      simpa using m
    · ext
      dsimp [smallCoproductDesc]
      simp
  · dsimp [sSup]
    

Proof state:
case w
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
X Y Z : C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
inst✝² : WellPowered C
inst✝¹ : HasCoproducts C
inst✝ : HasImages C
A : C
s : Set (Subobject A)
f : Subobject A
k : ∀ g ∈ s, g ≤ f
⊢ ((underlyingIso (image.ι (smallCoproductDesc s))).hom ≫
        image.lift
          (MonoFactorisation.mk (underlying.obj f) (arrow f)
            (Sigma.desc fun b => underlying.map (homOfLE (_ : (equivShrink (Subobject A)).symm ↑b ≤ f))))) ≫
      arrow f =
    arrow (mk (image.ι (smallCoproductDesc s)))

Next tactic:
rw [assoc, image.lift_fac, underlyingIso_hom_comp_eq_mk]
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
Z : Subobject (underlying.obj Y)
⊢ ((underlyingIso (arrow Z ≫ arrow Y)).hom ≫ arrow Z) ≫ arrow Y = arrow (mk (arrow Z ≫ arrow Y))

Next tactic:
simp
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
Z : Subobject (underlying.obj Y)
⊢ (underlyingIso (arrow Z ≫ arrow Y)).hom ≫ arrow Z =
    ofLE (↑((fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }) Z)) Y
      (_ :
        ↑((fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }) Z) ∈
          Set.Iic Y)

Next tactic:
aesop_cat
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
Z : ↑(Set.Iic Y)
⊢ (underlyingIso (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))).hom ≫ arrow ↑Z =
    arrow ((fun Z => mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))) Z) ≫ arrow Y

Next tactic:
dsimp
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
Z : ↑(Set.Iic Y)
⊢ (underlyingIso (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))).hom ≫ arrow ↑Z =
    arrow (mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))) ≫ arrow Y

Next tactic:
simp [← Iso.eq_inv_comp]
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
⊢ { toFun := fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) },
          invFun := fun Z => mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y)),
          left_inv :=
            (_ :
              ∀ (Z : Subobject (underlying.obj Y)),
                mk
                    (ofLE
                      (↑((fun Z =>
                            { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                          Z))
                      Y
                      (_ :
                        ↑((fun Z =>
                                { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                              Z) ∈
                          Set.Iic Y)) =
                  Z),
          right_inv :=
            (_ :
              ∀ (Z : ↑(Set.Iic Y)),
                (fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                    ((fun Z => mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))) Z) =
                  Z) }
        W ≤
      { toFun := fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) },
          invFun := fun Z => mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y)),
          left_inv :=
            (_ :
              ∀ (Z : Subobject (underlying.obj Y)),
                mk
                    (ofLE
                      (↑((fun Z =>
                            { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                          Z))
                      Y
                      (_ :
                        ↑((fun Z =>
                                { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                              Z) ∈
                          Set.Iic Y)) =
                  Z),
          right_inv :=
            (_ :
              ∀ (Z : ↑(Set.Iic Y)),
                (fun Z => { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) })
                    ((fun Z => mk (ofLE (↑Z) Y (_ : ↑Z ∈ Set.Iic Y))) Z) =
                  Z) }
        Z ↔
    W ≤ Z

Next tactic:
dsimp
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
⊢ { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
      { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) } ↔
    W ≤ Z

Next tactic:
constructor
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · 

Proof state:
case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
⊢ { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
      { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) } →
    W ≤ Z

Next tactic:
intro h
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · intro h
      

Proof state:
case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
h :
  { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
    { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }
⊢ W ≤ Z

Next tactic:
exact le_of_comm (((underlyingIso _).inv ≫ ofLE _ _ (Subtype.mk_le_mk.mp h) ≫
        (underlyingIso _).hom)) (by aesop_cat)
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · intro h
      exact le_of_comm (((underlyingIso _).inv ≫ ofLE _ _ (Subtype.mk_le_mk.mp h) ≫
        (underlyingIso _).hom)) (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
h :
  { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
    { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }
⊢ ((underlyingIso (arrow W ≫ arrow Y)).inv ≫
        ofLE (mk (arrow W ≫ arrow Y)) (mk (arrow Z ≫ arrow Y)) (_ : mk (arrow W ≫ arrow Y) ≤ mk (arrow Z ≫ arrow Y)) ≫
          (underlyingIso (arrow Z ≫ arrow Y)).hom) ≫
      arrow Z =
    arrow W

Next tactic:
aesop_cat
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · intro h
      exact le_of_comm (((underlyingIso _).inv ≫ ofLE _ _ (Subtype.mk_le_mk.mp h) ≫
        (underlyingIso _).hom)) (by aesop_cat)
    · 

Proof state:
case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
⊢ W ≤ Z →
    { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
      { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }

Next tactic:
intro h
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · intro h
      exact le_of_comm (((underlyingIso _).inv ≫ ofLE _ _ (Subtype.mk_le_mk.mp h) ≫
        (underlyingIso _).hom)) (by aesop_cat)
    · intro h
      

Proof state:
case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
h : W ≤ Z
⊢ { val := mk (arrow W ≫ arrow Y), property := (_ : mk (arrow W ≫ arrow Y) ∈ Set.Iic Y) } ≤
    { val := mk (arrow Z ≫ arrow Y), property := (_ : mk (arrow Z ≫ arrow Y) ∈ Set.Iic Y) }

Next tactic:
exact Subtype.mk_le_mk.mpr (le_of_comm
        ((underlyingIso _).hom ≫ ofLE _ _ h ≫ (underlyingIso _).inv) (by simp))
/-- The subobject lattice of a subobject `Y` is order isomorphic to the interval `Set.Iic Y`. -/
def subobjectOrderIso {X : C} (Y : Subobject X) : Subobject (Y : C) ≃o Set.Iic Y where
  toFun Z :=
    ⟨Subobject.mk (Z.arrow ≫ Y.arrow),
      Set.mem_Iic.mpr (le_of_comm ((underlyingIso _).hom ≫ Z.arrow) (by simp))⟩
  invFun Z := Subobject.mk (ofLE _ _ Z.2)
  left_inv Z := mk_eq_of_comm _ (underlyingIso _) (by aesop_cat)
  right_inv Z := Subtype.ext (mk_eq_of_comm _ (underlyingIso _) (by
          dsimp
          simp [← Iso.eq_inv_comp]))
  map_rel_iff' {W Z} := by
    dsimp
    constructor
    · intro h
      exact le_of_comm (((underlyingIso _).inv ≫ ofLE _ _ (Subtype.mk_le_mk.mp h) ≫
        (underlyingIso _).hom)) (by aesop_cat)
    · intro h
      exact Subtype.mk_le_mk.mpr (le_of_comm
        ((underlyingIso _).hom ≫ ofLE _ _ h ≫ (underlyingIso _).inv) (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
X : C
Y : Subobject X
W Z : Subobject (underlying.obj Y)
h : W ≤ Z
⊢ ((underlyingIso (arrow W ≫ arrow Y)).hom ≫ ofLE W Z h ≫ (underlyingIso (arrow Z ≫ arrow Y)).inv) ≫
      arrow (mk (arrow Z ≫ arrow Y)) =
    arrow (mk (arrow W ≫ arrow Y))

Next tactic:
simp
/-- (Impl.) An auxiliary definition for `digits`, to help get the desired definitional unfolding. -/
def digitsAux (b : ℕ) (h : 2 ≤ b) : ℕ → List ℕ
  | 0 => []
  | n + 1 =>
    ((n + 1) % b) :: digitsAux b h ((n + 1) / b)
decreasing_by 

Proof state:
b : ℕ
h : 2 ≤ b
n : ℕ
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 ((n + 1) / b) (succ n)

Next tactic:
exact Nat.div_lt_self (Nat.succ_pos _) h
@[simp]
theorem digitsAux_zero (b : ℕ) (h : 2 ≤ b) : digitsAux b h 0 = [] := by 

Proof state:
n b : ℕ
h : 2 ≤ b
⊢ digitsAux b h 0 = []

Next tactic:
rw [digitsAux]
theorem digitsAux_def (b : ℕ) (h : 2 ≤ b) (n : ℕ) (w : 0 < n) :
    digitsAux b h n = (n % b) :: digitsAux b h (n / b) := by
  

Proof state:
n✝ b : ℕ
h : 2 ≤ b
n : ℕ
w : 0 < n
⊢ digitsAux b h n = n % b :: digitsAux b h (n / b)

Next tactic:
cases n
theorem digitsAux_def (b : ℕ) (h : 2 ≤ b) (n : ℕ) (w : 0 < n) :
    digitsAux b h n = (n % b) :: digitsAux b h (n / b) := by
  cases n
  · 

Proof state:
case zero
n b : ℕ
h : 2 ≤ b
w : 0 < zero
⊢ digitsAux b h zero = zero % b :: digitsAux b h (zero / b)

Next tactic:
cases w
theorem digitsAux_def (b : ℕ) (h : 2 ≤ b) (n : ℕ) (w : 0 < n) :
    digitsAux b h n = (n % b) :: digitsAux b h (n / b) := by
  cases n
  · cases w
  · 

Proof state:
case succ
n b : ℕ
h : 2 ≤ b
n✝ : ℕ
w : 0 < succ n✝
⊢ digitsAux b h (succ n✝) = succ n✝ % b :: digitsAux b h (succ n✝ / b)

Next tactic:
rw [digitsAux]
/-- `digits b n` gives the digits, in little-endian order,
of a natural number `n` in a specified base `b`.

In any base, we have `ofDigits b L = L.foldr (fun x y ↦ x + b * y) 0`.
* For any `2 ≤ b`, we have `l < b` for any `l ∈ digits b n`,
  and the last digit is not zero.
  This uniquely specifies the behaviour of `digits b`.
* For `b = 1`, we define `digits 1 n = List.replicate n 1`.
* For `b = 0`, we define `digits 0 n = [n]`, except `digits 0 0 = []`.

Note this differs from the existing `Nat.to_digits` in core, which is used for printing numerals.
In particular, `Nat.to_digits b 0 = [0]`, while `digits b 0 = []`.
-/
def digits : ℕ → ℕ → List ℕ
  | 0 => digitsAux0
  | 1 => digitsAux1
  | b + 2 => digitsAux (b + 2) (by 

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

Next tactic:
norm_num
@[simp]
theorem digits_zero (b : ℕ) : digits b 0 = [] := by
  

Proof state:
n b : ℕ
⊢ digits b 0 = []

Next tactic:
rcases b with (_ | ⟨_ | ⟨_⟩⟩)
@[simp]
theorem digits_zero (b : ℕ) : digits b 0 = [] := by
  rcases b with (_ | ⟨_ | ⟨_⟩⟩) <;> 

Proof state:
case zero
n : ℕ
⊢ digits zero 0 = []

Next tactic:
simp [digits, digitsAux0, digitsAux1]
@[simp]
theorem digits_zero (b : ℕ) : digits b 0 = [] := by
  rcases b with (_ | ⟨_ | ⟨_⟩⟩) <;> 

Proof state:
case succ.zero
n : ℕ
⊢ digits (succ zero) 0 = []

Next tactic:
simp [digits, digitsAux0, digitsAux1]
@[simp]
theorem digits_zero (b : ℕ) : digits b 0 = [] := by
  rcases b with (_ | ⟨_ | ⟨_⟩⟩) <;> 

Proof state:
case succ.succ
n n✝ : ℕ
⊢ digits (succ (succ n✝)) 0 = []

Next tactic:
simp [digits, digitsAux0, digitsAux1]
theorem digits_add_two_add_one (b n : ℕ) :
    digits (b + 2) (n + 1) = ((n + 1) % (b + 2)) :: digits (b + 2) ((n + 1) / (b + 2)) := by
  

Proof state:
n✝ b n : ℕ
⊢ digits (b + 2) (n + 1) = (n + 1) % (b + 2) :: digits (b + 2) ((n + 1) / (b + 2))

Next tactic:
simp [digits, digitsAux_def]
@[simp]
lemma digits_of_two_le_of_pos {b : ℕ} (hb : 2 ≤ b) (hn : 0 < n) :
    Nat.digits b n = n % b :: Nat.digits b (n / b) := by
  

Proof state:
n b : ℕ
hb : 2 ≤ b
hn : 0 < n
⊢ digits b n = n % b :: digits b (n / b)

Next tactic:
rw [Nat.eq_add_of_sub_eq hb rfl, Nat.eq_add_of_sub_eq hn rfl, Nat.digits_add_two_add_one]
theorem digits_def' :
    ∀ {b : ℕ} (_ : 1 < b) {n : ℕ} (_ : 0 < n), digits b n = (n % b) :: digits b (n / b)
  | 0, h => absurd h (by 

Proof state:
n n✝ : ℕ
h : 1 < 0
⊢ ¬1 < 0

Next tactic:
decide
theorem digits_def' :
    ∀ {b : ℕ} (_ : 1 < b) {n : ℕ} (_ : 0 < n), digits b n = (n % b) :: digits b (n / b)
  | 0, h => absurd h (by decide)
  | 1, h => absurd h (by 

Proof state:
n n✝ : ℕ
h : 1 < 1
⊢ ¬1 < 1

Next tactic:
decide
theorem digits_def' :
    ∀ {b : ℕ} (_ : 1 < b) {n : ℕ} (_ : 0 < n), digits b n = (n % b) :: digits b (n / b)
  | 0, h => absurd h (by decide)
  | 1, h => absurd h (by decide)
  | b + 2, _ => digitsAux_def _ (by 

Proof state:
n n✝ b : ℕ
x✝ : 1 < b + 2
⊢ 2 ≤ Nat.add b 0 + 2

Next tactic:
simp
@[simp]
theorem digits_of_lt (b x : ℕ) (hx : x ≠ 0) (hxb : x < b) : digits b x = [x] := by
  

Proof state:
n b x : ℕ
hx : x ≠ 0
hxb : x < b
⊢ digits b x = [x]

Next tactic:
rcases exists_eq_succ_of_ne_zero hx with ⟨x, rfl⟩
@[simp]
theorem digits_of_lt (b x : ℕ) (hx : x ≠ 0) (hxb : x < b) : digits b x = [x] := by
  rcases exists_eq_succ_of_ne_zero hx with ⟨x, rfl⟩
  

Proof state:
case intro
n b x : ℕ
hx : succ x ≠ 0
hxb : succ x < b
⊢ digits b (succ x) = [succ x]

Next tactic:
rcases exists_eq_add_of_le' ((Nat.le_add_left 1 x).trans_lt hxb) with ⟨b, rfl⟩
@[simp]
theorem digits_of_lt (b x : ℕ) (hx : x ≠ 0) (hxb : x < b) : digits b x = [x] := by
  rcases exists_eq_succ_of_ne_zero hx with ⟨x, rfl⟩
  rcases exists_eq_add_of_le' ((Nat.le_add_left 1 x).trans_lt hxb) with ⟨b, rfl⟩
  

Proof state:
case intro.intro
n x : ℕ
hx : succ x ≠ 0
b : ℕ
hxb : succ x < b + succ 1
⊢ digits (b + succ 1) (succ x) = [succ x]

Next tactic:
rw [digits_add_two_add_one, div_eq_of_lt hxb, digits_zero, mod_eq_of_lt hxb]
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  

Proof state:
n b : ℕ
h : 1 < b
x y : ℕ
hxb : x < b
hxy : x ≠ 0 ∨ y ≠ 0
⊢ digits b (x + b * y) = x :: digits b y

Next tactic:
rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  

Proof state:
case intro
n x y : ℕ
hxy : x ≠ 0 ∨ y ≠ 0
b : ℕ
h : 1 < b + 2
hxb : x < b + 2
⊢ digits (b + 2) (x + (b + 2) * y) = x :: digits (b + 2) y

Next tactic:
cases y
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · 

Proof state:
case intro.zero
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
hxy : x ≠ 0 ∨ zero ≠ 0
⊢ digits (b + 2) (x + (b + 2) * zero) = x :: digits (b + 2) zero

Next tactic:
simp [hxb, hxy.resolve_right (absurd rfl)]
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · simp [hxb, hxy.resolve_right (absurd rfl)]
  

Proof state:
case intro.succ
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
n✝ : ℕ
hxy : x ≠ 0 ∨ succ n✝ ≠ 0
⊢ digits (b + 2) (x + (b + 2) * succ n✝) = x :: digits (b + 2) (succ n✝)

Next tactic:
dsimp [digits]
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · simp [hxb, hxy.resolve_right (absurd rfl)]
  dsimp [digits]
  

Proof state:
case intro.succ
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
n✝ : ℕ
hxy : x ≠ 0 ∨ succ n✝ ≠ 0
⊢ digitsAux (b + 2) (_ : 2 ≤ b + 2) (x + (b + 2) * succ n✝) = x :: digitsAux (b + 2) (_ : 2 ≤ b + 2) (succ n✝)

Next tactic:
rw [digitsAux_def]
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · simp [hxb, hxy.resolve_right (absurd rfl)]
  dsimp [digits]
  rw [digitsAux_def]
  · 

Proof state:
case intro.succ
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
n✝ : ℕ
hxy : x ≠ 0 ∨ succ n✝ ≠ 0
⊢ (x + (b + 2) * succ n✝) % (b + 2) :: digitsAux (b + 2) (_ : 2 ≤ b + 2) ((x + (b + 2) * succ n✝) / (b + 2)) =
    x :: digitsAux (b + 2) (_ : 2 ≤ b + 2) (succ n✝)

Next tactic:
congr
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · simp [hxb, hxy.resolve_right (absurd rfl)]
  dsimp [digits]
  rw [digitsAux_def]
  · congr
    · 

Proof state:
case intro.succ.e_head
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
n✝ : ℕ
hxy : x ≠ 0 ∨ succ n✝ ≠ 0
⊢ (x + (b + 2) * succ n✝) % (b + 2) = x

Next tactic:
simp [Nat.add_mod, mod_eq_of_lt hxb]
theorem digits_add (b : ℕ) (h : 1 < b) (x y : ℕ) (hxb : x < b) (hxy : x ≠ 0 ∨ y ≠ 0) :
    digits b (x + b * y) = x :: digits b y := by
  rcases exists_eq_add_of_le' h with ⟨b, rfl : _ = _ + 2⟩
  cases y
  · simp [hxb, hxy.resolve_right (absurd rfl)]
  dsimp [digits]
  rw [digitsAux_def]
  · congr
    · simp [Nat.add_mod, mod_eq_of_lt hxb]
    · 

Proof state:
case intro.succ.e_tail.e_a
n x b : ℕ
h : 1 < b + 2
hxb : x < b + 2
n✝ : ℕ
hxy : x ≠ 0 ∨ succ n✝ ≠ 0
⊢ (x + (b + 2) * succ n✝) / (b + 2) = succ n✝

Next tactic:
simp [add_mul_div_left, div_eq_of_lt hxb]