Question

Le profilage montre c'est le plus lent segment mon code pour un petit jeu de mots que j'ai écrit:

def distance(word1, word2):
    difference = 0
    for i in range(len(word1)):
        if word1[i] != word2[i]:
            difference += 1
    return difference

def getchildren(word, wordlist):
    return [ w for w in wordlist if distance(word, w) == 1 ]

Notes:

  • distance() est appelé plus de 5 millions de fois, dont la majorité est de GetChildren, qui est censé obtenir tous les mots dans la liste de mots qui diffèrent de word exactement 1 lettre.
  • est wordlist préfiltré pour avoir seulement des mots contenant le même nombre de lettres que word il est garanti que word1 et word2 ont le même nombre de caractères.
  • Je suis assez nouveau pour Python (commencé à apprendre il y a 3 jours) si des commentaires sur les conventions de nommage ou d'autres choses de style ont également apprécié.
  • pour wordlist prendre la liste de mots 12dict en utilisant le « 2+ 2lemma.txt » fichier

Résultats:

Merci tout le monde, avec des combinaisons de différentes suggestions que je reçu le programme en cours d'exécution deux fois plus vite maintenant (au-dessus des optimisations que j'ai fait moi-même avant de demander, donc 4 fois la vitesse augmente environ de ma mise en œuvre initiale)

Je l'ai testé avec 2 séries d'entrées que je vais appeler A et B

optimisation1: itérer sur indices de word1,2 ... à partir de

for i in range(len(word1)):
        if word1[i] != word2[i]:
            difference += 1
    return difference

itérer sur les paires de lettres en utilisant zip(word1, word2)

for x,y in zip (word1, word2):
        if x != y:
            difference += 1
    return difference

eu le temps d'exécution de 11,92 à 9,18 pour l'entrée A, et 79,30 à 74,59 pour l'entrée B

Optimization2: Ajout d'un procédé distinct pour diffère par un, en plus de la distance (procédé qui je encore nécessaires ailleurs pour les heuristiques A *)

def is_neighbors(word1,word2):
    different = False
    for c1,c2 in zip(word1,word2):
        if c1 != c2:
            if different:
                return False
            different = True
    return different

eu le temps d'exécution de 9,18 à 8,83 pour l'entrée A, et 74,59 à 70,14 pour l'entrée B

Optimization3: Grand gagnant ici était d'utiliser izip au lieu de zip

eu le temps d'exécution de 8,83 à 5,02 pour l'entrée A, et 70,14 à 41,69 pour l'entrée B

Je pourrais probablement faire mieux l'écrire dans une langue de niveau inférieur, mais je suis heureux avec ce pour l'instant. Merci à tous!

Modifier à nouveau: Plus de résultats En utilisant la méthode de Mark de vérifier le cas où la première lettre ne correspond pas à se vers le bas de 5,02 -> 3,59 et 41,69 -> 29,82

Miser sur cela et incorporant izip au lieu de range , j'ai fini avec ceci:

def is_neighbors(word1,word2):
    if word1[0] != word2[0]:
        return word1[1:] == word2[1:]
    different = False
    for x,y in izip(word1[1:],word2[1:]):
        if x != y:
            if different:
                return False
            different = True
    return different

Ce qui serra un peu plus, ce qui porte le temps vers le bas de 3,59 -> 3,38 et 29,82 -> 27,88

résultats encore plus!

Essayer la suggestion de Sumudu que je générer une liste de toutes les chaînes qui sont 1 lettre au large de « mot », puis vérifier pour voir ceux qui étaient dans la liste des mots , au lieu de la fonction is_neighbor J'ai fini avec ceci:

def one_letter_off_strings(word):
    import string
    dif_list = []
    for i in xrange(len(word)):
        dif_list.extend((word[:i] + l + word[i+1:] for l in string.ascii_lowercase if l != word[i]))
    return dif_list

def getchildren(word, wordlist):
    oneoff = one_letter_off_strings(word)
    return ( w for w in oneoff if w in wordlist )

Ce qui a fini par être plus lente (3,38 -> 3,74 et 27,88 -> 34,40) mais il semblait prometteur. Au début, je pensais que la partie que je avais besoin d'optimiser était « one_letter_off_strings », mais le profilage montré autrement et que la partie lente était en fait

( w for w in oneoff if w in wordlist )

