Trouvez le verrou à combinaison le plus mot


18

J'ai un cadenas à combinaison qui a des lettres au lieu de chiffres. Il ressemble à ceci: http://pictures.picpedia.com/2012/09/Word_Combination_Padlock.jpg Il y a 5 bobines, chacune ayant 10 lettres différentes dessus.

La plupart des gens aiment utiliser un mot pour leur combinaison plutôt qu'une chaîne arbitraire de lettres. (Moins sûr, bien sûr, mais plus facile à retenir.) Ainsi, lors de la fabrication du verrou, il serait bon de le construire pour avoir une combinaison de lettres qui peut être utilisée pour créer autant de mots anglais à 5 lettres que possible.

Votre tâche, si vous l'acceptez, est de trouver une affectation de lettres aux bobines qui permettra de créer autant de mots que possible. Par exemple, votre solution peut être

ABCDEFGHIJ DEFGHIJKLM ZYXWVUTSR ABCDEFGHIJ ABCDEFGHIJ

(Si vous ne vous sentiez pas trop imaginatif, c'est).

Par souci de cohérence, veuillez utiliser la liste de mots sur http://www.cs.duke.edu/~ola/ap/linuxwords

Tout mot de 5 lettres dans cette liste est OK, y compris les noms propres. Ignorez Sino- et L'vov et tous les autres mots de la liste qui contiennent un caractère non az.

Le programme gagnant est celui qui produit le plus grand nombre de mots. Dans le cas où plusieurs programmes trouveraient le même résultat, le premier à être publié l'emporterait. Le programme devrait s'exécuter en moins de 5 minutes.

Edit: depuis que l'activité s'est calmée et qu'aucune meilleure solution n'est sortie, je déclare Peter Taylor vainqueur! Merci à tous pour vos solutions inventives.


Comment peut-on compter les noms propres étant donné qu'ils varient tellement d'une culture à l'autre?
elssar

@elssar, Si je comprends bien, n'importe quel mot de la liste est OK, qu'il s'agisse d'un nom propre (dans n'importe quelle culture).
ugoren

Oh droite, là - bas , ne voit pas
elssar

Donc, pas une question de code; mais la logique?
Brigand

2
Ceci est étiqueté comme code-challenge : quel est le défi? Tout ce que vous avez demandé, c'est la valeur qui maximise une fonction dont la taille du domaine est d'environ 110,3 bits. Il n'est donc pas possible de forcer le problème par la force brute, mais il devrait être possible d'obtenir la réponse exacte, et peut-être même de le prouver. Compte tenu de tout cela, quelles sont les conditions préalables à la prise en compte d'une réponse et quels critères allez-vous utiliser pour sélectionner un gagnant?
Peter Taylor

Réponses:


6

1275 mots par simple escalade gourmande

Le code est C #. La solution produite est

Score 1275 from ^[bcdfgmpstw][aehiloprtu][aeilnorstu][acdeklnrst][adehklrsty]$

J'utilise ce format de sortie car il est vraiment facile à tester:

grep -iE "^[bcdfgmpstw][aehiloprtu][aeilnorstu][acdeklnrst][adehklrsty]$" linuxwords.txt | wc

namespace Sandbox {
    class Launcher {
        public static void Main(string[] args)
        {
            string[] lines = _Read5s();
            int[][] asMasks = lines.Select(line => line.ToCharArray().Select(ch => 1 << (ch - 'a')).ToArray()).ToArray();
            Console.WriteLine(string.Format("{0} words found", lines.Length));

            // Don't even bother starting with a good mapping.
            int[] combos = _AllCombinations().ToArray();
            int[] best = new int[]{0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff};
            int bestSc = 0;
            while (true)
            {
                Console.WriteLine(string.Format("Score {0} from {1}", bestSc, _DialsToString(best)));

                int[] prevBest = best;
                int prevBestSc = bestSc;

                // Greedy hill-climbing approach
                for (int off = 0; off < 5; off++)
                {
                    int[] dials = (int[])prevBest.Clone();

                    dials[off] = (1 << 26) - 1;
                    int[][] filtered = asMasks.Where(mask => _Permitted(dials, mask)).ToArray();
                    int sc;
                    dials[off] = _TopTen(filtered, off, out sc);
                    if (sc > bestSc)
                    {
                        best = (int[])dials.Clone();
                        bestSc = sc;
                    }
                }

                if (bestSc == prevBestSc) break;
            }

            Console.WriteLine("Done");
            Console.ReadKey();
        }

        private static int _TopTen(int[][] masks, int off, out int sc)
        {
            IDictionary<int, int> scores = new Dictionary<int, int>();
            for (int k = 0; k < 26; k++) scores[1 << k] = 0;

            foreach (int[] mask in masks) scores[mask[off]]++;

            int rv = 0;
            sc = 0;
            foreach (KeyValuePair<int, int> kvp in scores.OrderByDescending(kvp => kvp.Value).Take(10))
            {
                rv |= kvp.Key;
                sc += kvp.Value;
            }
            return rv;
        }

        private static string _DialsToString(int[] dials)
        {
            StringBuilder sb = new StringBuilder("^");
            foreach (int dial in dials)
            {
                sb.Append('[');
                for (int i = 0; i < 26; i++)
                {
                    if ((dial & (1 << i)) != 0) sb.Append((char)('a' + i));
                }
                sb.Append(']');
            }
            sb.Append('$');
            return sb.ToString();
        }

        private static IEnumerable<int> _AllCombinations()
        {
            // \binom{26}{10}
            int set = (1 << 10) - 1;
            int limit = (1 << 26);
            while (set < limit)
            {
                yield return set;

                // Gosper's hack:
                int c = set & -set;
                int r = set + c;
                set = (((r ^ set) >> 2) / c) | r;
            }
        }

        private static bool _Permitted(int[] dials, int[] mask)
        {
            for (int i = 0; i < dials.Length; i++)
            {
                if ((dials[i] & mask[i]) == 0) return false;
            }
            return true;
        }

        private static string[] _Read5s()
        {
            System.Text.RegularExpressions.Regex word5 = new System.Text.RegularExpressions.Regex("^[a-z][a-z][a-z][a-z][a-z]$", System.Text.RegularExpressions.RegexOptions.Compiled);
            return File.ReadAllLines(@"d:\tmp\linuxwords.txt").Select(line => line.ToLowerInvariant()).Where(line => word5.IsMatch(line)).ToArray();
        }
    }
}

J'étais sur le point de modifier ma réponse avec cette solution exacte, mais vous m'avez battu.
cardboard_box

Lorsque je lance la même recherche d'escalade à partir de 1000 combinaisons de départ aléatoires et que je sélectionne le meilleur des 1000 optima locaux trouvés, il semble toujours produire la même solution, il semble donc que ce soit l'optimum global.
Peter Taylor

Cela dépend de votre définition de probable ;-) Mais il est en outre "confirmé" par d'autres approches qui donnent 1275 au maximum. (Et où est passé le Quantum-Tic-Tac-Toe?)
Howard

@Howard, ce n'était qu'un artefact de .Net ne prenant pas en charge plusieurs points d'entrée dans un même projet. J'ai un projet "sandbox" que j'utilise pour des trucs comme ça, et je change généralement la Mainméthode pour appeler différentes _Mainméthodes.
Peter Taylor

J'ai essayé un algorithme génétique et j'ai obtenu le même résultat en quelques minutes, puis rien dans l'heure suivante, donc je ne serais pas surpris si c'est l'optimum.
cardboard_box

4

Python (3), 1273 ≈ 30,5%

C'est une approche vraiment naïve: garder un décompte de la fréquence de chaque lettre dans chaque position, puis éliminer la "pire" lettre jusqu'à ce que les lettres restantes tiennent sur les rouleaux. Je suis surpris que cela semble si bien fonctionner.

Ce qui est le plus intéressant, c'est que j'ai presque exactement la même sortie que la solution C # 1275, sauf que j'ai une Nsur ma dernière bobine à la place A. C'était aussi Ama 11e à la dernière élimination, même avant de jeter a Vet a G.

from collections import Counter

def main(fn, num_reels, letters_per_reel):
    # Read ye words
    words = []
    with open(fn) as f:
        for line in f:
            word = line.strip().upper()
            if len(word) == num_reels and word.isalpha():
                words.append(word)

    word_pool_size = len(words)

    # Populate a structure of freq[reel_number][letter] -> count
    freq = [Counter() for _ in range(num_reels)]
    for word in words:
        for r, letter in enumerate(word):
            freq[r][letter] += 1

    while True:
        worst_reelidx = None
        worst_letter = None
        worst_count = len(words)
        for r, reel in enumerate(freq):
            # Skip reels that already have too-few letters left
            if len(reel) <= letters_per_reel:
                continue

            for letter, count in reel.items():
                if count < worst_count:
                    worst_reelidx = r
                    worst_letter = letter
                    worst_count = count

        if worst_letter is None:
            # All the reels are done
            break

        # Discard any words containing this worst letter, and update counters
        # accordingly
        filtered_words = []
        for word in words:
            if word[worst_reelidx] == worst_letter:
                for r, letter in enumerate(word):
                    freq[r][letter] -= 1
                    if freq[r][letter] == 0:
                        del freq[r][letter]
            else:
                filtered_words.append(word)
        words = filtered_words

    for reel in freq:
        print(''.join(sorted(reel)))

    print("{} words found (~{:.1f}%)".format(
        len(words), len(words) / word_pool_size * 100))

Produit:

BCDFGMPSTW
AEHILOPRTU
AEILNORSTU
ACDEKLNRST
DEHKLNRSTY
1273 words found (~30.5%)

Que représente le pourcentage?
Joe Z.

pourcentage des mots donnés qui peuvent être faits avec le jeu de bobines proposé
Eevee

D'accord. (Whoa, je viens de voir qui tu étais.)
Joe Z.

ha, petit monde.
Evoli

3

Mathematica , 1275 mots encore et encore ...

Ce code n'est pas Golfé car la question ne semble pas appeler cela.

wordlist = Flatten @ Import @ "http://www.cs.duke.edu/~ola/ap/linuxwords";
shortlist = Select[ToLowerCase@wordlist, StringMatchQ[#, Repeated[LetterCharacter, {5}]] &];
string = "" <> Riffle[shortlist, ","];

set = "a" ~CharacterRange~ "z";
gb = RandomChoice[set, {5, 10}];

best = 0;
While[True,
  pos = Sequence @@ RandomInteger /@ {{1, 5}, {1, 10}};
  old = gb[[pos]];
  gb[[pos]] = RandomChoice @ set;
  If[best < #,
    best = #; Print[#, "   ", StringJoin /@ gb],
    gb[[pos]] = old
  ] & @ StringCount[string, StringExpression @@ Alternatives @@@ gb]
]

Le nombre de mots rapidement (moins de 10 secondes) évolue à 1275 sur la plupart des pistes mais ne dépasse jamais cela. J'ai essayé de perturber les lettres de plus d'une à la fois pour essayer de sortir d'un maximum local théorique, mais cela n'a jamais aidé. Je soupçonne fortement que 1275 est la limite pour la liste de mots donnée. Voici un parcours complet:

36   {tphcehmqkt,agvkqxtnpy,nkehuaakri,nsibxpctio,iafwdyhone}

37   {tpicehmqkt,agvkqxtnpy,nkehuaakri,nsibxpctio,iafwdyhone}

40   {tpicehmqkt,agvkqxtnpy,nkehuaakri,nsibxpctio,iafldyhone}

42   {tpicehmqkt,agvkqxtnpy,nkehuaakri,nsfbxpctio,iafldyhone}

45   {tpicehmrkt,agvkqxtnpy,nkehuaakri,nsfbxpctio,iafldyhone}

48   {tpicehmrkt,agvkwxtnpy,nkehuaakri,nsfbxpctio,iafldyhone}

79   {tpicehmskt,agvkwxtnpy,nkehuaakri,nsfbxpctio,iafldyhone}

86   {tpicehmskt,agvkwxtnpy,nkehuaakri,esfbxpctio,iafldyhone}

96   {tpicehmskt,agvkwxtnpy,nkehuaokri,esfbxpctio,iafldyhone}

97   {tpicehmskt,agvkwxtnpy,nkehuaokri,esfbxpctio,ipfldyhone}

98   {tpicehmskv,agvkwxtnpy,nkehuaokri,esfbxpctio,ipfldyhone}

99   {tpicehmskv,agvkwxtnpy,nkehuaokri,esfbzpctio,ipfldyhone}

101   {tpicehmskv,agvkwxtnpy,nkehuaokri,esfhzpctio,ipfldyhone}

102   {tpicehmskv,agvkwxtnpy,nkehuaokri,esfhzpctno,ipfldyhone}

105   {tpicehmskv,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldyhone}

107   {tpicehmskn,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldyhone}

109   {tpgcehmskn,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldyhone}

115   {tpgcehmsan,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldyhone}

130   {tpgcehmsan,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldyhons}

138   {tpgcehmsan,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldytons}

143   {tpgcehmsab,agvkwxtnpy,nkehuaokri,esfhzmctno,ipfldytons}

163   {tpgcehmsab,auvkwxtnpy,nkehuaokri,esfhzmctno,ipfldytons}

169   {tpgcehmsab,auvkwctnpy,nkehuaokri,esfhzmctno,ipfldytons}

176   {tpgcehmsab,auvkwctnpy,nkehuaokri,esfhzmctno,ihfldytons}

189   {tpgcehmsab,auvkwchnpy,nkehuaokri,esfhzmctno,ihfldytons}

216   {tpgcehmsab,auvkwchnpy,nkehtaokri,esfhzmctno,ihfldytons}

220   {tpgcehmsab,auvkwthnpy,nkehtaokri,esfhzmctno,ihfldytons}

223   {tpgcehmsab,auvkwthnpy,nkehtaokri,esfhbmctno,ihfldytons}

234   {tpgcehmsab,auvkwthnpy,nkegtaokri,esfhbmctno,ihfldytons}

283   {tpgcehmsab,auvkwthnpy,nkegtaokri,esfhbrctno,ihfldytons}

285   {tpdcehmsab,auvkwthnpy,nkegtaokri,esfhbrctno,ihfldytons}

313   {tpdcehmsab,auvkwthnly,nkegtaokri,esfhbrctno,ihfldytons}

371   {tpdcehmsab,auvkethnly,nkegtaokri,esfhbrctno,ihfldytons}

446   {tpdcehmsab,auvoethnly,nkegtaokri,esfhbrctno,ihfldytons}

451   {tpdcehmslb,auvoethnly,nkegtaokri,esfhbrctno,ihfldytons}

465   {tpdcwhmslb,auvoethnly,nkegtaokri,esfhbrctno,ihfldytons}

545   {tpdcwhmslb,auioethnly,nkegtaokri,esfhbrctno,ihfldytons}

565   {tpdcwhmslb,auioethnly,nkegtaocri,esfhbrctno,ihfldytons}

571   {tpdcwhmslb,auioethnly,nkegtaocri,esfhwrctno,ihfldytons}

654   {tpdcwhmslb,auioethnly,nkegtaocri,esfhwrctno,ihfedytons}

671   {tpdcwhmslb,auioethnly,nkegtaocri,esfhirctno,ihfedytons}

731   {tpdcwhmslb,auioethnly,nkegtaocri,esfhirctno,ihredytons}

746   {tpdcwhmslb,arioethnly,nkegtaocri,esfhirctno,ihredytons}

755   {tpdcwhmslb,arioethnuy,nkegtaocri,esfhirctno,ihredytons}

772   {tpdcwhmslb,arioethnuy,nkegtaocri,ekfhirctno,ihredytons}

786   {tpdcwhmslb,arioethnuy,nkegtaocri,ekfhirctno,lhredytons}

796   {tpdcwhmslb,arioethnuy,nkegtaocri,ekfhgrctno,lhredytons}

804   {tpdcwhmslb,arioethwuy,nkegtaocri,ekfhgrctno,lhredytons}

817   {tpdcwhmslb,arioethwuy,nklgtaocri,ekfhgrctno,lhredytons}

834   {tpdcwhmslb,arioethwuy,nklgtaocri,ekfhdrctno,lhredytons}

844   {tpdcwhmslb,arioethwup,nklgtaocri,ekfhdrctno,lhredytons}

887   {tpdcwhmslb,arioethwup,nklgtaocri,ekshdrctno,lhredytons}

901   {tpdcwhmslb,arioethwup,nklgtaouri,ekshdrctno,lhredytons}

966   {tpdcwhmslb,arioethwup,nklgtaouri,elshdrctno,lhredytons}

986   {tpdcwhmsfb,arioethwup,nklgtaouri,elshdrctno,lhredytons}

1015   {tpdcwhmsfb,arioethwup,nklgtaouri,elsidrctno,lhredytons}

1039   {tpdcwhmsfb,arioethwup,nklgtaouri,elsidrctno,khredytons}

1051   {tpdcwhmsfb,arioethwup,nklgtaouri,elskdrctno,khredytons}

1055   {tpdcwhmsfb,arioethwup,nklgtaouri,elskdrctno,khredytlns}

1115   {tpdcwhmsfb,arioethwup,nelgtaouri,elskdrctno,khredytlns}

1131   {tpdcwhmsfb,arioethwup,nelwtaouri,elskdrctno,khredytlns}

1149   {tpdcwhmsfb,arioethwup,nelwtaouri,elskdrctna,khredytlns}

1212   {tpdcwhmsfb,arioelhwup,nelwtaouri,elskdrctna,khredytlns}

1249   {tpdcwhmsfb,arioelhwup,nelstaouri,elskdrctna,khredytlns}

1251   {tpgcwhmsfb,arioelhwup,nelstaouri,elskdrctna,khredytlns}

1255   {tpgcwdmsfb,arioelhwup,nelstaouri,elskdrctna,khredytlns}

1258   {tpgcwdmsfb,arioelhwup,nelstaouri,elskdrctna,khredytlas}

1262   {tpgcwdmsfb,arioelhwut,nelstaouri,elskdrctna,khredytlas}

1275   {tpgcwdmsfb,arioelhput,nelstaouri,elskdrctna,khredytlas}

Voici quelques autres sélections "gagnantes":

{"cbpmsftgwd", "hriuoepatl", "euosrtanli", "clknsaredt", "yhlkdstare"}
{"wptdsgcbmf", "ohlutraeip", "erotauinls", "lknectdasr", "sytrhklaed"}
{"cftsbwgmpd", "ropilhtaue", "niauseltor", "clstnkdrea", "esdrakthly"}
{"smgbwtdcfp", "ihulpreota", "ianrsouetl", "ekndasctlr", "kehardytls"}

Comme Peter le fait remarquer, ce sont en fait la même solution dans des ordres différents. Trié:

{"bcdfgmpstw", "aehiloprtu", "aeilnorstu", "acdeklnrst", "adehklrsty"}

@belisarius Merci! C'est plus intéressant avec ENABLE2k .
Mr.Wizard

J'ai envisagé NetworkFlow de Combinatorica pour celui-ci, mais je n'ai pas trouvé de moyen utile de l'utiliser
Dr. belisarius

@belisarius J'espère que vous trouverez un moyen; J'aimerais voir ça.
Mr.Wizard

@belisarius par la façon dont mon code shortlistsemble long, et bien que ce ne soit pas Golf, j'aimerais quelque chose de plus court. Pouvez-vous m'aider?
Mr.Wizard

1
Je pense que vos sélections "gagnantes" sont toutes la même permutation modulo dans les cadrans.
Peter Taylor

2

Python, 1210 mots (~ 29%)

En supposant que j'ai compté les mots correctement cette fois, c'est légèrement mieux que la solution de FakeRainBrigand. La seule différence est que j'ajoute chaque bobine dans l'ordre, puis que je supprime tous les mots de la liste qui ne correspondent pas à la bobine afin d'obtenir une distribution légèrement meilleure pour les bobines suivantes. Pour cette raison, il donne exactement la même première bobine.

word_list = [line.upper()[:-1] for line in open('linuxwords.txt','r').readlines() if len(line) == 6]
cur_list = word_list
s = ['']*5
for i in range(5):
    count = [0]*26
    for j in range(26):
        c = chr(j+ord('A'))
        count[j] = len([x for x in cur_list if x[i] == c])
    s[i] = [chr(x+ord('A')) for x in sorted(range(26),lambda a,b: count[b] - count[a])[:10]]
    cur_list = filter(lambda x:x[i] in s[i],cur_list)
for e in s:
    print ''.join(e)
print len(cur_list)

Les résultats du programme

SBCAPFDTMG
AOREILUHTP
ARIOLENUTS
ENTLRCSAID
SEYDTKHRNL
1210

Nice, et 1210 fonctionne dans mon vérificateur.
Brigand

1

iPython ( 273 210 octets, 1115 mots)

1115/4176 * ~ 27%

Je les ai calculés dans iPython, mais mon historique (coupé pour supprimer le débogage) ressemblait à ceci.

with open("linuxwords") as fin: d = fin.readlines()
x = [w.lower().strip() for w in d if len(w) == 6]
# Saving for later use:
# with open("5letter", "w") as fout: fout.write("\n".join(x))
from string import lowercase as low
low=lowercase + "'"
c = [{a:0 for a in low} for q in range(5)]
for w in x:
    for i, ch in enumerate(w):
        c[i][ch] += 1

[''.join(sorted(q, key=q.get, reverse=True)[:10]) for q in c]

Si nous allons court; Je pourrais le couper à cela.

x = [w.lower().strip() for w in open("l") if len(w)==6]
c=[{a:0 for a in"abcdefghijklmnopqrstuvwxyz'-"}for q in range(5)]
for w in[w.lower().strip()for w in open("l") if len(w)==6]:
 for i in range(5):c[i][w[i]]+=1
[''.join(sorted(q,key=q.get,reverse=True)[:10])for q in c]

Raccourci:

c=[{a:0 for a in"abcdefghijklmnopqrstuvwxyz'-"}for q in range(5)]
for w in[w.lower() for w in open("l")if len(w)==6]:
 for i in range(5):c[i][w[i]]+=1
[''.join(sorted(q,key=q.get,reverse=True)[:10])for q in c]

Mes résultats étaient les suivants : ['sbcapfdtmg', 'aoeirulhnt', 'aironeluts', 'etnlriaosc', 'seyrdtnlah'].

* Mes calculs sur le 4176 peuvent être un peu courts en raison de l'omission de mots avec des tirets ou des apostrophes


1
Bien que cette solution soit une bonne heuristique et renverra probablement une bonne solution, je ne pense pas qu'elle soit garantie de renvoyer la solution optimale. La raison en est que vous ne capturez pas les contraintes entre les bobines: vous traitez chaque bobine comme une variable indépendante alors qu'en fait elles sont dépendantes. Par exemple, il se peut que les mots qui partagent la première lettre la plus courante aient une grande variance dans la distribution de leur deuxième lettre. Si tel est le cas, votre solution pourrait produire des combinaisons de bobines qui ne permettent en fait aucun mot.
ESultanik

1

Q

? (todo) mots

Les mots doivent être stockés dans un fichier appelé words

(!:')10#/:(desc')(#:'')(=:')(+:)w@(&:)(5=(#:')w)&(&/')(w:(_:)(0:)`:words)in\:.Q.a

Fonctionne en environ 170 ms sur mon i7. Il analyse la liste de mots, recherchant la lettre la plus courante dans chaque poste (filtrant évidemment les non-candidats). C'est une solution naïve paresseuse mais produit un résultat raisonnablement bon avec un code minimal.

Résultats:

"sbcapfdtmg"
"aoeirulhnt"
"aironeluts"
"etnlriaosc"
"seyrdtnlah"

Combien de mots de 5 lettres avez-vous trouvé?
DavidC

J'ai fait la même chose en python et j'ai obtenu 16353.
cardboard_box

Est-ce le même algorithme gourmand que celui de FakeRainBrigand?
Peter Taylor

1
@cardboard_box, votre résultat est définitivement faux. Il n'y a pas beaucoup de mots de 5 lettres dans le dictionnaire.
Peter Taylor

1
Oui, c'est 1115. J'ai compté le nombre de lettres correctes dans n'importe quel mot au lieu du nombre de mots corrects. Je pense que j'ai besoin d'un autre café.
cardboard_box

0

Éditer: Maintenant que les règles ont été modifiées, cette approche est disqualifiée. Je vais le laisser ici au cas où quelqu'un serait intéressé jusqu'à ce que je finisse par le modifier pour les nouvelles règles.

Python: 277 caractères

Je suis presque sûr que la version généralisée de ce problème est NP-Hard, et la question ne nécessitait pas de trouver la solution la plus rapide , alors voici une méthode de force brute pour le faire:

import itertools,string
w=[w.lower()[:-1] for w in open('w') if len(w)==6]
v=-1
for l in itertools.product(itertools.combinations(string.ascii_lowercase,10),repeat=5):
 c=sum(map(lambda d:sum(map(lambda i:i[0] in i[1],zip(d,l)))==5,w))
 if c>v:
  v=c
  print str(c)+" "+str(l)

Notez que j'ai renommé le fichier de liste de mots en "w" pour enregistrer quelques caractères.

La sortie est le nombre de mots possibles à partir d'une configuration donnée suivie de la configuration elle-même:

34 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'))
38 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'))
42 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l'))
45 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'n'))
50 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'r'))
57 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 's'))
60 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'k', 's'))
64 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'l', 's'))
67 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'n', 's'))
72 (('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'), ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'r', 's'))
...

