Ce défi consiste à trouver la plus longue chaîne de mots anglais où les 3 premiers caractères du mot suivant correspondent aux 3 derniers caractères du dernier mot. Vous utiliserez un dictionnaire commun disponible dans les distributions Linux qui peut être téléchargé ici:
https://www.dropbox.com/s/8tyzf94ps37tzp7/words?dl=0
qui a 99171 mots anglais. Si votre Linux local /usr/share/dict/words
est le même fichier (a md5sum == cbbcded3dc3b61ad50c4e36f79c37084), vous pouvez l'utiliser.
Les mots ne peuvent être utilisés qu'une seule fois dans une réponse.
EDIT: les lettres doivent correspondre exactement, y compris les majuscules / minuscules, les apostrophes et les accents.
Un exemple de réponse valide est:
idea deadpan panoramic micra craftsman mantra traffic fiche
qui donnerait 8.
La réponse avec la chaîne de mots valide la plus longue sera la gagnante. En cas d'égalité, la première réponse l'emportera. Votre réponse doit énumérer la chaîne de mots que vous avez trouvée et (bien sûr) le programme que vous avez écrit pour le faire.
la source
Réponses:
Java, heuristique privilégiant le sommet qui induit le plus grand graphe:
1825 18551873Le code ci-dessous s'exécute en moins de 10 minutes et trouve le chemin suivant:
Idées fondamentales
Dans Approximation des chemins et cycles dirigés les plus longs , Bjorklund, Husfeldt et Khanna, Lecture Notes in Computer Science (2004), 222-233, les auteurs proposent que dans les graphiques à expansion clairsemée, un long chemin puisse être trouvé par une recherche gourmande qui sélectionne à chaque pas le voisin de la queue actuelle du chemin qui s'étend sur le plus grand sous-graphe de G ', où G' est le graphique d'origine avec les sommets du chemin actuel supprimés. Je ne suis pas sûr d'un bon moyen de tester si un graphe est un graphe expanseur, mais nous avons certainement affaire à un graphe clairsemé, et puisque son noyau est d'environ 20000 sommets et qu'il a un diamètre de seulement 15, il doit avoir une bonne propriétés d'expansion. J'adopte donc cette heuristique gourmande.
Étant donné un graphique
G(V, E)
, nous pouvons trouver combien de sommets sont accessibles à partir de chaque sommet en utilisant Floyd-Warshall dans leTheta(V^3)
temps, ou en utilisant l'algorithme de Johnson dans leTheta(V^2 lg V + VE)
temps. Cependant, je sais que nous avons affaire à un graphique qui a un très grand composant fortement connecté (SCC), alors j'adopte une approche différente. Si nous identifions les SCC en utilisant l'algorithme de Tarjan, nous obtenons également un tri topologique pour le graphique compresséG_c(V_c, E_c)
, qui sera beaucoup plus petit, dans leO(E)
temps. Puisqu'ilG_c
s'agit d'un DAG, nous pouvons calculer l'accessibilitéG_c
dans leO(V_c^2 + E_c)
temps. (J'ai découvert par la suite que cela est indiqué dans l'exercice 26-2.8 du CLR ).Étant donné que le facteur dominant dans le temps d'exécution est
E
, je l'optimise en insérant des nœuds factices pour les préfixes / suffixes. Donc plutôt que 151 * 64 = 9664 bords des mots finissant -res aux mots commençant res, j'ai 151 bords des mots se terminant par -res à # res # et 64 bords de # res # aux mots commençant par res- .Et enfin, comme chaque recherche prend environ 4 minutes sur mon ancien PC, j'essaie de combiner les résultats avec les longs trajets précédents. C'est beaucoup plus rapide et c'est ma meilleure solution actuelle.
Code
org/cheddarmonk/math/graph/Graph.java
:org/cheddarmonk/math/graph/MutableGraph.java
:org/cheddarmonk/math/graph/StronglyConnectedComponents.java
:org/cheddarmonk/ppcg/PPCG.java
:la source
Rubis, 1701
"Del" -> "ersatz's"
( séquence complète )Essayer de trouver la solution optimale s'est avéré trop coûteux en temps. Alors pourquoi ne pas choisir des échantillons aléatoires, mettre en cache ce que nous pouvons et espérer le meilleur?
Un premier
Hash
est construit qui mappe les préfixes aux mondes complets en commençant par ce préfixe (par exemple"the" => ["the", "them", "their", ...]
). Ensuite, pour chaque mot de la liste, la méthodesequence
est appelée. Il obtient les mots qui pourraient éventuellement découler duHash
, en prend un échantillon100
et s'appelle récursivement. Le plus long est pris et affiché fièrement. Le germe du RNG (Random::DEFAULT
) et la longueur de la séquence sont également affichés.J'ai dû exécuter le programme plusieurs fois pour obtenir un bon résultat. Ce résultat particulier a été généré avec des graines
328678850348335483228838046308296635426328678850348335483228838046308296635426
.Scénario
la source
0.0996
quelques secondes.Résultat:
16311662 motsVous pouvez retrouver toute la séquence ici: http://pastebin.com/TfAvhP9X
Je n'ai pas le code source complet. J'essayais différentes approches. Mais voici quelques extraits de code, qui devraient pouvoir générer une séquence d'environ la même longueur. Désolé, ce n'est pas très beau.
Code (Python):
D'abord un prétraitement des données.
J'ai ensuite défini une fonction récursive (Depth first search).
Bien sûr, cela prend trop de temps. Mais après un certain temps, il a trouvé une séquence de 1090 éléments, et je me suis arrêté.
La prochaine chose à faire est une recherche locale. Pour chacun des deux voisins n1, n2 dans la séquence, j'essaie de trouver une séquence commençant à n1 et se terminant à n2. Si une telle séquence existe, je l'insère.
Bien sûr, j'ai également dû arrêter le programme manuellement.
la source
PHP,
17421795J'ai dérangé avec PHP à ce sujet. L'astuce consiste à éliminer la liste aux environ 20k qui sont réellement valides, et à jeter le reste. Mon programme le fait de manière itérative (certains mots qu'il jette lors de la première itération signifient que d'autres ne sont plus valides) au début.
Mon code est horrible, il utilise un certain nombre de variables globales, il utilise beaucoup trop de mémoire (il conserve une copie de la table de préfixes entière pour chaque itération) et il a fallu littéralement des jours pour trouver mon meilleur actuel, mais il gère toujours gagner - pour l'instant. Cela commence assez rapidement mais devient plus lent et plus lent au fil du temps.
Une amélioration évidente consisterait à utiliser un mot orphelin pour le début et la fin.
Quoi qu'il en soit, je ne sais vraiment pas pourquoi ma liste pastebin a été déplacée dans un commentaire ici, elle est de retour sous forme de lien vers pastebin car j'ai maintenant inclus mon code.
http://pastebin.com/Mzs0XwjV
la source
Python:
1702-1704- 1733 motsJ'ai utilisé un dict pour mapper tous les préfixes à tous les mots, comme
Modifier une petite amélioration: supprimer tous les
useless
mots au début, si leurs suffixes ne sont pas dans la liste des préfixes (ce serait évidemment un mot de fin)Ensuite, prenez un mot dans la liste et parcourez la carte de préfixe comme un arbre Node
Le programme a besoin d'un certain nombre de mots pour savoir quand s'arrêter, peut être trouvé comme
1733
dans la méthodecheckForNextWord̀
Le programme a besoin du chemin du fichier comme argument
Pas très pythonique mais j'ai essayé.
Il a fallu moins de 2 minutes pour calculer cette séquence: sortie complète :
la source
Score:
2495001001Voici mon code:
Modifier: 1001:
http://pastebin.com/yN0eXKZm
Modifier: 500:
la source
Mathematica
14821655Quelque chose pour commencer ...
Les liens sont les préfixes et suffixes d'intersection des mots.
Les bords sont tous les liens dirigés d'un mot à d'autres mots:
Trouvez un chemin entre "raccommoder" et "zeste".
Résultat (1655 mots)
la source
Python, 90
Je nettoie d'abord la liste manuellement en supprimant tout
cela me coûte au plus 2 points car ces mots ne peuvent être qu'au début ou à la fin de la chaîne, mais cela réduit la liste de mots de 1/3 et je n'ai pas à gérer unicode.
Ensuite, je construis une liste de tous les pré- et suffixes, trouve le chevauchement et jette tous les mots à moins que le pré- et le suffixe ne soient dans l'ensemble de chevauchement. Encore une fois, cela réduit au maximum 2 points de mon score maximal réalisable, mais cela réduit la liste de mots à un tiers de la taille d'origine (essayez d'exécuter votre algorithme sur la liste courte pour une accélération possible) et les mots restants sont hautement connectés (sauf 3 -les mots lettres qui ne sont liés qu’à eux-mêmes). En fait, presque n'importe quel mot peut être atteint à partir de n'importe quel autre mot par un chemin avec une moyenne de 4 bords.
Je stocke le nombre de liens dans une matrice d'adjacence qui simplifie toutes les opérations et me permet de faire des trucs sympas comme regarder n étapes en avant ou compter des cycles ... au moins en théorie, car il faut environ 15 secondes pour cadrer la matrice que je ne fais pas réellement ceci pendant la recherche. Au lieu de cela, je commence par un préfixe aléatoire et je me promène au hasard, soit en choisissant une fin uniformément, en favorisant ceux qui se produisent souvent (comme «-ing») ou ceux qui se produisent moins souvent.
Les trois variantes sont nulles et produisent des chaînes de 20 à 40, mais au moins c'est rapide. Je suppose que je dois ajouter une récursivité après tout.
Au départ , je voulais essayer quelque chose de similaire à ce mais puisque c'est un graphe orienté avec des cycles, aucun des algorithmes standards pour topologiques tri, chemin le plus long, le plus grand chemin Eulerian ou de travail chinois Postman problème sans modifications lourdes.
Et juste parce que ça a l'air bien, voici une image de la matrice d'adjacence M, M ^ 2 et M ^ infini (infini = 32, ça ne change pas par la suite) avec blanc = entrées non nulles
la source