Je pensais que s'il n'y aurait aucune différence si je suis passé « OneOff » et « liste de mots » et fait la comparaison de l'autre quand il m'a frappé que je cherchais l'intersection des 2 listes. Je remplacerai que set intersection sur les lettres :

return set(oneoff) & set(wordlist)

Bam! 3,74 -> 0,23 et 34,40 -> 2,25

Ceci est vraiment incroyable, la différence de vitesse totale de ma mise en œuvre naïve originale: 23,79 -> 0,23 et 180,07 -.> 2,25, donc environ 80 à 100 fois plus rapide que la mise en œuvre originale

Si quelqu'un est intéressé, j'ai fait de blog décrivant le programme et sa réponse . Il prétend que ce serait plus rapide en utilisant la méthode originale (à l'aide is_neighbor au lieu d'utiliser les jeux) si elle a été porté à C. J'ai essayé pendant 2 heures pour obtenir un module C je l'ai écrit pour construire et être liable sans beaucoup de succès après avoir essayé de suivez cette et ce exemple, et il semble que le processus est un peu différent dans Windows? Je ne sais pas, mais j'ai renoncé à cela. Quoi qu'il en soit, voici le code complet du programme, et le fichier texte proviennent de la 12dict liste de mots en utilisant le fichier "2 + 2lemma.txt". Désolé si le code est, c'était un peu en désordre juste quelque chose que je piraté ensemble. Aussi j'oublié de dépouiller des virgules de la liste de mots de sorte que est en fait un bug que vous pouvez laisser dans pour le bien de la même comparaison ou le corriger en ajoutant une virgule à la liste des caractères dans cleanentries.

from itertools import izip
def unique(seq):  
    seen = {} 
    result = [] 
    for item in seq: 
        if item in seen:
            continue 
        seen[item] = 1 
        result.append(item) 
    return result
def cleanentries(li):
    pass
    return unique( [w.strip('[]') for w in li if w != "->"] )
def distance(word1, word2):
    difference = 0
    for x,y in izip (word1, word2):
        if x != y:
            difference += 1
    return difference
def is_neighbors(word1,word2):
    if word1[0] != word2[0]:
        return word1[1:] == word2[1:]
    different = False
    for x,y in izip(word1[1:],word2[1:]):
        if x != y:
            if different:
                return False
            different = True
    return different
def one_letter_off_strings(word):
    import string
    dif_list = []
    for i in xrange(len(word)):
        dif_list.extend((word[:i] + l + word[i+1:] for l in string.ascii_lowercase if l != word[i]))
    return dif_list

def getchildren(word, wordlist):
    oneoff = one_letter_off_strings(word)
    return set(oneoff) & set(wordlist)
def AStar(start, goal, wordlist):
    import Queue
    closedset = []
    openset = [start]
    pqueue = Queue.PriorityQueue(0)
    g_score = {start:0}         #Distance from start along optimal path.
    h_score = {start:distance(start, goal)}
    f_score = {start:h_score[start]}
    pqueue.put((f_score[start], start))
    parent_dict = {}
    while len(openset) > 0:
        x = pqueue.get(False)[1]
        if x == goal:
            return reconstruct_path(parent_dict,goal)
        openset.remove(x)
        closedset.append(x)
        sortedOpen = [(f_score[w], w, g_score[w], h_score[w]) for w in openset]
        sortedOpen.sort()
        for y in getchildren(x, wordlist):
            if y in closedset:
                continue
            temp_g_score = g_score[x] + 1
            temp_is_better = False
            appended = False
            if (not y in openset): 
                openset.append(y)
                appended = True
                h_score[y] = distance(y, goal)
                temp_is_better = True
            elif temp_g_score < g_score[y] :
                temp_is_better = True
            else :
                pass
            if temp_is_better:
                parent_dict[y] = x
                g_score[y] = temp_g_score
                f_score[y] = g_score[y] + h_score[y]
                if appended :
                    pqueue.put((f_score[y], y))
    return None


def reconstruct_path(parent_dict,node):
     if node in parent_dict.keys():
         p = reconstruct_path(parent_dict,parent_dict[node])
         p.append(node)
         return p
     else:
         return []        

wordfile = open("2+2lemma.txt")
wordlist = cleanentries(wordfile.read().split())
wordfile.close()
words = []
while True:
    userentry = raw_input("Hello, enter the 2 words to play with separated by a space:\n ")
    words = [w.lower() for w in userentry.split()]
    if(len(words) == 2 and len(words[0]) == len(words[1])):
        break
