Advertisement
lewapkon

huffman.py

Mar 23rd, 2014
368
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.05 KB | None | 0 0
  1. #!/usr/bin/python
  2. # coding: utf-8
  3.  
  4. from collections import Counter
  5. from operator import itemgetter
  6. import urllib
  7. from matplotlib import pyplot as plt
  8.  
  9. '''
  10. ===========
  11. functions
  12. ===========
  13. '''
  14.  
  15. def biSearch(a, x):
  16.     l = 0
  17.     r = len(a) - 1
  18.     while (l <= r):
  19.         mid = (l+r)/2
  20.         if (a[mid][1] < x):
  21.             r = mid - 1
  22.         else:
  23.             l = mid + 1
  24.     return l
  25.    
  26. def generateTree(a):
  27.     while len(a) > 1:
  28.         l = a.pop()
  29.         r = a.pop()
  30.         val = l[1]+r[1]
  31.         # node's structure is: [letter, value, left hand child, right hand child]
  32.         node = [None, val, l, r]
  33.         pos = biSearch(a, val) if len(a)>1 else 0
  34.         a.insert(pos, node)
  35.  
  36. def uniqueGenerator():
  37.     ''' the generator is needed to prevent the existance of nodes which are having more than one parent and more than two children
  38.        normally it would occur if two nodes had the same value '''
  39.     i = 0
  40.     while True:
  41.         yield ('i' + str(i))
  42.         i += 1
  43.  
  44. def huffCode(tree, result, dot, values, code=[], dotTemp=[], isRight=False):
  45.     if (tree[0] is not None):
  46.         result[tree[0]] = ''.join(code), tree[1]
  47.         dot.append(''.join(dotTemp) + tree[0] + ('', '[label=1]')[isRight] + ';\n')
  48.     else:
  49.         id = next(generator)
  50.         values[id]=tree[1]
  51.         huffCode(tree[2], result, dot, values, code+['0'], dotTemp + [id + '->'] if not isRight else [id + '->'], False)
  52.         huffCode(tree[3], result, dot, values, code+['1'], [id + '->'] if not isRight else dotTemp + [id + '->'], True)
  53.  
  54. def generateDotScript(dot, huff, values):
  55.     ''' http://en.wikipedia.org/wiki/DOT_(graph_description_language) '''
  56.     letters = [ '{0}[shape=record,label="{{{{{0}|{1}}}|{2}}}"];\n'.format(k, v[1], v[0]) for k,v in huff.items() ]
  57.     l = [ '{0}[label={1}];\n'.format(k, v) for k,v in values.items() ]
  58.     return 'digraph G{\nedge[label=0];\ngraph[ranksep=0];\n' + ''.join(letters) + ''.join(l) + ''.join(dot) + '}'
  59.  
  60. def openDiagramImage(dot):
  61.     ''' sends a POST request to Google Chart API '''
  62.     try:
  63.         dot = dot.encode('utf-8')
  64.         data = urllib.urlencode({ 'cht': 'gv:dot',
  65.                                   'chl': dot
  66.         })
  67.         url = 'http://chart.apis.google.com/chart'
  68.         f = urllib.urlopen(url, data)
  69.         a = plt.imread(f)
  70.         plt.imshow(a)
  71.         plt.axis('off')
  72.         mng = plt.get_current_fig_manager()
  73.         mng.resize(*mng.window.maxsize())
  74.         plt.show()
  75.     except:
  76.         print "Couldn't open the image of generated tree. There might be a problem with your internet connection or the request to Google Chart API is too long."
  77.  
  78. '''
  79. ======
  80. main
  81. ======
  82. '''
  83.  
  84. text = 'Litwo! Ojczyzno moja! ty jestes jak zdrowie. Ile cie trzeba cenic, ten tylko sie dowie, Kto cie stracil. Dzis pieknosc twa w calej ozdobie Widze i opisuje, bo tesknie po tobie. Panno Świeta, co jasnej bronisz Czestochowy I w Ostrej swiecisz Bramie! Ty, co grod zamkowy Nowogrodzki ochraniasz z jego wiernym ludem! Jak mnie dziecko do zdrowia powrocilas cudem (Gdy od placzacej matki pod Twoja opieke Ofiarowany, martwa podnioslem powieke I zaraz moglem pieszo do Twych swiatyn progu Isc za wrocone życie podziekowac Bogu), Tak nas powrocisz cudem na Ojczyzny lono. Tymczasem przenos moje dusze uteskniona Do tych pagorkow lesnych, do tych lak zielonych, Szeroko nad blekitnym Niemnem rozciagnionych; Do tych pol malowanych zbożem rozmaitem, Wyzlacanych pszenica, posrebrzanych żytem; Gdzie bursztynowy swierzop, gryka jak snieg biala, Gdzie panienskim rumiencem dziecielina pala, A wszystko przepasane, jakby wstega, miedza Zielona, na niej z rzadka ciche grusze siedza. Środ takich pol przed laty, nad brzegiem ruczaju, Na pagorku niewielkim, we brzozowym gaju, Stal dwor szlachecki, z drzewa, lecz podmurowany; Świecily sie z daleka pobielane sciany, Tym bielsze, że odbite od ciemnej zieleni Topoli, co go bronia od wiatrow jesieni. Dom mieszkalny niewielki, lecz zewszad chedogi, I stodole mial wielka, i przy niej trzy stogi Użatku, co pod strzecha zmiescic sie nie może; Widac, że okolica obfita we zboże, I widac z liczby kopic, co wzdluż i wszerz smugow Świeca gesto jak gwiazdy, widac z liczby plugow Orz cych wcze a snie lany ogromne ugoru, Czarnoziemne, zapewne należne do dworu, Uprawne dobrze na ksztalt ogrodowych grzadek: Że w tym domu dostatek mieszka i porzadek. Brama na wciaż otwarta przechodniom oglasza, Że goscinna i wszystkich w goscine zaprasza.'
  85.  
  86. # creates descendingly sorted list of tuples: (letter, frequency)
  87. text = ''.join( i for i in text if i.isalpha())
  88. text = text.upper()
  89. letters = Counter(text)
  90. letters = sorted(letters.iteritems(), key=itemgetter(1), reverse=True)
  91.  
  92. # generates a binary tree represented by a multilevel list
  93. tree=letters
  94. generateTree(tree)
  95.  
  96. generator = uniqueGenerator()
  97. huff = {}
  98. dot = []
  99. values = {}
  100. huffCode(tree[0], huff, dot, values)
  101. for k,v in sorted(huff.iteritems(), key=itemgetter(0)):
  102.     print '{0}: code={1}, value={2}'.format(k, v[0], v[1])
  103.  
  104. dotScript = generateDotScript(dot, huff, values)
  105. openDiagramImage(dotScript)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement