[Haskell] Кодирование методом Шеннона-Фано
От: kurtx  
Дата: 18.09.07 08:11
Оценка:
Доброго времени суток.
Почитав статьи на RSDN решил изучить декларативную парадигму, в частности функциональный подход.
В качестве упражнений пишу расчеты лабораторных работ по Теории Информации на Haskell. И вот загвоздка, не могу сгенерировать бинарное дерево:

module Main where

-- бинарное дерево
data BinTree a = Leaf a | Branch (BinTree a) (BinTree a)

-- обходим дерево, генерируем для каждого символа его код
calcRule :: BinTree (Char,Integer) -> [(Char,String)]
calcRule (Branch lhs rhs) =
  let
    calc' :: String -> BinTree (Char,Integer) -> [(Char,String)]
    calc' code (Leaf x) = [(fst x, code)]
    calc' code (Branch lhs rhs) = (calc' (code ++ "0") lhs) ++ (calc' (code ++ "1") rhs)
  in
    (calc' "0" lhs) ++ (calc' "1" rhs)

-- генерируем дерево
genTree :: [(Char,Integer)] -> BinTree (Char,Integer)
{-
-- вот такое дерево должно получиться
genTree _ = Branch (Branch (Leaf ('A',15))
                           (Leaf ('B',7)))
                   (Branch (Leaf ('C',6))
                           (Branch (Leaf ('D',6))
                                   (Leaf ('E',5))))
-}
genTree sepp = undefined

-- получаем список пар (символ, код) из списка (символ, кол-во)
getRule :: [(Char,Integer)] -> [(Char,String)]
getRule sorted_ch_count_pairs =
  let
    tree = genTree sorted_ch_count_pairs
  in
    calcRule tree

--------
main =
  let
    -- список (символ, кол-во)
    char_count_pairs = [('A',15), ('B',7), ('C',6), ('D',6), ('E',5)]
  in
    print $ getRule char_count_pairs


Визуально дерево должно выглядеть вот так:
http://en.wikipedia.org/wiki/Shannon-Fano_coding

Группы символов делятся по алгоритму:
1. сумма первой группы (p1) и второй (p2) равна нулю;
2. p1 <= p2 ?
* да: добавить в первую группу символ с начала таблицы;
* нет: добавить во вторую группу символ с конца таблицы;
3. если все символы разделены на группы, то завершить алгоритм, иначе перейти к шагу 2.

Т.е. надо как-то рекурсивно поделить список [('A',15), ('B',7), ('C',6), ('D',6), ('E',5)] на группы и натянуть результат на дерево. Уже 3-ий день не могу это сделать
Помогите кодом или советом. Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.