print "You selected %s and %s as your words" % (words[0], words[1])
wordlist = [ w for w in wordlist if len(words[0]) == len(w)]
answer = AStar(words[0], words[1], wordlist)
if answer != None:
    print "Minimum number of steps is %s" % (len(answer))
    reply = raw_input("Would you like the answer(y/n)? ")
    if(reply.lower() == "y"):
        answer.insert(0, words[0])
        print "\n".join(answer)
    else:
        print "Good luck!"
else:
    print "Sorry, there's no answer to yours"
reply = raw_input("Press enter to exit")

J'ai quitté la méthode is_neighbors, même si ce n'est pas utilisé. Ceci est la méthode qui est proposée à être porté à C. Pour l'utiliser, il suffit de remplacer GetChildren avec ceci:

def getchildren(word, wordlist):
    return ( w for w in wordlist if is_neighbors(word, w))

Quant à le faire fonctionner en tant que module C Je n'ai pas jusque-là, mais ce que je suis venu avec:

#include "Python.h"

static PyObject *
py_is_neighbor(PyObject *self, Pyobject *args)
{
    int length;
    const char *word1, *word2;
    if (!PyArg_ParseTuple(args, "ss", &word1, &word2, &length))
        return NULL;

    int i;
    int different = 0;
    for (i =0; i < length; i++)
    {
        if (*(word1 + i) != *(word2 + i))
        {
            if (different)
            {
                return Py_BuildValue("i", different);
            }
            different = 1;
        }
    }
    return Py_BuildValue("i", different);
}