La dernière ligne de sortie avant la fin du programme est garantie d'être la solution optimale.


Je serais ravi de voir une version C ou ASM de votre code afin qu'il puisse réellement se terminer cette année :-) Ou au moins l'exécuter jusqu'à 1116. Pourriez-vous l'écrire sans itertools, afin que je puisse l'exécuter sur jython ? (plus rapide que le python ordinaire, mais plus facile que le cython.)
Brigand

Peu importe la chose Jython. J'avais besoin de saisir l'alpha. Il est toujours tombé en panne (trop de mémoire) mais cela semble inévitable.
Brigand

Je suis à peu près sûr que même si cela était implémenté dans l'assemblage, cela prendrait plus de temps que ma vie pour terminer sur le matériel actuel :-P
ESultanik

Le problème est que j'itère sur (26 choisissez 10) ^ 5 ≈ 4,23 * 10 ^ 33 possibilités. Même si nous pouvions tester une possibilité par nanoseconde, il faudrait environ 10 ^ 7 fois l'âge actuel de l'univers pour terminer.
ESultanik

1
Il y a deux caractères qui n'apparaissent pas en 5ème position dans n'importe quel mot de la liste de mots donnée, vous pouvez donc réduire le nombre de possibilités d'un facteur d'environ 4. Voilà comment j'ai obtenu "environ 110,3 bits" dans mon commentaire sur la question.
Peter Taylor
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.