{-# OPTIONS --safe #-} module Problem13 where open import Data.Empty using (⊥-elim) open import Data.Fin hiding (_≟_; _+_; _<_; _>_; _≤_) open import Data.Fin.Properties hiding (_≟_; ≤-trans) open import Data.Nat open import Data.Nat.DivMod open import Data.Nat.Properties open import Data.Product open import Data.Unit using (tt) open import Data.Vec open import Function.Base using (_$′_) open import Relation.Nullary.Decidable open import Relation.Binary.PropositionalEquality open ≤-Reasoning renaming (begin_ to begin-≤_) okToDivide : ∀ n → n > 1 → False (n ≟ 0) okToDivide (suc n) p = tt toRadix : (n : ℕ)(nz : n > 1) → (f : ℕ) → ℕ → Vec (Fin n) f toRadix n nz zero k = [] toRadix n nz (suc f) k with (k divMod n) {okToDivide _ nz} ... | result q r prf₂ = r ∷ toRadix n nz f q fromRadix : (n : ℕ) {f : ℕ} → Vec (Fin n) f → ℕ fromRadix n [] = 0 fromRadix n (x ∷ xs) = toℕ x + n * fromRadix n xs goal₁ : (n : ℕ)(nz : n > 1){f : ℕ}(num : Vec (Fin n) f) → toRadix n nz f (fromRadix n num) ≡ num goal₁ n nz [] = refl goal₁ n nz (x ∷ xs) with ((toℕ x + n * fromRadix n xs) divMod n) {okToDivide _ nz} ... | result q r prf = let (prf₁ , prf₂) = invertProof x r (fromRadix n xs) q prf in cong₂ _∷_ (sym prf₁) (trans (sym (cong (toRadix n nz _) prf₂)) (goal₁ n nz xs)) where invertProof : (x y : Fin n) (p q : ℕ) → toℕ x + n * p ≡ toℕ y + q * n → x ≡ y × p ≡ q invertProof x y zero zero prf .proj₁ = toℕ-injective $′ +-cancelʳ-≡ (toℕ x) (toℕ y) $′ begin-equality toℕ x + n * zero ≡⟨ prf ⟩ toℕ y + zero ≡˘⟨ cong (toℕ y +_) (*-zeroʳ n) ⟩ toℕ y + n * zero ∎ invertProof x y zero zero prf .proj₂ = refl invertProof x y zero (suc q) prf = ⊥-elim $′ <⇒≱ (toℕ 1)(f : ℕ)(k : ℕ)(p : k < n ^ f) → fromRadix n (toRadix n nz f k) ≡ k goal₂ n nz zero k k