Znajdź najsławniejszy zamek szyfrowy

18

Mam kombinowaną kłódkę, która ma litery zamiast cyfr. Wygląda to tak: http://pictures.picpedia.com/2012/09/Word_Combination_Padlock.jpg Jest 5 rolek, z których każda zawiera 10 różnych liter.

Większość ludzi lubi używać słowa w swojej kombinacji zamiast dowolnego ciągu liter. (Oczywiście mniej bezpieczne, ale łatwiejsze do zapamiętania.) Dlatego przy produkcji zamka dobrze byłoby zbudować go tak, aby zawierał kombinację liter, których można użyć do utworzenia jak największej liczby 5-literowych angielskich słów.

Twoim zadaniem, jeśli zdecydujesz się to zaakceptować, jest znalezienie przypisania liter do rolek, co pozwoli na utworzenie jak największej liczby słów. Na przykład rozwiązaniem może być

ABCDEFGHIJ DEFGHIJKLM ZYXWVUTSR ABCDEFGHIJ ABCDEFGHIJ

(To znaczy, jeśli nie czujesz się zbyt pomysłowy).

Aby zachować spójność, użyj listy słów na stronie http://www.cs.duke.edu/~ola/ap/linuxwords

Każde 5-literowe słowo z tej listy jest poprawne, w tym nazwy własne. Zignoruj ​​Sino- i L'vov oraz wszelkie inne słowa na liście, które zawierają znak inny niż az.

Zwycięski program to ten, który daje największy zestaw słów. W przypadku, gdy wiele programów znajdzie ten sam wynik, pierwszy z opublikowanych wygrywa. Program powinien zostać uruchomiony w mniej niż 5 minut.

Edycja: odkąd aktywność umarła i nie ma lepszych rozwiązań, ogłaszam zwycięzcę Petera Taylora! Dziękujemy wszystkim za pomysłowe rozwiązania.

Edwin Young
źródło
Jak policzyć właściwe nazwy, biorąc pod uwagę, że różnią się tak bardzo w różnych kulturach?
elssar
@elssar, Jeśli dobrze rozumiem, każde słowo na liście jest OK, niezależnie od tego, czy jest to właściwe imię (w dowolnej kulturze).
ugoren
No tak, tam , nie widziałem tego
Elssar
Więc nie pytanie kodowe; ale logika?
Brigand
2
Oznaczono to jako kod-wyzwanie : jakie jest wyzwanie? Wszystko, o co prosiłeś, to wartość, która maksymalizuje funkcję, której rozmiar domeny wynosi około 110,3 bitów. Problem brutalnej siły nie jest więc możliwy, ale uzyskanie dokładnej odpowiedzi, a może nawet udowodnienie jej poprawności, powinno być wykonalne. Mając to na uwadze, jakie są warunki wstępne do rozważenia odpowiedzi i jakich kryteriów zamierzasz użyć, aby wybrać zwycięzcę?
Peter Taylor

Odpowiedzi:

6

1275 słów przez prostą chciwą wspinaczkę

Kod to C #. Wytworzone rozwiązanie to

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

Używam tego formatu wyjściowego, ponieważ bardzo łatwo go przetestować:

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();
        }
    }
}
Peter Taylor
źródło
Właśnie miałem edytować moją odpowiedź z tym dokładnym rozwiązaniem, ale pobiłaś mnie.
cardboard_box
Kiedy uruchamiam to samo wyszukiwanie wspinaczkowe na podstawie 1000 losowych kombinacji początkowych i wybieram najlepsze z 1000 znalezionych lokalnych optymów, wydaje się, że zawsze daje to samo rozwiązanie, więc wydaje się, że jest to globalne optimum.
Peter Taylor
To zależy od twojej definicji prawdopodobieństwa ;-) Ale jest to dalej „potwierdzane” przez inne podejścia, które dają 1275 jako maksimum. (A gdzie poszedł Quantum-Tic-Tac-Toe?)
Howard
@Howard, to był tylko artefakt .Net nie obsługujący wielu punktów wejścia w jednym projekcie. Mam jeden projekt „piaskownicy”, którego używam do takich rzeczy i zwykle zmieniam Mainmetodę, aby wywoływała różne _Mainmetody.
Peter Taylor
Wypróbowałem algorytm genetyczny i uzyskałem ten sam wynik w ciągu kilku minut, a potem nic w ciągu następnej godziny, więc nie zdziwiłbym się, gdyby był optymalny.
cardboard_box
4