PyMethodDef methods[] = {
    {"isneighbor", py_is_neighbor, METH_VARARGS, "Returns whether words are neighbors"},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initIsNeighbor(void)
{
    Py_InitModule("isneighbor", methods);
}

Je PROFILES cela en utilisant:

  

python -m cprofile "Wordgame.py"

Et le temps enregistré était le temps total de l'appel de méthode AStar. L'ensemble d'entrée rapide était « poètes de vers » et l'ensemble d'entrée était longue « vers » poètes. Timings varie évidemment entre les machines différentes, donc si quelqu'un ne finissent par essayer cette comparaison des résultats donnent du programme tel qu'il est, ainsi qu'avec le module C.

Était-ce utile?

La solution

Si votre liste de mots est très longue, pourrait-il être plus efficace pour générer toutes les 1-lettre-différences de « mot » possibles, puis vérifiez ceux qui sont dans la liste? Je ne sais pas Python, mais il devrait y avoir une structure de données appropriée pour la liste de mots permettant lookups log-temps.

Je suggère cela parce que si vos mots sont des longueurs raisonnables (~ 10 lettres), alors vous ne serez cherchez 250 mots potentiels, ce qui est probablement plus rapide si votre liste de mots est plus grand que quelques centaines de mots.

Autres conseils

Votre fonction distance calcule la distance totale, lorsque vous vraiment ne vous préoccupez distance = 1. La majorité des cas, vous saurez qu'il est> 1 en quelques caractères, vous pouvez donc revenir tôt et économiser beaucoup de temps.

Au-delà, il pourrait y avoir un meilleur algorithme, mais je ne peux pas y penser.

Modifier. Une autre idée

Vous pouvez faire 2 cas, selon que le premier caractère correspond. Si elle ne correspond pas, le reste du mot doit correspondre exactement, et vous pouvez tester pour cela d'un seul coup. Dans le cas contraire, faites-le de façon similaire à ce que vous faisiez. Vous pouvez même le faire récursive, mais je ne pense pas que ce serait plus rapide.

def DifferentByOne(word1, word2):
    if word1[0] != word2[0]:
        return word1[1:] == word2[1:]
    same = True
    for i in range(1, len(word1)):
        if word1[i] != word2[i]:
            if same:
                same = False
            else:
                return False
    return not same

Edit 2: J'ai supprimé le contrôle pour voir si les chaînes sont de la même longueur, puisque vous dites qu'il est redondant. Exécution tests de Ryan sur mon propre code et sur la fonction is_neighbors fourni par MizardX , je reçois le texte suivant :

  • distance d'origine (): 3,7 secondes
  • Mon DifferentByOne (): 1,1 secondes
  • is_neighbors de MizardX (): 3,7 secondes

Modifier 3: (probablement entrer dans le territoire wiki communautaire, mais ...)

Essayer votre définition finale de is_neighbors () avec IZIP au lieu de zip. 2.9 secondes

Voici ma dernière version, qui encore temps à 1.1 secondes:

def DifferentByOne(word1, word2):
    if word1[0] != word2[0]:
        return word1[1:] == word2[1:]
    different = False
    for i in range(1, len(word1)):
        if word1[i] != word2[i]:
            if different:
                return False
            different = True
    return different
from itertools import izip

def is_neighbors(word1,word2):
    different = False
    for c1,c2 in izip(word1,word2):
        if c1 != c2:
            if different:
                return False
            different = True
    return different

Ou peut-être en alignant le code izip:

def is_neighbors(word1,word2):
    different = False
    next1 = iter(word1).next
    next2 = iter(word2).next
    try:
        while 1:
            if next1() != next2():
                if different:
                    return False
                different = True
    except StopIteration:
        pass
    return different

Et getchildren réécrite:

def iterchildren(word, wordlist):
    return ( w for w in wordlist if is_neighbors(word, w) )
  • izip(a,b) renvoie un itérateur sur des paires de valeurs de a et b.
  • zip(a,b) renvoie une liste de paires de a et b.

Les gens vont principalement à ce sujet en essayant d'écrire une fonction plus rapide, mais il pourrait y avoir une autre façon ..

  

"distance" est appelé plus de 5 millions de fois

Pourquoi est-ce? Peut-être une meilleure façon d'optimiser est d'essayer de réduire le nombre d'appels à distance, plutôt que de se raser millisecondes de temps d'exécution de distance's. Il est impossible de dire sans voir le script complet, mais l'optimisation d'une fonction spécifique est généralement inutile.

Si cela est impossible, vous pourriez peut-être écrire comme un module C?

Comment est souvent la fonction de distance appelée avec les mêmes arguments? Un simple à mettre en œuvre l'optimisation serait d'utiliser memoization .

Vous pouvez probablement aussi créer une sorte de dictionnaire avec frozensets de lettres et des listes de mots qui diffèrent par un et rechercher des valeurs dans ce. Cette structure de données pourrait soit être stocké et chargé par cornichon ou généré à partir de zéro au démarrage.

Le court-circuitage l'évaluation ne vous donnera des gains si les mots que vous utilisez sont très longues, puisque l'algorithme de distance de Hamming que vous utilisez est essentiellement O (n) où n est la longueur de mot.

Je l'ai fait quelques expériences avec timeit pour certaines approches alternatives qui peuvent être illustrative.

Résultats TimeIt

Votre solution

d = """\
def distance(word1, word2):
    difference = 0
    for i in range(len(word1)):
        if word1[i] != word2[i]:
            difference += 1
    return difference
"""
t1 = timeit.Timer('distance("hello", "belko")', d)
print t1.timeit() # prints 6.502113536776391

One Liner

d = """\
from itertools import izip
def hamdist(s1, s2):
    return sum(ch1 != ch2 for ch1, ch2 in izip(s1,s2))
"""
t2 = timeit.Timer('hamdist("hello", "belko")', d)
print t2.timeit() # prints 10.985101179

Raccourci évaluation

d = """\
def distance_is_one(word1, word2):
    diff = 0
    for i in xrange(len(word1)):
        if word1[i] != word2[i]:
            diff += 1
        if diff > 1:
            return False
    return diff == 1
"""
t3 = timeit.Timer('hamdist("hello", "belko")', d)
print t2.timeit() # prints 6.63337

Eh bien, vous pouvez commencer par avoir votre rupture de boucle si la différence est 2 ou plus.

Vous pouvez également modifier

for i in range(len(word1)):

à

for i in xrange(len(word1)):

Parce que xrange génère des séquences sur la demande au lieu de générer l'ensemble des nombres à la fois.

Vous pouvez également essayer de comparer les longueurs de mots qui serait plus rapide. Notez également que votre code ne fonctionne pas si mot1 est supérieure à word2

Il n'y a pas beaucoup d'autres choses que vous pouvez faire algorithmiquement après cela, ce qui est de dire que vous aurez probablement plus d'un portage que par speedup section C.

Edit 2

Tenter d'expliquer mon analyse de l'algorithme de Sumudu par rapport aux différences de vérification CHAR par char.

Lorsque vous avez un mot de longueur L, le nombre de mots « diffère par un » vous générerez sera 25L. Nous savons que des mises en œuvre de jeux sur les ordinateurs modernes, que la vitesse de recherche est d'environ log (n) base 2 , où n est le nombre d'éléments à rechercher.

Après avoir constaté que la plupart des 5 millions de mots que vous testez contre est pas dans l'ensemble, la plupart du temps, vous serez en traversant l'ensemble, ce qui signifie qu'il devient vraiment journal (25L) au lieu de seulement log (25L) / 2. (Et ceci suppose le meilleur des cas pour les jeux que la comparaison par chaîne chaîne est équivalente à comparer par char omble chevalier)

Maintenant, nous jeter un oeil à la complexité de temps pour déterminer un « diffère par un ». Si nous supposons que vous devez vérifier le mot entier, le nombre d'opérations par mot devient L . Nous savons que la plupart des mots diffèrent par 2 très rapidement. Et sachant que la plupart des préfixes prennent une petite partie du mot, on peut logiquement supposer que vous casserez la plupart du temps par L / 2 , soit la moitié du mot (ce qui est une estimation prudente) .

Alors maintenant, nous traçons les complexités de temps des deux recherches, L / 2 et log (25L), et en gardant à l'esprit que cela même chaîne envisage correspondant à la même vitesse que correspondant char (très en faveur des ensembles). Vous avez le journal de l'équation (25 * L)> L / 2, qui peut être simplifiée jusqu'à log (25)> L / 2 - log (L). Comme vous pouvez le voir sur le graphique, il devrait être plus rapide d'utiliser l'algorithme de correspondance char jusqu'à très un grand nombre de L.

text alt

  

En outre, je ne sais pas si vous comptez briser la différence de 2 ou plus dans votre optimisation, mais de la réponse de Mark I déjà pause sur une différence de 2 ou plus, et en fait, si la différence de la première lettre, il se casse après la première lettre, et même en dépit de toutes ces optimisations, le passage à l'aide d'ensembles juste les sauter hors de l'eau. Je suis intéressé à essayer votre idée si

Je suis la première personne dans cette question de proposer la rupture sur une différence de 2 ou plus. La chose est, que l'idée de marque de découpage en tranches de chaîne (si word1 [0] = word2 [0]: retour word1 [1:] == word2 [1:]) est en train de mettre tout simplement ce que nous faisons en C. Comment avez-vous penser word1 [1:] == word2 [1:] est calculée? De la même façon que nous faisons.

  

Je lis votre explication quelques fois, mais je ne suis pas tout à fait cela, voulez-vous nous expliquer un peu plus en profondeur? Aussi je ne suis pas terriblement familier avec le C et je travaille dans les langues de haut niveau au cours des dernières années (le plus proche a été l'apprentissage C ++ dans le lycée il y a 6 ans

En ce qui concerne la production du code C, je suis un peu occupé. Je suis sûr que vous serez en mesure de le faire depuis que vous avez écrit en C avant. Vous pouvez également essayer C #, ce qui a probablement des caractéristiques de performance similaires.

Plus Explication

Voici une explication plus approfondie à Davy8

def getchildren(word, wordlist):
    oneoff = one_letter_off_strings(word)
    return set(oneoff) & set(wordlist)

Votre fonction one_letter_off_strings va créer un ensemble de chaînes 25L (où L est le nombre de lettres).

CreAting un ensemble de la liste de mots va créer un ensemble de chaînes D (où D est la longueur de votre dictionnaire). En créant une intersection de cela, vous DOIT itérer sur chaque OneOff et voir si elle existe dans wordlist .

La complexité de temps pour cette opération est détaillée ci-dessus. Cette opération est moins efficace que la comparaison du mot que vous voulez avec chaque mot wordlist . La méthode de sumudu est une optimisation en C plutôt que dans l'algorithme.

Plus Explication 2

  

Il y a seulement 4500 mots au total (parce que la liste de mots est pré-filtré pour 5 mots de lettre avant même d'être passé à l'algorithme), étant entrecoupés de 125 mots-off d'une lettre. Il semble que vous disiez intersection est log (plus petit) ou dans le journal otherwords (125, 2). Comparez cela à nouveau en supposant que vous avez dit, où l'on compare une pause de mot dans L / 2 lettres, je vais arrondir cela à 2, même si un mot de 5 lettres, il est plus susceptible d'être 3. Cette comparaison se fait 4500 fois, si 9000. log (125,2) est d'environ 6,9, et le journal (4500,2) est d'environ 12. laissez-moi savoir si je mal interprété vos chiffres.

Pour créer l'intersection de 125 mots-off d'une lettre avec un dictionnaire de 4500, vous devez faire 125 * 4500 comparaisons. Ceci est journalise pas (125,2). Il est au mieux 125 * log (4500, 2) en supposant que le dictionnaire est prétrié. Il n'y a pas de raccourci magique pour les ensembles. Vous faites également une chaîne par chaîne au lieu de char par comparaison char ici.

Pour une telle fonction simple qui a une si grande implication de la performance, je serais probablement faire une bibliothèque C et l'appeler à l'aide ctypes . L'un des fondateurs de reddit réclamations qu'ils ont fait le site en utilisant 2x plus vite cette technique.

Vous pouvez également utiliser psyco sur cette fonction, mais méfiez-vous qu'il peut manger beaucoup de mémoire .

Je ne sais pas si cela va affecter de manière significative votre vitesse, mais vous pouvez commencer en tournant la compréhension de la liste dans une expression de générateur. Il est encore itérables donc il ne devrait pas être très différente dans l'usage:

def getchildren(word, wordlist):
    return [ w for w in wordlist if distance(word, w) == 1 ]

à

def getchildren(word, wordlist):
    return ( w for w in wordlist if distance(word, w) == 1 )

Le principal problème serait qu'une compréhension de la liste ne se construire en mémoire et prendre un peu d'espace, alors que le générateur va créer votre liste à la volée donc il n'y a pas besoin de stocker l'ensemble.

En outre, à la suite sur la réponse inconnue, cela peut être une manière plus « pythonique » de la distance d'écriture ():

def distance(word1, word2):
    difference = 0
    for x,y in zip (word1, word2):
        if x == y:
            difference += 1
    return difference

Mais il est déroutant ce INTENTIONNELLE quand len (word1)! = Len (mot2), dans le cas de zip ne retournera autant de caractères que le mot le plus court. (Ce qui pourrait se révéler une optimisation ...)

Essayez ceci:

def distance(word1, word2):
  return sum([not c1 == c2 for c1, c2 in zip(word1,word2)])

En outre, avez-vous un lien vers votre jeu? J'aime être détruit par des jeux de mots

La première chose à se produire à moi:

from operator import ne

def distance(word1, word2):
    return sum(map(ne, word1, word2))

qui a une bonne chance d'aller plus vite que d'autres fonctions de gens ont posté, car il n'a pas de boucles interprétées, appelle simplement à des primitives Python. Et il est assez court que vous pourriez inline raisonnablement dans l'appelant.

Pour votre problème de niveau supérieur, je regarde dans les structures de données mis au point pour la recherche de similarité dans les espaces métriques, par exemple ce papier ou

pour cet extrait:

for x,y in zip (word1, word2):
    if x != y:
        difference += 1
return difference

j'utiliser celui-ci:

return sum(1 for i in xrange(len(word1)) if word1[i] == word2[i])

le même schéma suivrait tout autour du code fourni ...

Tout le monde mis au point juste sur le calcul de la distance explicite sans rien faire construire les candidats à distance 1. Vous pouvez améliorer en utilisant un bien connu des données structure appelée Trie pour fusionner les implicite avec la tâche de générer tous les mots voisins à distance 1 . A Trie est une liste chaînée où chaque noeud représente une lettre, et le champ « suivant » est un dict jusqu'à 26 entrées, pointant vers le nœud suivant.

Voici le pseudocode: marcher sur la Trie itérativement pour votre parole donnée; à chaque noeud ajouter toutes les distances et la distance 0-1 voisins les résultats; garder un compteur de distance et de décrémenter. Vous n'avez pas besoin récursion, juste une fonction de recherche qui prend un argument entier distance_so_far supplémentaire.

Un compromis mineure de vitesse supplémentaire pour l'augmentation de l'espace de O (N) peut être obtenu par la construction d'Essais séparés pour longueur 3, 4-longueur, la longueur des mots-5 etc..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top