{-# OPTIONS --cubical --safe #-}
module Data.Nat.Properties where
open import Data.Nat.Base
open import Agda.Builtin.Nat using () renaming (_<_ to _<ᴮ_) public
open import Prelude
open import Cubical.Data.Nat using (caseNat; injSuc) public
open import Data.Nat.DivMod
infixr 4 _⊔_ _-1⊔_
_⊔_ _-1⊔_ : ℕ → ℕ → ℕ
zero ⊔ m = m
suc n ⊔ m = suc (m -1⊔ n)
zero -1⊔ n = n
suc m -1⊔ n = n ⊔ m
znots : ∀ {n} → zero ≢ suc n
znots z≡s = subst (caseNat ⊤ ⊥) z≡s tt
snotz : ∀ {n} → suc n ≢ zero
snotz s≡z = subst (caseNat ⊥ ⊤) s≡z tt
pred : ℕ → ℕ
pred (suc n) = n
pred zero = zero
suc-inj : ∀ {n m} → suc n ≡ suc m → n ≡ m
suc-inj = cong pred
+-inj : ∀ x {n m} → x + n ≡ x + m → n ≡ m
+-inj zero p = p
+-inj (suc x) p = +-inj x (suc-inj p)
open import Relation.Nullary.Discrete.FromBoolean
module Eqℕ where
open import Agda.Builtin.Nat using () renaming (_==_ to _≡ᴮ_) public
sound : ∀ n m → T (n ≡ᴮ m) → n ≡ m
sound zero zero p i = zero
sound (suc n) (suc m) p i = suc (sound n m p i)
complete : ∀ n → T (n ≡ᴮ n)
complete zero = tt
complete (suc n) = complete n
discreteℕ : Discrete ℕ
discreteℕ = from-bool-eq (record { Eqℕ })
isSetℕ : isSet ℕ
isSetℕ = Discrete→isSet discreteℕ
+-suc : ∀ x y → x + suc y ≡ suc (x + y)
+-suc zero y = refl
+-suc (suc x) y = cong suc (+-suc x y)
+-idʳ : ∀ x → x + 0 ≡ x
+-idʳ zero = refl
+-idʳ (suc x) = cong suc (+-idʳ x)
+-comm : ∀ x y → x + y ≡ y + x
+-comm x zero = +-idʳ x
+-comm x (suc y) = +-suc x y ; cong suc (+-comm x y)
infix 4 _<_
_<_ : ℕ → ℕ → Type
n < m = T (n <ᴮ m)
infix 4 _≤ᴮ_
_≤ᴮ_ : ℕ → ℕ → Bool
n ≤ᴮ m = not (m <ᴮ n)
infix 4 _≤_
_≤_ : ℕ → ℕ → Type
n ≤ m = T (n ≤ᴮ m)
infix 4 _≥ᴮ_
_≥ᴮ_ : ℕ → ℕ → Bool
_≥ᴮ_ = flip _≤ᴮ_
+-assoc : ∀ x y z → (x + y) + z ≡ x + (y + z)
+-assoc zero y z i = y + z
+-assoc (suc x) y z i = suc (+-assoc x y z i)
+-*-distrib : ∀ x y z → (x + y) * z ≡ x * z + y * z
+-*-distrib zero y z = refl
+-*-distrib (suc x) y z = cong (z +_) (+-*-distrib x y z) ; sym (+-assoc z (x * z) (y * z))
*-zeroʳ : ∀ x → x * zero ≡ zero
*-zeroʳ zero = refl
*-zeroʳ (suc x) = *-zeroʳ x
*-suc : ∀ x y → x + x * y ≡ x * suc y
*-suc zero y = refl
*-suc (suc x) y = cong suc (sym (+-assoc x y (x * y)) ; cong (_+ x * y) (+-comm x y) ; +-assoc y x (x * y) ; cong (y +_) (*-suc x y))
*-comm : ∀ x y → x * y ≡ y * x
*-comm zero y = sym (*-zeroʳ y)
*-comm (suc x) y = cong (y +_) (*-comm x y) ; *-suc y x
*-assoc : ∀ x y z → (x * y) * z ≡ x * (y * z)
*-assoc zero y z = refl
*-assoc (suc x) y z = +-*-distrib y (x * y) z ; cong (y * z +_) (*-assoc x y z)
open import Data.Nat.DivMod
open import Agda.Builtin.Nat using (div-helper)
div-helper′ : (m n j : ℕ) → ℕ
div-helper′ m zero j = zero
div-helper′ m (suc n) zero = suc (div-helper′ m n m)
div-helper′ m (suc n) (suc j) = div-helper′ m n j
div-helper-lemma : ∀ k m n j → div-helper k m n j ≡ k + div-helper′ m n j
div-helper-lemma k m zero j = sym (+-idʳ k)
div-helper-lemma k m (suc n) zero = div-helper-lemma (suc k) m n m ; sym (+-suc k (div-helper′ m n m))
div-helper-lemma k m (suc n) (suc j) = div-helper-lemma k m n j
Even : ℕ → Type
Even n = T (even n)
open Eqℕ using (_≡ᴮ_)
odd : ℕ → Bool
odd n = not (rem n 2 ≡ᴮ 0)
Odd : ℕ → Type
Odd n = T (odd n)
s≤s : ∀ n m → n ≤ m → suc n ≤ suc m
s≤s zero m p = tt
s≤s (suc n) m p = p
n≤s : ∀ n m → n ≤ m → n ≤ suc m
n≤s zero m p = tt
n≤s (suc zero) m p = tt
n≤s (suc (suc n)) zero p = p
n≤s (suc (suc n₁)) (suc n) p = n≤s (suc n₁) n p
div-≤ : ∀ n m → n ÷ suc m ≤ n
div-≤ n m = subst (_≤ n) (sym (div-helper-lemma 0 m n m)) (go m n m)
where
go : ∀ m n j → div-helper′ m n j ≤ n
go m zero j = tt
go m (suc n) zero = s≤s (div-helper′ m n m) n (go m n m)
go m (suc n) (suc j) = n≤s (div-helper′ m n j) n (go m n j)
≤-trans : ∀ x y z → x ≤ y → y ≤ z → x ≤ z
≤-trans zero y z p q = tt
≤-trans (suc n) zero zero p q = p
≤-trans (suc zero) zero (suc n) p q = tt
≤-trans (suc (suc n₁)) zero (suc n) p q = ≤-trans (suc n₁) zero n p tt
≤-trans (suc n) (suc zero) zero p q = q
≤-trans (suc zero) (suc zero) (suc n) p q = tt
≤-trans (suc (suc n₁)) (suc zero) (suc n) p q = ≤-trans (suc n₁) zero n p tt
≤-trans (suc n₁) (suc (suc n)) zero p q = q
≤-trans (suc zero) (suc (suc n₁)) (suc n) p q = tt
≤-trans (suc (suc n₁)) (suc (suc n₂)) (suc n) p q = ≤-trans (suc n₁) (suc n₂) n p q
p≤n : ∀ n m → suc n ≤ m → n ≤ m
p≤n zero m p = tt
p≤n (suc n) zero p = p
p≤n (suc zero) (suc n) p = tt
p≤n (suc (suc n₁)) (suc n) p = p≤n (suc n₁) n p
p≤p : ∀ n m → suc n ≤ suc m → n ≤ m
p≤p zero m p = tt
p≤p (suc n) m p = p
≤-refl : ∀ n → n ≤ n
≤-refl zero = tt
≤-refl (suc zero) = tt
≤-refl (suc (suc n)) = ≤-refl (suc n)
linearise : ∀ n m → n ≡ m → n ≡ m
linearise n m n≡m with discreteℕ n m
... | yes p = p
... | no ¬p = ⊥-elim (¬p n≡m)
x≢sx+y : ∀ x y → x ≢ suc x + y
x≢sx+y zero y = znots
x≢sx+y (suc x) y p = x≢sx+y x y (suc-inj p)