Python (3), 1273 ≈ 30,5%

To naprawdę naiwne podejście: trzymaj sumę częstotliwości każdej litery w każdej pozycji, a następnie eliminuj „najgorszą” literę, aż pozostałe litery zmieszczą się na rolkach. Dziwi mnie, że wydaje się, że robi to tak dobrze.

Najciekawsze jest to, że mam prawie taką samą moc wyjściową jak rozwiązanie C # 1275, tyle że Nzamiast tego mam ostatnią rolkę A. To Abyła moja ostatnia eliminacja, nawet przed wyrzuceniem a Vi 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))

Produkuje:

BCDFGMPSTW
AEHILOPRTU
AEILNORSTU
ACDEKLNRST
DEHKLNRSTY
1273 words found (~30.5%)
Eevee
źródło
Co stanowi procent?
Joe Z.
procent podanych słów, które można utworzyć za pomocą proponowanego zestawu rolek
Eevee
W porządku. (Whoa, właśnie widziałem, kim jesteś.)
Joe Z.
ha, mały świat.
Eevee
3

Mathematica , 1275 słów w kółko ...

Ten kod nie jest golfowy, ponieważ wydaje się, że nie wymaga tego pytanie.

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]
]

Liczba słów szybko (mniej niż 10 sekund) ewoluuje do 1275 w większości przebiegów, ale nigdy nie przekracza tego. Próbowałem naruszyć litery więcej niż jeden na raz, próbując wydostać się z teoretycznego maksimum lokalnego, ale to nigdy nie pomogło. Podejrzewam, że 1275 jest limitem dla danej listy słów. Oto kompletny przebieg:

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}

Oto kilka innych „zwycięskich” wyborów:

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

Jak komentuje Peter, w rzeczywistości są to te same rozwiązania w różnych zamówieniach. Posortowane:

{"bcdfgmpstw", "aehiloprtu", "aeilnorstu", "acdeklnrst", "adehklrsty"}
Mr.Wizard
źródło
@belisarius Thanks! Jest bardziej interesujący z ENABLE2k .
Mr.Wizard
Zastanawiałem się nad tym dla NetworkFlow firmy Combinatorica, ale nie znalazłem przydatnego sposobu jej wykorzystania
dr belisarius
@belisarius Mam nadzieję, że znajdziesz sposób; Chciałabym to zobaczyć.
Mr.Wizard
@ belisarius, przy okazji, mój kod od shortlistdawna wydaje się długi i chociaż nie jest to Golf, chciałbym coś krótszego. Możesz pomóc?
Mr.Wizard
1
Myślę, że twoje „zwycięskie” wybory są tą samą modulo permutacją w obrębie tarcz.
Peter Taylor
2

Python, 1210 słów (~ 29%)

Zakładając, że tym razem poprawnie policzyłem słowa, jest to nieco lepsze niż rozwiązanie FakeRainBrigand. Jedyna różnica polega na tym, że dodam kolejno każdą rolkę, a następnie usuwam z listy wszystkie słowa, które nie pasują do rolki, dzięki czemu otrzymuję nieco lepszą dystrybucję dla kolejnych rolek. Z tego powodu daje dokładnie ten sam pierwszy kołowrotek.

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)

Program generuje

SBCAPFDTMG
AOREILUHTP
ARIOLENUTS
ENTLRCSAID
SEYDTKHRNL
1210
pudełko kartonowe
źródło
Ładne, a 1210 działa w mojej warcabie.
Brigand
1

iPython ( 273 210 bajtów, 1115 słów)

1115/4176 * ~ 27%

Obliczałem je w iPython, ale moja historia (dostosowana do usuwania debugowania) wyglądała tak.

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]

Jeśli idziemy krótko; Mógłbym to przyciąć.

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]

Skrócony:

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]

Moje wyniki to: ['sbcapfdtmg', 'aoeirulhnt', 'aironeluts', 'etnlriaosc', 'seyrdtnlah'] .

