Counting Sort
〈Functional Algorithm Design〉最後一節的那三個 sorting algorithm derivation 實在好複雜,所以我想自己弄一個試試看。於是我挑上
perm : List Nat ← List Nat perm = ((fun bagify) º) ○ (fun bagify)
這個定義來做。其中 bag 實作為一個 List (Nat × Nat)
,每個 pair 分別是一個數字和它出現的次數,整個 list 依照前者從小到大排列。(就是這裡作弊了 XD。)bagify
就定義成
bagify : List Nat -> List (Nat × Nat) bagify = foldr consbag [] where consbag : Nat -> List (Nat × Nat) -> List (Nat × Nat) consbag a [] = < a , 1 > :: [] consbag a (< a' , c > :: x) = a == a' => < a' , suc c > :: x ! a > a' => < a' , c > :: consbag a x ! otherwise < a , 1 > :: < a' , c > :: x
把 specification ordered? ○ perm
展開成 ordered? ○ bagifyº ○ bagify
後,很顯然只能從前面兩個下手,而那一段很自然就是把 bag 鋪展成一個 sorted list。把這個動作叫做 unroll
,
unroll : List (Nat × Nat) -> List Nat unroll = foldr dup [] where dup : Nat × Nat -> List Nat -> List Nat dup < a , c > x = dup-term a c x where dup-term : Nat -> Nat -> List Nat -> List Nat dup-term a 0 x = x dup-term a (suc n) x = a :: dup-term a n x
就得到 counting sort unroll ○ bagify
。雖然整個 derivation 平淡無奇,也沒用到 fold fusion,不過在其他 sorting 都還做不出來的情況下,先來試試也好 XD。
--
像 combine = cons ⊔ (cons ○ (idR ⨉ combine) ○ swap ○ (idR ⨉ (cons º)))
這種 relation 根本沒辦法動它呀 XD。
Labels: Agda, Program Derivation
<< 回到主頁