à l'arrière d'un calendrier de bloc, j'ai trouvé l'énigme suivante:
Combien de mots anglais communs de 4 lettres ou plus pouvez-vous faire des lettres du mot "manuel" (chaque lettre ne peut être utilisée qu'une seule fois). P> blockQuote>
Ma première solution que j'ai proposée était: p>
xxx pré> ceci donne le résultat
défini (["Tote", "goûte", 'Text', 'Boot', 'A pris', 'Toot', 'Book', 'TOKE', 'TOKE', 'BETOOK']) COOK ']) Mais a pris plus de 7 minutes sur ma machine. P>
Ma prochaine itération était: p>
xxx pré> qui retourne une réponse presque immédiatement mais donnait comme réponse:
['book', 'goûte', 'toot', 'toot' ] code> p>
Quelle est la solution la plus rapide, correcte et la plus pythonique à ce problème? p>
( edit strud>: ajouté ma solution de permutations antérieure et sa Différente sortie). P> P>
6 Réponses :
Il y a un générateur édition # 1: Oh! Il dit "4 ou plus";) oublie ce que j'ai dit! P> Edit # 2: Ceci est la deuxième version que j'ai proposée: p> itheroTools.permutations code> avec lequel vous pouvez rassembler toutes les permutations d'une séquence avec une longueur spécifiée. Cela facilite la tâche:
LETTERS = set('textbook')
with open('/usr/share/dict/words') as f:
WORDS = filter(lambda x: len(x) >= 4, [l.strip() for l in f])
matching = filter(lambda x: set(x).issubset(LETTERS) and all([x.count(c) == 1 for c in x]), WORDS)
print len(matching)
Je n'ai pas creusé cela beaucoup, mais ce code me donne des résultats différents et prend plus de 20 fois plus longtemps pour exécuter.
Veuillez également noter que ma version se souciait de chaque mot correspondant contenant chaque lettre une seule fois.
Votre deuxième version ne renvoie que des mots dans lesquels chaque lettre est différente (dans ce cas: TOKE code>), mais
Tote code>,
oboe code>,
texte < / code>,
boot code>,
a pris code>,
toot code>,
book code> et
betook code> sont Aussi des solutions valides.
Citation: "Chaque lettre ne peut être utilisée qu'une seule fois". ;)
@Gandaro bien mais il y a deux t code> s dans le manuel et chacun peut être utilisé une fois;)
On dirige-t-il?
>>> print matches set(['textbook', 'keto', 'obex', 'tote', 'oboe', 'text', 'boot', 'toto', 'took', 'koto', 'bott', 'tobe', 'boke', 'toot', 'book', 'bote', 'otto', 'toke', 'toko', 'oket'])
Créez l'ensemble de la puissance, puis vérifiez si le mot dictionnaire est dans l'ensemble (l'ordre des lettres n'a pas d'importance):
powerset = lambda x: powerset(x[1:]) + [x[:1] + y for y in powerset(x[1:])] if x else [x] pw = map(lambda x: sorted(x), powerset(given_word)) filter(lambda x: sorted(x) in pw, words)
Cool, je n'avais pas déjà entendu parler du concept de Powerset. Petit Nitpick, votre mise en œuvre actuelle ne filtre pas les mots de Lengt 4 ou plus.
Je pensais partager cette astuce légèrement intéressante bien que cela prend un bon plus de code que le reste et n'est pas vraiment "Pythonic". Cela prendra un bon plus de code que les autres solutions mais devraient être assez rapides si je regarde le timing des autres besoin.
Nous faisons un peu de prétraitement pour accélérer les calculs. L'approche de base est la suivante: nous attribuons chaque lettre de l'alphabet un nombre premier. Par exemple. A = 2, B = 3, et ainsi de suite. Nous calculons ensuite un hash pour chaque mot dans l'alphabet qui est simplement le produit des représentations premières de chaque personnage dans le mot. Nous stockons ensuite chaque mot dans un dictionnaire indexé par le hachage. P>
Maintenant si nous voulons savoir quels mots sont équivalents à dire Voici le code Avec une légère optimisation que, dans notre cas, nous n'avions à vous inquiéter qu'aux personnages apparaissant également dans le mot donné, ce qui signifie que nous pouvons obtenir avec une table de choix beaucoup plus petite que sinon (l'optimisation évidente serait de ne céder que des caractères apparaissant dans le Word une valeur du tout - il était assez rapide de toute façon, je ne me suis donc pas dérangé et de cette façon, nous ne pouvions pas traiter une seule fois et le faire pour plusieurs mots). L'algorithme de choix est utile assez souvent pour que vous puissiez en avoir une vous-même;) p> fonctionne sur ma liste de mots Ubuntu (mots de 98k) plutôt rapidement, mais pas ce que je Appelez Pythonic car il s'agit essentiellement d'un port d'un algorithme C ++. Utile si vous voulez comparer plus d'un mot de cette façon .. p> p> manuel code> nous ne devons calculer que le même hachage pour le mot et le regarder dans notre dictionnaire. Habituellement (par exemple en C ++), nous devions nous inquiéter des débordements, mais en Python, il est encore plus simple que cela: chaque mot de la liste avec le même index contiendra exactement les mêmes caractères. P>
Explication et code très clairs, merci. Votre code a également été renvoyé les mots corrects kobe code>,
otto code> et
too code> et maintenant je me demande pourquoi ma solution de permutations n'a pas présenté à celles-ci.
@Biogeek, vous ne gérez pas de majuscules / minuscules de manière équivalente.
Ce qui suit vérifie simplement chaque mot dans le dictionnaire pour voir si elle est de la longueur appropriée, puis s'il s'agit d'une permutation de «manuel». J'ai emprunté le chèque de permutation de Vérification si deux chaînes sont des permutations les unes des autres dans Python mais a légèrement changé.
given_word = 'textbook' with open('/usr/share/dict/words', 'r') as f: words = [s.strip() for s in f.readlines()] matches = [] for word in words: if word != given_word and 4 <= len(word) <= len(given_word): if all(word.count(char) <= given_word.count(char) for char in word): matches.append(word) print sorted(matches)
Pas de Lambda, pas de carte, aucun filtre: enfin, Ceci b> est pythonique. Bien que l'utilisation des compréhensions de générateur au lieu d'une compréhension de la liste et une boucle d'accumulation devait être plus efficace.
@Evpok Je peux comprendre (et accepter) Pourquoi la carte et le filtre ne seraient pas nécessaires avec des compromies de la liste, mais je ne vois pas pourquoi créer des dizaines de mini-fonctions serait particulièrement pythonique au lieu d'utiliser des Lambdas?
Voir Réponse de Guido : "[...] une fois que la carte (), filtre () et réduire () sont partis, il n'y a pas beaucoup d'endroits où vous avez vraiment besoin d'écrire des fonctions locales très courtes [...] ». Pourquoi auriez-vous besoin de Lambdas si vous utilisez des compréhensions?
@Evpok pas pour les générateurs évidemment, mais pour beaucoup d'autres situations. Passer des fonctions triviales (par exemple des comparateurs) est souvent utile (fondamentalement, tout type de rappel) peut également être une caractéristique immensément utile de mon expérience. Mais dépend certainement du style de codage.
@Voo a accepté des comparateurs, j'adore vraiment le style de codage fonctionnel et je abuse régulièrement functools.Partial code>. Mais Python n'était pas censé être une langue fonctionnelle.
@Evpok: Un peu hors sujet ici, mais s'il vous plaît, seriez-vous assez gentille pour considérer ce post ? Merci d'avance.
Les permutations sont très grandes pour des mots plus longs. Essayez contrevolutaire em> par exemple. Je filtrerais la dicte pour les mots de 4 à Len (mot) (8 pour manuel).
Ensuite, je filtrerais avec une expression régulière "hautbois" .matches ("[manuel] +"). P> Les mots restants, je trierais et comparez-les avec une version triée de votre mot, ("beoo", "bekoottx") avec un saut à l'index suivant d'un caractère correspondant, pour trouver des numéros de déséquilibre. des caractères: p> puisque je ne parle pas python, je laisse la mise en œuvre comme un exercice au public. p> p>
Supprimé ma réponse avant de voir votre commentaire, pour la même raison que vous avez souligné. Merci
Vous pouvez résoudre celui-ci extrêmement efficace avec un pré-traitement de la plume et l'attribution de chaque lettre une représentation principale. Je vais écrire une solution si j'ai le temps plus tard.
@Voo, je vais attendre avec le choix d'une réponse correcte jusqu'à ce que vous ayez soumis votre solution. Je suis impatient d'y être.
Cette question semble être hors sujets car il s'agit de puzzles de programmation ( codegolf.stackexchange.com )