{-# OPTIONS --cubical-compatible --safe #-} module nat where open import Data.Nat open import Data.Nat.Properties open import Data.Empty open import Relation.Nullary open import Relation.Binary.PropositionalEquality open import Relation.Binary.Core open import Relation.Binary.Definitions open import logic open import Level hiding ( zero ; suc ) =→¬< : {x : ℕ } → ¬ ( x < x ) =→¬< {x} x ¬a ¬b c = ⊥-elim ( ¬b refl ) >→¬< : {x y : ℕ } → (x < y ) → ¬ ( y < x ) >→¬< {x} {y} x ¬a ¬b c = ⊥-elim ( ¬a x : { x y : ℕ } → x < y → y < x → ⊥ nat-<> {x} {y} x ¬a ¬b c = ⊥-elim ( ¬a x ¬a ¬b c = ⊥-elim ( ¬a x : { x y : ℕ } → x ≤ y → y < x → ⊥ nat-≤> {x} {y} x≤y y ¬a ¬b c = ⊥-elim (nat-<≡ (≤-trans c x≤y)) ≤-∨ : { x y : ℕ } → x ≤ y → ( (x ≡ y ) ∨ (x < y) ) ≤-∨ {x} {y} x≤y with <-cmp x y ... | tri< a ¬b ¬c = case2 a ... | tri≈ ¬a b ¬c = case1 b ... | tri> ¬a ¬b c = ⊥-elim ( nat-<≡ (≤-trans c x≤y)) <-∨ : { x y : ℕ } → x < suc y → ( (x ≡ y ) ∨ (x < y) ) <-∨ {x} {y} x ¬a ¬b c = ⊥-elim ( nat-<≡ (≤-trans x sx≤x a ¬a ¬b c = ⊥-elim ( nat-≤> c lt ) y≤x→max=x : (x y : ℕ) → y ≤ x → max x y ≡ x y≤x→max=x zero zero y≤x = refl y≤x→max=x zero (suc y) () y≤x→max=x (suc x) zero lt = refl y≤x→max=x (suc x) (suc y) lt with <-cmp y x ... | tri< a ¬b ¬c = cong suc (y≤x→max=x x y (≤-trans a≤sa a)) ... | tri≈ ¬a refl ¬c = cong suc (y≤x→max=x x y ≤-refl ) ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> c lt ) -- _*_ : ℕ → ℕ → ℕ -- _*_ zero _ = zero -- _*_ (suc n) m = m + ( n * m ) -- x ^ y exp : ℕ → ℕ → ℕ exp _ zero = 1 exp n (suc m) = n * ( exp n m ) div2 : ℕ → (ℕ ∧ Bool ) div2 zero = ⟪ 0 , false ⟫ div2 (suc zero) = ⟪ 0 , true ⟫ div2 (suc (suc n)) = ⟪ suc (proj1 (div2 n)) , proj2 (div2 n) ⟫ where open _∧_ div2-rev : (ℕ ∧ Bool ) → ℕ div2-rev ⟪ x , true ⟫ = suc (x + x) div2-rev ⟪ x , false ⟫ = x + x div2-eq : (x : ℕ ) → div2-rev ( div2 x ) ≡ x div2-eq zero = refl div2-eq (suc zero) = refl div2-eq (suc (suc x)) with div2 x in eq1 ... | ⟪ x1 , true ⟫ = begin -- eq1 : div2 x ≡ ⟪ x1 , true ⟫ div2-rev ⟪ suc x1 , true ⟫ ≡⟨⟩ suc (suc (x1 + suc x1)) ≡⟨ cong (λ k → suc (suc k )) (+-comm x1 _ ) ⟩ suc (suc (suc (x1 + x1))) ≡⟨⟩ suc (suc (div2-rev ⟪ x1 , true ⟫)) ≡⟨ cong (λ k → suc (suc (div2-rev k ))) (sym eq1) ⟩ suc (suc (div2-rev (div2 x))) ≡⟨ cong (λ k → suc (suc k)) (div2-eq x) ⟩ suc (suc x) ∎ where open ≡-Reasoning ... | ⟪ x1 , false ⟫ = begin div2-rev ⟪ suc x1 , false ⟫ ≡⟨⟩ suc (x1 + suc x1) ≡⟨ cong (λ k → (suc k )) (+-comm x1 _ ) ⟩ suc (suc (x1 + x1)) ≡⟨⟩ suc (suc (div2-rev ⟪ x1 , false ⟫)) ≡⟨ cong (λ k → suc (suc (div2-rev k ))) (sym eq1) ⟩ suc (suc (div2-rev (div2 x))) ≡⟨ cong (λ k → suc (suc k)) (div2-eq x) ⟩ suc (suc x) ∎ where open ≡-Reasoning sucprd : {i : ℕ } → 0 < i → suc (pred i) ≡ i sucprd {suc i} 0 ¬a ¬b c = ⊥-elim ( nat-<> c lt ) minus : (a b : ℕ ) → ℕ minus a zero = a minus zero (suc b) = zero minus (suc a) (suc b) = minus a b _-_ = minus sn-m=sn-m : {m n : ℕ } → m ≤ n → suc n - m ≡ suc ( n - m ) sn-m=sn-m {0} {n} m≤n = refl sn-m=sn-m {suc m} {suc n} le with <-cmp m n ... | tri< a ¬b ¬c = sm00 where sm00 : suc n - m ≡ suc ( n - m ) sm00 = sn-m=sn-m {m} {n} (≤-trans a≤sa a ) ... | tri≈ ¬a refl ¬c = sn-m=sn-m {m} {n} ≤-refl ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> c le ) si-sn=i-n : {i n : ℕ } → n < i → suc (i - suc n) ≡ (i - n) si-sn=i-n {i} {n} n ¬a ¬b c = ⊥-elim ( nat-≤> c x≤y ) n-n-m=m : {m n : ℕ } → m ≤ n → m ≡ (n - (n - m)) n-n-m=m {0} {zero} le = refl n-n-m=m {0} {suc n} lt = begin 0 ≡⟨ sym (m-m=0 {suc n}) ⟩ suc n - suc n ∎ where open ≡-Reasoning n-n-m=m {suc m} {suc n} le = begin suc m ≡⟨ cong suc ( n-n-m=m (px≤py le)) ⟩ suc (n - (n - m)) ≡⟨ sym (sn-m=sn-m (n-m y → minus x y + y ≡ x minus+n {x} {zero} _ = trans (sym (+-comm zero _ )) refl minus+n {zero} {suc y} lt = ⊥-elim ( nat-≤> lt (≤-trans a ¬a ¬b c = ⊥-elim ( nat-<> c (px≤py y ¬a ¬b c = ⊥-elim ( nat-<> x ¬a ¬b c = ⊥-elim ( nat-<> c (≤-trans x ¬a ¬b c = ⊥-elim ( nat-≤> c x ¬a ¬b c = case2 ( ¬a ¬b c = ⊥-elim ( ¬a ( ≤-trans x j≤i a ) ... | tri≈ ¬a b ¬c = b ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> i≤j c ) sx≤py→x≤y : {x y : ℕ } → suc x ≤ suc y → x ≤ y sx≤py→x≤y = px≤py sx ¬a ¬b c = ⊥-elim ( nat-<> (s≤s c) sx0 : {x y : ℕ } → x < y → 0 < minus y x minus>0 {zero} {suc _} lt = lt minus>0 {suc x} {suc y} lt = minus>0 {x} {y} (sx0→x0→x ¬a ¬b c = ⊥-elim ( nat-≡< (sym (minus<=0 {y} (≤-trans refl-≤s c ))) lt ) minus+y-y : {x y : ℕ } → (x + y) - y ≡ x minus+y-y {zero} {y} = minus<=0 {zero + y} {y} ≤-refl minus+y-y {suc x} {y} = begin (suc x + y) - y ≡⟨ sym (minus+1 {_} {y} x≤y+x) ⟩ suc ((x + y) - y) ≡⟨ cong suc (minus+y-y {x} {y}) ⟩ suc x ∎ where open ≡-Reasoning minus+yx-yz : {x y z : ℕ } → (y + x) - (y + z) ≡ x - z minus+yx-yz {x} {zero} {z} = refl minus+yx-yz {x} {suc y} {z} = minus+yx-yz {x} {y} {z} minus+xy-zy : {x y z : ℕ } → (x + y) - (z + y) ≡ x - z minus+xy-zy {x} {y} {z} = subst₂ (λ j k → j - k ≡ x - z ) (+-comm y x) (+-comm y z) (minus+yx-yz {x} {y} {z}) +cancel ¬a ¬b c = subst ( λ k → k < y ) (sym (minus<=0 {y} {x} (≤-trans (≤-trans refl-≤s refl-≤s) c))) 0 ¬a ¬b c = +m= {_} {_} {suc y * z} ( begin minus x (suc y) * z + suc y * z ≡⟨ sym (proj₂ *-distrib-+ z (minus x (suc y) ) _) ⟩ ( minus x (suc y) + suc y ) * z ≡⟨ cong (λ k → k * z) (minus+n {x} {suc y} (s≤s c)) ⟩ x * z ≡⟨ sym (minus+n {x * z} {suc y * z} (s≤s (lt c))) ⟩ minus (x * z) (suc y * z) + suc y * z ∎ ) where open ≡-Reasoning lt : {x y z : ℕ } → suc y ≤ x → z + y * z ≤ x * z lt {x} {y} {z} le = *≤ le distr-minus-*' : {z x y : ℕ } → z * (minus x y) ≡ minus (z * x) (z * y) distr-minus-*' {z} {x} {y} = begin z * (minus x y) ≡⟨ *-comm _ (x - y) ⟩ (minus x y) * z ≡⟨ distr-minus-* {x} {y} {z} ⟩ minus (x * z) (y * z) ≡⟨ cong₂ (λ j k → j - k ) (*-comm x z ) (*-comm y z) ⟩ minus (z * x) (z * y) ∎ where open ≡-Reasoning minus- : {x y z : ℕ } → suc x > z + y → minus (minus x y) z ≡ minus x (y + z) minus- {x} {y} {z} gt = +m= {_} {_} {z} ( begin minus (minus x y) z + z ≡⟨ minus+n {_} {z} lemma ⟩ minus x y ≡⟨ +m= {_} {_} {y} ( begin minus x y + y ≡⟨ minus+n {_} {y} lemma1 ⟩ x ≡⟨ sym ( minus+n {_} {z + y} gt ) ⟩ minus x (z + y) + (z + y) ≡⟨ sym ( +-assoc (minus x (z + y)) _ _ ) ⟩ minus x (z + y) + z + y ∎ ) ⟩ minus x (z + y) + z ≡⟨ cong (λ k → minus x k + z ) (+-comm _ y ) ⟩ minus x (y + z) + z ∎ ) where open ≡-Reasoning lemma1 : suc x > y lemma1 = x+y z lemma = <-minus {_} {_} {y} ( subst ( λ x → z + y < suc x ) (sym (minus+n {x} {y} lemma1 )) gt ) sn≤1→n=0 : {n : ℕ } → suc n ≤ 1 → n ≡ 0 sn≤1→n=0 {n} sn≤1 with <-cmp n 0 ... | tri≈ ¬a b ¬c = b ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> c sn≤1 ) minus-* : {M k n : ℕ } → n < k → minus k (suc n) * M ≡ minus (minus k n * M ) M minus-* {zero} {k} {n} lt = begin minus k (suc n) * zero ≡⟨ *-comm (minus k (suc n)) zero ⟩ zero * minus k (suc n) ≡⟨⟩ 0 * minus k n ≡⟨ *-comm 0 (minus k n) ⟩ minus (minus k n * 0 ) 0 ∎ where open ≡-Reasoning minus-* {suc m} {k} {n} lt with <-cmp k 1 minus-* {suc m} {k} {n} lt | tri< a ¬b ¬c = ⊥-elim ( nat-≤> (sx≤py→x≤y a) (≤-trans (s≤s z≤n) lt) ) minus-* {suc m} {k} {n} lt | tri≈ ¬a refl ¬c = subst (λ k → minus 0 k * suc m ≡ minus (minus 1 k * suc m) (suc m)) (sym n=0) lem where n=0 : n ≡ 0 n=0 = sn≤1→n=0 lt lem : minus 0 0 * suc m ≡ minus (minus 1 0 * suc m) (suc m) lem = begin minus 0 0 * suc m ≡⟨⟩ 0 ≡⟨ sym ( minus<=0 {suc m} {suc m} ≤-refl ) ⟩ minus (suc m) (suc m) ≡⟨ cong (λ k → minus k (suc m)) (+-comm 0 (suc m) ) ⟩ minus (suc m + 0) (suc m) ≡⟨⟩ minus (minus 1 0 * suc m) (suc m) ∎ where open ≡-Reasoning minus-* {suc m} {k} {n} lt | tri> ¬a ¬b c = begin minus k (suc n) * M ≡⟨ distr-minus-* {k} {suc n} {M} ⟩ minus (k * M ) ((suc n) * M) ≡⟨⟩ minus (k * M ) (M + n * M ) ≡⟨ cong (λ x → minus (k * M) x) (+-comm M _ ) ⟩ minus (k * M ) ((n * M) + M ) ≡⟨ sym ( minus- {k * M} {n * M} (lemma lt) ) ⟩ minus (minus (k * M ) (n * M)) M ≡⟨ cong (λ x → minus x M ) ( sym ( distr-minus-* {k} {n} )) ⟩ minus (minus k n * M ) M ∎ where M = suc m lemma : {n k m : ℕ } → n < k → suc (k * suc m) > suc m + n * suc m lemma {n} {k} {m} lt = ≤-plus-0 {_} {_} {1} (*≤ lt ) open ≡-Reasoning x=y+z→x-z=y : {x y z : ℕ } → x ≡ y + z → x - z ≡ y x=y+z→x-z=y {x} {zero} {.x} refl = minus<=0 {x} {x} refl-≤ -- x ≡ suc (y + z) → (x ≡ y + z → x - z ≡ y) → (x - z) ≡ suc y x=y+z→x-z=y {suc x} {suc y} {zero} eq = begin -- suc x ≡ suc (y + zero) → (suc x - zero) ≡ suc y suc x - zero ≡⟨ refl ⟩ suc x ≡⟨ eq ⟩ suc y + zero ≡⟨ +-comm _ zero ⟩ suc y ∎ where open ≡-Reasoning x=y+z→x-z=y {suc x} {suc y} {suc z} eq = x=y+z→x-z=y {x} {suc y} {z} ( begin x ≡⟨ cong pred eq ⟩ pred (suc y + suc z) ≡⟨ +-comm _ (suc z) ⟩ suc z + y ≡⟨ cong suc ( +-comm _ y ) ⟩ suc y + z ∎ ) where open ≡-Reasoning m*1=m : {m : ℕ } → m * 1 ≡ m m*1=m {zero} = refl m*1=m {suc m} = cong suc m*1=m +-cancel-1 : (x y z : ℕ ) → x + y ≡ x + z → y ≡ z +-cancel-1 zero y z eq = eq +-cancel-1 (suc x) y z eq = +-cancel-1 x y z (cong pred eq ) +-cancel-0 : (x y z : ℕ ) → y + x ≡ z + x → y ≡ z +-cancel-0 x y z eq = +-cancel-1 x y z (trans (+-comm x y) (trans eq (sym (+-comm x z)) )) *-cancel-left : {x y z : ℕ } → x > 0 → x * y ≡ x * z → y ≡ z *-cancel-left {suc x} {zero} {zero} lt eq = refl *-cancel-left {suc x} {zero} {suc z} lt eq = ⊥-elim ( nat-≡< eq (s≤s (begin x * zero ≡⟨ *-comm x _ ⟩ zero ≤⟨ z≤n ⟩ z + x * suc z ∎ ))) where open ≤-Reasoning *-cancel-left {suc x} {suc y} {zero} lt eq = ⊥-elim ( nat-≡< (sym eq) (s≤s (begin x * zero ≡⟨ *-comm x _ ⟩ zero ≤⟨ z≤n ⟩ _ ∎ ))) where open ≤-Reasoning *-cancel-left {suc x} {suc y} {suc z} lt eq with cong pred eq ... | eq1 = cong suc (*-cancel-left {suc x} {y} {z} lt (+-cancel-0 x _ _ (begin y + x * y + x ≡⟨ +-assoc y _ _ ⟩ y + (x * y + x) ≡⟨ cong (λ k → y + (k + x)) (*-comm x _) ⟩ y + (y * x + x) ≡⟨ cong (_+_ y) (+-comm _ x) ⟩ y + (x + y * x ) ≡⟨ refl ⟩ y + suc y * x ≡⟨ cong (_+_ y) (*-comm (suc y) _) ⟩ y + x * suc y ≡⟨ eq1 ⟩ z + x * suc z ≡⟨ refl ⟩ _ ≡⟨ sym ( cong (_+_ z) (*-comm (suc z) _) ) ⟩ _ ≡⟨ sym ( cong (_+_ z) (+-comm _ x)) ⟩ z + (z * x + x) ≡⟨ sym ( cong (λ k → z + (k + x)) (*-comm x _) ) ⟩ z + (x * z + x) ≡⟨ sym ( +-assoc z _ _) ⟩ z + x * z + x ∎ ))) where open ≡-Reasoning record Finduction {n m : Level} (P : Set n ) (Q : P → Set m ) (f : P → ℕ) : Set (n Level.⊔ m) where field fzero : {p : P} → f p ≡ zero → Q p pnext : (p : P ) → P decline : {p : P} → 0 < f p → f (pnext p) < f p ind : {p : P} → Q (pnext p) → Q p y ¬a ¬b () ... | tri≈ ¬a b ¬c = Finduction.fzero I (sym b) ... | tri< lt _ _ = f-induction0 p (f p) ( ¬a ¬b c = ⊥-elim ( nat-≤> le c ) record Ninduction {n m : Level} (P : Set n ) (Q : P → Set m ) (f : P → ℕ) : Set (n Level.⊔ m) where field pnext : (p : P ) → P fzero : {p : P} → f (pnext p) ≡ zero → Q p decline : {p : P} → 0 < f p → f (pnext p) < f p ind : {p : P} → Q (pnext p) → Q p s≤s→≤ : { i j : ℕ} → suc i ≤ suc j → i ≤ j s≤s→≤ = sx≤py→x≤y n-induction : {n m : Level} {P : Set n } → {Q : P → Set m } → (f : P → ℕ) → Ninduction P Q f → (p : P ) → Q p n-induction {n} {m} {P} {Q} f I p = f-induction0 p (f (Ninduction.pnext I p)) ≤-refl where f-induction0 : (p : P) → (x : ℕ) → (f (Ninduction.pnext I p)) ≤ x → Q p f-induction0 p zero lt = Ninduction.fzero I {p} (fi0 _ lt) f-induction0 p (suc x) le with <-cmp (f (Ninduction.pnext I p)) (suc x) ... | tri< a ¬b ¬c = f-induction0 p x (px≤py a) ... | tri≈ ¬a b ¬c = Ninduction.ind I (f-induction0 (Ninduction.pnext I p) x (s≤s→≤ nle) ) where f>0 : 0 < f (Ninduction.pnext I p) f>0 = subst (λ k → 0 < k ) (sym b) ( s≤s z≤n ) nle : suc (f (Ninduction.pnext I (Ninduction.pnext I p))) ≤ suc x nle = subst (λ k → suc (f (Ninduction.pnext I (Ninduction.pnext I p))) ≤ k) b (Ninduction.decline I {Ninduction.pnext I p} f>0 ) ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> le c ) record Factor (n m : ℕ ) : Set where field factor : ℕ remain : ℕ is-factor : factor * n + remain ≡ m record Factor< (n m : ℕ ) : Set where field factor : ℕ remain : ℕ is-factor : factor * n + remain ≡ m remain 1 → ¬ Dividable k 1 div1 {k} k>1 record { factor = f1 ; is-factor = fa } = ⊥-elim ( nat-≡< (sym fa) ( begin 2 ≤⟨ k>1 ⟩ k ≡⟨ +-comm 0 _ ⟩ k + 0 ≡⟨ refl ⟩ 1 * k ≤⟨ *-mono-≤ {1} {f1} (lem1 _ fa) ≤-refl ⟩ f1 * k ≡⟨ +-comm 0 _ ⟩ f1 * k + 0 ∎ )) where open ≤-Reasoning lem1 : (f1 : ℕ) → f1 * k + 0 ≡ 1 → 1 ≤ f1 lem1 zero () lem1 (suc f1) eq = s≤s z≤n div+div : { i j k : ℕ } → Dividable k i → Dividable k j → Dividable k (i + j) ∧ Dividable k (j + i) div+div {i} {j} {k} di dj = ⟪ div+div1 , subst (λ g → Dividable k g) (+-comm i j) div+div1 ⟫ where fki = Dividable.factor di fkj = Dividable.factor dj div+div1 : Dividable k (i + j) div+div1 = record { factor = fki + fkj ; is-factor = ( begin (fki + fkj) * k + 0 ≡⟨ +-comm _ 0 ⟩ (fki + fkj) * k ≡⟨ *-distribʳ-+ k fki _ ⟩ fki * k + fkj * k ≡⟨ cong₂ ( λ i j → i + j ) (+-comm 0 (fki * k)) (+-comm 0 (fkj * k)) ⟩ (fki * k + 0) + (fkj * k + 0) ≡⟨ cong₂ ( λ i j → i + j ) (Dividable.is-factor di) (Dividable.is-factor dj) ⟩ i + j ∎ ) } where open ≡-Reasoning div-div : { i j k : ℕ } → k > 1 → Dividable k i → Dividable k j → Dividable k (i - j) ∧ Dividable k (j - i) div-div {i} {j} {k} k>1 di dj = ⟪ div-div1 di dj , div-div1 dj di ⟫ where div-div1 : {i j : ℕ } → Dividable k i → Dividable k j → Dividable k (i - j) div-div1 {i} {j} di dj = record { factor = fki - fkj ; is-factor = ( begin (fki - fkj) * k + 0 ≡⟨ +-comm _ 0 ⟩ (fki - fkj) * k ≡⟨ distr-minus-* {fki} {fkj} ⟩ (fki * k) - (fkj * k) ≡⟨ cong₂ ( λ i j → i - j ) (+-comm 0 (fki * k)) (+-comm 0 (fkj * k)) ⟩ (fki * k + 0) - (fkj * k + 0) ≡⟨ cong₂ ( λ i j → i - j ) (Dividable.is-factor di) (Dividable.is-factor dj) ⟩ i - j ∎ ) } where open ≡-Reasoning fki = Dividable.factor di fkj = Dividable.factor dj open _∧_ div+1 : { i k : ℕ } → k > 1 → Dividable k i → ¬ Dividable k (suc i) div+1 {i} {k} k>1 d d1 = div1 k>1 div+11 where div+11 : Dividable k 1 div+11 = subst (λ g → Dividable k g) (minus+y-y {1} {i} ) ( proj2 (div-div k>1 d d1 ) ) div 1 → m > 0 → m < k → ¬ Dividable k m div1 m>0 m (div0 ) div 0 → m > 0 → (d : Dividable k m ) → Dividable.factor d > 0 00 m>0 d with Dividable.factor d in eq1 ... | zero = ⊥-elim ( nat-≡< ff1 m>0 ) where ff1 : 0 ≡ m ff1 = begin 0 ≡⟨⟩ 0 * k + 0 ≡⟨ cong (λ j → j * k + 0) (sym eq1) ⟩ Dividable.factor d * k + 0 ≡⟨ Dividable.is-factor d ⟩ m ∎ where open ≡-Reasoning ... | suc t = s≤s z≤n div→k≤m : { m k : ℕ } → k > 1 → m > 0 → Dividable k m → m ≥ k div→k≤m {m} {k} k>1 m>0 d with <-cmp m k ... | tri< a ¬b ¬c = ⊥-elim ( div1 m>0 a d ) ... | tri≈ ¬a refl ¬c = ≤-refl ... | tri> ¬a ¬b c = 1 → Factor< k m factor< {k} {m} k>1 = n-induction {_} {_} {ℕ} {λ m → Factor< k m} F I m where F : ℕ → ℕ F m = m F0 : ( m : ℕ ) → F (m - k) ≡ 0 → Factor< k m F0 0 eq = record { factor = 0 ; remain = 0 ; is-factor = refl ; remain1 } F0 (suc m) eq with <-cmp k (suc m) ... | tri< a ¬b ¬c = record { factor = 1 ; remain = 0 ; is-factor = lem00 ; remain1 } where lem00 : k + zero + 0 ≡ suc m lem00 = begin -- minus (suc m) k ≡ 0 k + zero + 0 ≡⟨ +-comm (k + 0) _ ⟩ k + 0 ≡⟨ +-comm k _ ⟩ k ≡⟨ sym ( i-j=0→i=j (≤-trans a≤sa a) eq ) ⟩ suc m ∎ where open ≡-Reasoning ... | tri≈ ¬a b ¬c = record { factor = 1 ; remain = 0 ; is-factor = trans (trans (+-comm (k + 0) _) (+-comm k 0)) b ; remain1 } ... | tri> ¬a ¬b c = record { factor = 0 ; remain = suc m ; is-factor = refl ; remain ¬a ¬b c = record { factor = 0 ; remain = m ; is-factor = refl ; remain1 ) 0 0 Factor<→¬k≤m {k} {m} k≤m x with Factor<.factor x in eqx ... | zero = ⊥-elim ( nat-≤> k≤m (begin suc m ≡⟨ cong suc (sym (Factor<.is-factor x)) ⟩ suc (Factor<.factor x * k + Factor<.remain x) ≡⟨ cong (λ j → suc (j * k + _)) eqx ⟩ suc (0 * k + Factor<.remain x) ≡⟨ refl ⟩ suc (Factor<.remain x) ≤⟨ Factor<.remain 1 → (x y : Factor< k m) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) Factor<-inject {k} {m} k>1 x y = n-induction {_} {_} {ℕ} {λ m → (x y : Factor< k m) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) } F I m x y where F : ℕ → ℕ F m = m f00 : (m : ℕ ) → ( k ≡ suc m ) → (x y : Factor< k (suc m)) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) f00 m lem00 x y = ⟪ trans (lem02 x) (sym (lem02 y)) , trans (lem01 x) (sym (lem01 y)) ⟫ where lem02 : (f : Factor< k (suc m)) → Factor<.factor f ≡ 1 lem02 f with <-cmp (Factor<.factor f) 1 ... | tri< a ¬b ¬c = ⊥-elim ( nat-≡< (Factor<.is-factor f) (begin suc (Factor<.factor f * k + Factor<.remain f) ≤⟨ s≤s (≤-plus {_} {_} {Factor<.remain f} (*≤ (px≤py a)) ) ⟩ suc (0 * k + Factor<.remain f) ≡⟨⟩ suc (0 + Factor<.remain f) ≡⟨⟩ suc (Factor<.remain f) ≤⟨ Factor<.remain ¬a ¬b c = ⊥-elim ( nat-≡< (sym (Factor<.is-factor f)) (begin -- 1 < Factor<. factor f, fa * k + r > k ≡ suc m suc (suc m) ≡⟨ cong suc (sym lem00) ⟩ suc k ≡⟨ sym (+-comm k 1) ⟩ k + 1 <⟨ <-plus-0 k>1 ⟩ k + k ≡⟨ cong (λ j → k + j) (+-comm 0 _ ) ⟩ k + (k + 0) ≡⟨⟩ k + (k + 0 * k) ≡⟨ refl ⟩ 2 * k ≤⟨ *≤ c ⟩ Factor<.factor f * k ≤⟨ x≤x+y ⟩ Factor<.factor f * k + Factor<.remain f ∎ ) ) where open ≤-Reasoning lem03 : k ≡ 1 * k lem03 = +-comm 0 k lem01 : (f : Factor< k (suc m)) → Factor<.remain f ≡ 0 lem01 f = +-cancel-1 _ _ _ ( begin Factor<.factor f * k + Factor<.remain f ≡⟨ Factor<.is-factor f ⟩ suc m ≡⟨ sym lem00 ⟩ k ≡⟨ +-comm 0 k ⟩ k + 0 ≡⟨ cong (λ j → j + 0) lem03 ⟩ 1 * k + 0 ≡⟨ cong (λ j → j * k + 0) (sym (lem02 f)) ⟩ Factor<.factor f * k + 0 ∎ ) where open ≡-Reasoning F0 : ( m : ℕ ) → F (m - k) ≡ 0 → (x y : Factor< k m) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) F0 0 eq x y = ⟪ trans (lem00 x) (sym (lem00 y)) , trans (lem01 x) (sym (lem01 y)) ⟫ where lem01 : (f : Factor< k 0) → Factor<.remain f ≡ 0 lem01 f with Factor<.remain f in eq1 ... | zero = refl ... | suc n = ⊥-elim ( nat-≡< (sym (Factor<.is-factor f)) (begin suc 0 ≤⟨ s≤s z≤n ⟩ suc n ≡⟨ sym eq1 ⟩ Factor<.remain f ≡⟨ refl ⟩ 0 + Factor<.remain f ≤⟨ x≤y+x ⟩ Factor<.factor f * k + Factor<.remain f ∎ ) ) where open ≤-Reasoning lem00 : (f : Factor< k 0) → Factor<.factor f ≡ 0 lem00 f with m*n=0⇒m=0∨n=0 {Factor<.factor f} {k} (trans (+-comm 0 (Factor<.factor f * k) ) (subst (λ j → _ + j ≡ 0) (lem01 f) (Factor<.is-factor f))) ... | case1 fa=0 = fa=0 ... | case2 k=0 = ⊥-elim (nat-≡< (sym k=0) (<-trans a1) ) F0 (suc m) eq x y with <-cmp k (suc m) ... | tri< a ¬b ¬c = ⊥-elim ( ¬b lem00 ) where lem00 : k ≡ suc m lem00 = begin k ≡⟨ sym ( i-j=0→i=j (≤-trans a≤sa a) eq ) ⟩ suc m ∎ where open ≡-Reasoning ... | tri≈ ¬a b ¬c = f00 m b x y ... | tri> ¬a ¬b c = ⟪ trans ( lem00 x ) (sym (lem00 y)) , trans (lem01 x) (sym (lem01 y)) ⟫ where lem00 : (f : Factor< k (suc m)) → Factor<.factor f ≡ 0 lem00 f with Factor<.factor f in eq1 ... | zero = refl ... | suc fa = ⊥-elim ( nat-≡< (sym (Factor<.is-factor f)) (begin suc (suc m) ≤⟨ c ⟩ k ≤⟨ x≤x+y ⟩ k + Factor<.remain f ≡⟨ cong (λ j → j + _) (+-comm 0 k) ⟩ suc 0 * k + Factor<.remain f ≤⟨ ≤-plus {_} {_} {Factor<.remain f} (*≤ {suc 0} {suc fa} {k} (s≤s z≤n)) ⟩ suc fa * k + Factor<.remain f ≡⟨ cong (λ j → j * k + Factor<.remain f) (sym eq1) ⟩ Factor<.factor f * k + Factor<.remain f ∎ ) ) where open ≤-Reasoning lem01 : (f : Factor< k (suc m)) → Factor<.remain f ≡ (suc m) lem01 f = begin Factor<.remain f ≡⟨ refl ⟩ 0 * k + Factor<.remain f ≡⟨ cong (λ j → j * k + Factor<.remain f) (sym (lem00 f)) ⟩ Factor<.factor f * k + Factor<.remain f ≡⟨ Factor<.is-factor f ⟩ suc m ∎ where open ≡-Reasoning ind : {m : ℕ} → ( (x y : Factor< k (m - k)) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) ) → (x y : Factor< k m) → (Factor<.factor x ≡ Factor<.factor y ) ∧ (Factor<.remain x ≡ Factor<.remain y ) ind {m} prev x y with <∨≤ m k ... | case1 m (begin k ≤⟨ x≤x+y ⟩ k + (fa * k + Factor<.remain x) ≡⟨ sym (+-assoc k _ _) ⟩ ( k + fa * k ) + Factor<.remain x ≡⟨ refl ⟩ suc fa * k + Factor<.remain x ≡⟨ cong (λ j → j * k + Factor<.remain x) (sym eqx) ⟩ Factor<.factor x * k + Factor<.remain x ≡⟨ Factor<.is-factor x ⟩ m ∎ ) m1 ) 0 1 → Dec0 (Dividable k m ) decD {k} {m} k>1 = dec0 (factor< {k} {m} k>1) where dec0 : Factor< k m → Dec0 (Dividable k m) dec0 fc with Factor<.remain fc in eq1 ... | zero = yes0 record { factor = Factor<.factor fc ; is-factor = trans (cong (λ j → Factor<.factor fc * k + j) (sym eq1)) (Factor<.is-factor fc) } ... | suc t = no0 ( λ dv → F1 eq1 dv )