From de0813f5233bb45cc196d59fbc3f0ce30dba2c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= Date: Mon, 22 Oct 2012 13:17:42 +0200 Subject: [PATCH] automatic pony name and balloon style name spelling correction --- ponysay.py | 75 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/ponysay.py b/ponysay.py index 34674579..b7abe7f9 100755 --- a/ponysay.py +++ b/ponysay.py @@ -259,17 +259,19 @@ class Ponysay(): Returns one file with full path, names is filter for names, also accepts filepaths @param names:list Ponies to choose from, may be `None` + @param alt:bool For method internal use... @return :str The file name of a pony ''' - def __getponypath(self, names = None): + def __getponypath(self, names = None, alt = False): ponies = {} ## List all pony files, without the .pony ending for ponydir in ponydirs: for ponyfile in os.listdir(ponydir): - pony = ponyfile[:-5] - if pony not in ponies: - ponies[pony] = ponydir + ponyfile + if endswith(ponyfile, ".pony"): + pony = ponyfile[:-5] + if pony not in ponies: + ponies[pony] = ponydir + ponyfile ## Support for explicit pony file names if not names == None: @@ -284,6 +286,11 @@ class Ponysay(): ## Select a random pony of the choosen onles pony = names[random.randrange(0, len(names))] if pony not in ponies: + if not alt: + autocorrect = SpelloCorrecter(ponydirs, '.pony') + (alternatives, dist) = autocorrect.correct(pony) + if len(alternatives) > 0: + return self.__getponypath(alternatives, True) sys.stderr.write('I have never heard of anypony named %s\n' % (pony)); exit(1) else: @@ -405,7 +412,6 @@ class Ponysay(): c -= 1 columns[c] = columns[c][:-diff] diff -= 1 - pass ## Create rows from columns lines = [] @@ -601,9 +607,10 @@ class Ponysay(): Returns one file with full path, names is filter for style names, also accepts filepaths @param names:list Balloons to choose from, may be `None` + @param alt:bool For method internal use @param :str The file name of the balloon, will be `None` iff `names` is `None` ''' - def __getballoonpath(self, names): + def __getballoonpath(self, names, alt = False): ## Stop if their is no choosen balloon if names is None: return None @@ -633,6 +640,11 @@ class Ponysay(): ## Select a random balloon of the choosen ones balloon = names[random.randrange(0, len(names))] if balloon not in balloons: + if not alt: + autocorrect = SpelloCorrecter(balloondirs, '.think' if isthink else '.say') + alternatives = autocorrect.correct(balloon)[0] + if len(alternatives) > 0: + return self.__getponypath(alternatives, True) sys.stderr.write('That balloon style %s does not exist\n' % (balloon)); exit(1) else: @@ -1981,20 +1993,36 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise continue proper = filename[:-len(ending)] - if dictionaryEnd == 0: - dictionaryEnd = len(self.dictionary) - self.reusable = [0] * dictionaryEnd + self.reusable - self.dictionary = [None] * dictionaryEnd + self.dictionary + if self.dictionaryEnd == 0: + self.dictionaryEnd = len(self.dictionary) + self.reusable = [0] * self.dictionaryEnd + self.reusable + self.dictionary = [None] * self.dictionaryEnd + self.dictionary + + self.dictionaryEnd -= 1 + self.dictionary[self.dictionaryEnd] = proper - dictionaryEnd -= 1 - dictionary[dictionaryEnd] = proper prevCommon = min(len(previous), len(proper)) for i in range(0, prevCommon): if previous[i] != proper[i]: prevCommon = i break - previous = dictionary[dictionaryEnd] - reusable[dictionaryEnd] = prevCommon + previous = proper + self.reusable[self.dictionaryEnd] = prevCommon + #part = self.dictionary[self.dictionaryEnd : len(self.dictionary) - 1] + #part.sort() + #self.dictionary[self.dictionaryEnd : len(self.dictionary) - 1] = part + # + #index = len(self.dictionary) - 1 + #while index >= self.dictionaryEnd: + # proper = self.dictionary[index] + # prevCommon = min(len(previous), len(proper)) + # for i in range(0, prevCommon): + # if previous[i] != proper[i]: + # prevCommon = i + # break + # previous = proper + # self.reusable[self.dictionaryEnd] = prevCommon + # index -= 1; ''' @@ -2004,11 +2032,11 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise @return (words, distance):(list, int) A list the closest spellings and the weighted distance ''' def correct(self, used): - if len(used) < 127: + if len(used) > 127: return ([used], 0) - __correct(used) - return (seld.corrections, self.closestDistance) + self.__correct(used) + return (self.corrections, self.closestDistance) ''' @@ -2025,7 +2053,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise proper = None prevCommon = 0 - d = len(self.dictionary) + d = len(self.dictionary) - 1 while d > self.dictionaryEnd: d -= 1 proper = self.dictionary[d] @@ -2041,7 +2069,7 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise skip = min(prevLen, len(proper)) i = prevCommon - while i < skip: + while i < skip: for u in range(0, usedLen): if (used[u] == previous[i]) or (used[u] == proper[i]): skip = i @@ -2054,13 +2082,13 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise common = i break - distance = self.__distance(proper, skip, proper.length, used, common, usedLen) + distance = self.__distance(proper, skip, len(proper), used, common, usedLen) if self.closestDistance > distance: self.closestDistance = distance - corrections = [proper] + self.corrections = [proper] elif self.closestDistance == distance: - corrections.append(proper) + self.corrections.append(proper) previous = proper; if distance >= 0x7FFFFF00: @@ -2102,13 +2130,14 @@ class SpelloCorrecter(): # Naïvely and quickly proted and adapted from optimise if my[x] in self.weights: if p in self.weights[u]: cw = self.weights[u][p] + x += 1 myy[x] = min(cw + change, 1 + min(remove, add)) if best > myy[x]: best = myy[x] if best > self.closestDistance: - return 0x7FFFFFFF | y + return 0x7FFFFF00 | y my = myy return my[xn]