""" printtools.py c odenthal 2005/05/30 This module contains some functions for displaying strings that are meant to be useful in cryptanalysis. """ from __future__ import division import stringtools def formatFreqList(lst): """ Takes a list of type [(key,freq)] and returns a list of type [string] where the each string is formatted from key and percent. """ frmt = lambda (k,d) : "\t%s\t%5d" % (k,d) return map(frmt, lst) def formatPercList(lst): """ Takes a list of type [(key,percent)] and returns a list of type [string] where the each string is formatted from key and percent. """ frmt = lambda (k,f) : "\t%s\t%2.2f" % (k,f) return map(frmt, lst) def formatProbList(lst): """ Takes a list of type [(key,probability)] and returns a list of type [string] where the each string is formatted from key and probability. """ frmt = lambda (k,f) : "\t%s\t%0.4f" % (k,f) return map(frmt, lst) def formatDataInCols(datalstList,dataType='prob'): """ Takes a list of type [probList], [percList] or [freqList] where probList is a list of type [(key,probability)], percList is a list of type [(key,percent)] and freqList is a list of type [(key,frequency)]. A string that displays the (perc/freq)List's in columns is returned. """ if dataType == 'prob': strLst = map(formatProbList,datalstList) elif dataType == 'perc': strLst = map(formatPercList,datalstList) else: strLst = map(formatFreqList,datalstList) # Group data in rows, insert tabs between columns, and # join into lines. strLst = apply(zip,strLst) strLst = ["\t".join(lst) for lst in strLst] # Insert newlines between lines return "\n".join(strLst) def formatTextInCols(T,ln,sp=1): """ Breaks a string into words of length 'ln', inserts 'sp' spaces between each character, then displays each word on a separate line. """ wLst = stringtools.breakIntoWords(T,lngth=ln) wLst = addSpaces2List(wLst,sp) return "\n"+"\n".join(wLst) def formatCols(colList,perc=True): """ Takes a list of type [percList] or [freqList] where percList is a list of type [(key,percent)] and freqList is a list of type [(key,frequency)]. A string that displays the (perc/freq)List's in columns is returned. """ if perc: strLst = map(formatPercList,colList) else: strLst = map(printFreqList,colList) strLst = apply(zip,strLst) strLst = ["\t".join(lst) for lst in strLst] return "\n".join(strLst) def formatRows(rowLst,l=5,ll=80,s=1): lnLst = [groupIntoLines( stringtools.breakIntoWords(row,lngth=l), lngth=l, lnlngth=ll, spc=s) for row in rowLst] lnLst = apply(zip,lnLst) lnLst = ["\n".join(ln) for ln in lnLst] return "\n"+"\n\n".join(lnLst) def breakPoints(strng,linelength=80,spaces=0): """ Finds the break points in a string so that it prints out nicely. """ # If the string is empty we're done. if len(strng)==0: return [0] # If we're going to insert extra spaces we need # to cut down the line length. linelength = linelength // (1+spaces) # If the string has a space in the first 'linelength' # characters we can split it there. Otherwise we'll # just split after 'linelength' characters. try: index = strng[:linelength].rindex(" ")+1 except ValueError: index = linelength # Get the indices for the tail of the string. indexList = breakPoints(strng[index:],linelength=linelength) # Add the current index to each of the tail's indices. indexList = [index + k for k in indexList] # Insert 0 at the begining of the index list. indexList.insert(0,0) return indexList def displayStrings(template,stringList,linelength=80,spaces=0): """ Displays the strings in stringList (a list of strings). They are split up in such a way that the 'template' string is broken only at spaces so that it displays on a line of length 'linelength' after inserting 'spaces' into the string. """ indexList = breakPoints(template,linelength=linelength,spaces=spaces) stringListList = [[strng[j:k] for strng in stringList] for (j,k) in zip(indexList,indexList[1:])] spacedList = [[addSpaces2String(strng,spaces=spaces) for strng in strngList] for strngList in stringListList] joinedList = ["\n".join(spaced) for spaced in spacedList] return "\n\n".join(joinedList) def groupIntoLines(lst,lngth=5,lnlngth=80,spc=1): """ Regroups a list of words - each of length 'lngth' - into a list of lines - each of length no greater than 'lnlngth'. There are 'spc' " "s placed between each character, with 2*'spc'+1 " "s placed between words. """ wrdcnt = lnlngth // ((lngth+1)*(1+spc)) s = " "*spc lnLst = [] while lst: l,lst = lst[:wrdcnt],lst[wrdcnt:] w = " ".join(l) w = s.join(list(w)) lnLst.append(w) return lnLst def displayStrings(template,stringList,linelength=80,spaces=0): """ Displays the strings in stringList (a list of strings). They are split up in such a way that the 'template' string is broken only at spaces so that it displays on a line of length 'linelength' after inserting 'spaces' into the string. """ indexList = breakPoints(template,linelength=linelength,spaces=spaces) stringListList = [[strng[j:k] for strng in stringList] for (j,k) in zip(indexList,indexList[1:])] spacedList = [[addSpaces2String(strng,spaces=spaces) for strng in strngList] for strngList in stringListList] joinedList = ["\n".join(spaced) for spaced in spacedList] return "\n\n".join(joinedList) def addSpaces2String(strng,spaces=0): s=" "*spaces return s.join(list(strng)) def addSpaces2List(L,spaces=1): return [addSpaces2String(strng,spaces) for strng in L]