* Moja matematyka na 4176 może być trochę krótka z powodu słów z pominiętymi myślnikami lub apostrofami

Bandyta
źródło
1
Chociaż to rozwiązanie jest dobrą heurystyką i prawdopodobnie zwróci dobre rozwiązanie, nie sądzę, że gwarantuje to zwrot optymalnego rozwiązania. Powodem jest to, że nie wychwytujesz ograniczeń między rolkami: traktujesz każdą rolkę jako niezależną zmienną, podczas gdy w rzeczywistości są one zależne. Na przykład może się zdarzyć, że słowa, które dzielą najczęstszą pierwszą literę, mają dużą zmienność w rozkładzie drugiej litery. W takim przypadku twoje rozwiązanie może tworzyć kombinacje rolek, które w rzeczywistości nie pozwalają na żadne słowa.
ESultanik
1

Q

? (todo) słowa

Słowa powinny być przechowywane w pliku o nazwie words

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

Działa za około 170 ms na moim i7. Analizuje listę słów, szukając najczęstszego listu na każdej pozycji (oczywiście odfiltrowuje osoby niebędące kandydatami). Jest to leniwe naiwne rozwiązanie, ale daje całkiem dobry wynik przy minimalnym kodzie.

Wyniki:

"sbcapfdtmg"
"aoeirulhnt"
"aironeluts"
"etnlriaosc"
"seyrdtnlah"
skeevey
źródło
Ile znalazłeś 5 literowych słów?
DavidC
Zrobiłem to samo w python i mam 16353.
cardboard_box
Czy to ten sam chciwy algorytm jak FakeRainBrigand?
Peter Taylor
1
@cardboard_box, twój wynik jest zdecydowanie zły. W słowniku nie ma tak wielu 5-literowych słów.
Peter Taylor
1
Tak, to jest 1115. Policzyłem liczbę poprawnych liter w dowolnym słowie zamiast liczby poprawnych słów. Myślę, że potrzebuję kolejnej kawy.
cardboard_box
0

Edytować: Teraz, gdy reguły zostały zmodyfikowane, to podejście jest zdyskwalifikowane. Zostawię to tutaj na wypadek, gdyby ktoś był zainteresowany, dopóki w końcu nie zacznę modyfikować go pod kątem nowych zasad.

Python: 277 znaków

Jestem prawie pewien, że uogólniona wersja tego problemu to NP-Hard, a pytanie nie wymagało znalezienia najszybszego rozwiązania, więc oto metoda zrobienia tego z brutalną siłą:

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)

Zauważ, że zmieniłem nazwę pliku listy słów na „w”, aby zapisać kilka znaków.

Dane wyjściowe to liczba możliwych słów z danej konfiguracji, po której następuje sama konfiguracja:

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'))
...

Ostatni wiersz wyjścia przed zakończeniem programu gwarantuje optymalne rozwiązanie.

ESultanik
źródło
Chciałbym zobaczyć wersję Twojego kodu C lub ASM, aby mogła zakończyć się w tym roku :-) Lub przynajmniej uruchom go, aż dojdzie do 1116. Czy możesz napisać go bez itertools, więc mogę uruchomić go na Jython ? (szybszy niż zwykły python, ale łatwiejszy niż cyton)
Brigand
Nieważne, co to jest za Jython. Musiałem złapać alfę. Nadal się zawiesił (za dużo pamięci), ale wydaje się to nieuniknione.
Brigand
Jestem prawie pewien, że nawet jeśli zostałyby zaimplementowane w asemblerze, ukończenie na obecnym sprzęcie zajęłoby więcej niż moje życie :-P
ESultanik 21.01.2013
Problem polega na tym, że iteruję (26 wybieram 10) ^ 5 ≈ 4,23 * 10 ^ 33 możliwości. Nawet gdybyśmy mogli przetestować jedną możliwość na nanosekundę, ukończenie tego zajęłoby około 10 ^ 7 razy więcej niż obecny wiek wszechświata.
ESultanik,
1
Istnieją dwa znaki, które nie pojawiają się na 5. pozycji w żadnym słowie z podanej listy słów, więc możesz zmniejszyć liczbę możliwości około czterokrotnie. W ten sposób otrzymałem „około 110,3 bitów” w moim komentarzu do pytanie.
Peter Taylor