module l18 where
open import Algebra
open import Data.Vec
open import Data.Nat
open import Data.Nat.Properties
private
module ℕ = CommutativeSemiring commutativeSemiring
open import Data.Product
open import Relation.Binary.PropositionalEquality
import Algebra.RingSolver.AlmostCommutativeRing as ACR
import Algebra.RingSolver.Simple as Solver
open Solver (ACR.fromCommutativeSemiring commutativeSemiring)
zeroLem : (n : ℕ) → n ≡ n + 0
zeroLem = solve 1 (\n → n := n :+ con 0) refl
sucLem₁ : (m n : ℕ) → (1 + (m + n)) ≡ (m + (1 + n))
sucLem₁ = solve 2 (\m n → con 1 :+ (m :+ n) := m :+ (con 1 :+ n)) refl
sucLem₂ : (m n : ℕ) → (m + (1 + n)) ≡ (1 + (m + n))
sucLem₂ m n = sym (sucLem₁ m n)
data Order : Set where le gt : Order
order : ℕ → ℕ → Order
order zero n = le
order (suc m) zero = gt
order (suc m) (suc n) = order m n
mutual
merge : {m n : ℕ} → Vec ℕ m → Vec ℕ n → Vec ℕ (m + n)
merge [] ns = ns
merge {suc lm} {zero} (m ∷ ms) [] = m ∷ subst (Vec ℕ) (zeroLem lm) ms
merge {suc lm} {suc ln} (m ∷ ms) (n ∷ ns) with order m n
... | le = m ∷ merge ms (n ∷ ns)
... | gt = n ∷ subst (Vec ℕ) (sucLem₁ lm ln) (merge' m ms ns)
merge' : {m n : ℕ} → ℕ → Vec ℕ m → Vec ℕ n → Vec ℕ (1 + (m + n))
merge' {lm} {zero} m ms [] = m ∷ subst (Vec ℕ) (zeroLem lm) ms
merge' {lm} {suc ln} m ms (n ∷ ns) with order m n
... | le = m ∷ merge ms (n ∷ ns)
... | gt = n ∷ subst (Vec ℕ) (sucLem₁ lm ln) (merge' m ms ns)
data Parity : Set where p0 p1 : Parity
pℕ : Parity → ℕ
pℕ p0 = 0
pℕ p1 = 1
data DealT (X : Set) : ℕ → Set where
empT : DealT X 0
leafT : X → DealT X 1
nodeT : {n : ℕ} (p : Parity) → DealT X (pℕ p + n) → DealT X n
→ DealT X (((pℕ p + n) + n))
insert : {X : Set}{n : ℕ} → X → DealT X n → DealT X (1 + n)
insert x empT = leafT x
insert x (leafT y) = nodeT p0 (leafT y) (leafT x)
insert x (nodeT p0 l r) = nodeT p1 (insert x l) r
insert {X} x (nodeT {n} p1 l r) = subst (\n → DealT X n) (cong suc (sucLem₂ n n)) (nodeT p0 l (insert x r))
deal : {n : ℕ} → Vec ℕ n → DealT ℕ n
deal [] = empT
deal (n ∷ ns) = insert n (deal ns)
mergeT : {n : ℕ} → DealT ℕ n → Vec ℕ n
mergeT empT = []
mergeT (leafT n) = [ n ]
mergeT (nodeT p l r) = merge (mergeT l) (mergeT r)
sort : {n : ℕ} → Vec ℕ n → Vec ℕ n
sort ns = mergeT (deal ns)
ex1 : Vec ℕ 6
ex1 = 5 ∷ 2 ∷ 0 ∷ 1 ∷ 4 ∷ 3 ∷ []
ex2 : Vec ℕ 6
ex2 = 100 ∷ 1 ∷ 10 ∷ 1 ∷ 100 ∷ 10 ∷ []