Tìm khóa kết hợp tốt nhất


18

Tôi có một ổ khóa kết hợp có chữ cái thay vì số. Nó trông như thế này: http://pictures.picpedia.com/2012/09/Word_Combination_Padlock.jpg Có 5 cuộn, mỗi cuộn có 10 chữ cái khác nhau trên đó.

Hầu hết mọi người thích sử dụng một từ cho sự kết hợp của họ hơn là một chuỗi các chữ cái tùy ý. (Tất nhiên là ít an toàn hơn, nhưng dễ nhớ hơn.) Vì vậy, khi sản xuất khóa, sẽ tốt hơn nếu xây dựng nó để có sự kết hợp của các chữ cái có thể được sử dụng để tạo ra càng nhiều từ tiếng Anh 5 chữ cái càng tốt.

Nhiệm vụ của bạn, nếu bạn chọn chấp nhận nó, là tìm một sự phân công các chữ cái cho các cuộn sẽ cho phép tạo ra càng nhiều từ càng tốt. Ví dụ: giải pháp của bạn có thể là

ABCDEFGHIJ DEFGHIJKLM ZYXWVUTSR ABCDEFGHIJ ABCDEFGHIJ

(Nếu bạn không cảm thấy quá giàu trí tưởng tượng, đó là).

Để thống nhất, vui lòng sử dụng danh sách từ tại http://www.cs.duke.edu/~ola/ap/linuxwords

Bất kỳ từ 5 chữ cái nào trong danh sách đó đều ổn, bao gồm cả tên riêng. Bỏ qua Sino- và L'vov và bất kỳ từ nào khác trong danh sách có chứa ký tự không az.

Chương trình chiến thắng là chương trình tạo ra tập hợp từ lớn nhất. Trong trường hợp nhiều chương trình tìm thấy cùng một kết quả, chương trình đầu tiên được đăng sẽ thắng. Chương trình sẽ chạy trong dưới 5 phút.

Chỉnh sửa: vì hoạt động đã ngừng hoạt động, và không có giải pháp nào tốt hơn được đưa ra, tôi tuyên bố Peter Taylor là người chiến thắng! Cảm ơn tất cả mọi người cho các giải pháp sáng tạo của bạn.


Làm thế nào người ta có thể đếm tên thích hợp xem xét rằng chúng khác nhau rất nhiều giữa các nền văn hóa?
elssar

@elssar, Nếu tôi hiểu chính xác, bất kỳ từ nào trong danh sách đều ổn, bất kể đó là tên riêng (trong bất kỳ nền văn hóa nào).
ugoren

Ồ đúng rồi, trong đó , đã không thấy điều đó
elssar

Vì vậy, không phải là một câu hỏi mã; nhưng logic?
Brigand

2
Điều này được gắn thẻ là thử thách mã : thách thức là gì? Tất cả những gì bạn đã yêu cầu là giá trị tối đa hóa một hàm có kích thước miền khoảng 110,3 bit. Vì vậy, nó không khả thi để giải quyết vấn đề, nhưng nó có thể khả thi để có câu trả lời chính xác, và thậm chí có thể chứng minh nó đúng. Ghi nhớ tất cả những điều đó, điều kiện tiên quyết để một câu trả lời được xem xét là gì, và bạn sẽ sử dụng tiêu chí nào để chọn người chiến thắng?
Peter Taylor

Câu trả lời:


6

1275 từ bằng cách leo đồi tham lam đơn giản

Mã là C #. Giải pháp sản xuất là

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

Tôi đang sử dụng định dạng đầu ra đó bởi vì nó thực sự dễ kiểm tra:

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();
        }
    }
}

Tôi chỉ định sửa câu trả lời của mình bằng giải pháp chính xác này, nhưng bạn đã đánh bại tôi.
tông_box

Khi tôi thực hiện cùng một tìm kiếm leo đồi từ 1000 kết hợp bắt đầu ngẫu nhiên và chọn tốt nhất trong số 1000 tối ưu địa phương được tìm thấy, nó dường như luôn tạo ra cùng một giải pháp, vì vậy nó có vẻ là tối ưu toàn cầu.
Peter Taylor

Điều đó phụ thuộc vào định nghĩa của bạn về khả năng ;-) Nhưng nó được "xác nhận" hơn nữa bởi các phương pháp khác mang lại tối đa 1275. (Và Quantum-Tic-Tac-Toe đã đi đâu?)
Howard

@Howard, đó chỉ là một tạo tác của .Net không hỗ trợ nhiều điểm vào trong một dự án. Tôi có một dự án "hộp cát" mà tôi sử dụng cho những thứ như thế này và tôi thường thay đổi Mainphương thức để gọi các _Mainphương thức khác nhau .
Peter Taylor

Tôi đã thử một thuật toán di truyền và nhận được kết quả tương tự trong vài phút, và sau đó không có gì trong giờ tiếp theo, vì vậy tôi sẽ không ngạc nhiên nếu đó là tối ưu.
tông_box

4

Con trăn (3), 1273 30,5%

Đây là một cách tiếp cận thực sự ngây thơ: giữ một tần số của từng chữ cái ở mỗi vị trí, sau đó loại bỏ chữ cái "tệ nhất" cho đến khi các chữ cái còn lại sẽ nằm gọn trong guồng. Tôi ngạc nhiên khi nó dường như làm rất tốt.

Điều thú vị nhất là tôi có đầu ra gần như chính xác như giải pháp C # 1275, ngoại trừ tôi có một Ncuộn cuối cùng thay vì A. Đó Acũng là lần loại thứ 11 đến cuối cùng của tôi, ngay cả trước khi vứt bỏ a Vvà 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))

Sản xuất:

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

Tỷ lệ phần trăm đại diện cho những gì?
Joe Z.

tỷ lệ phần trăm của các từ đã cho có thể được thực hiện với bộ cuộn được đề xuất
Eevee

Được chứ. (Whoa, tôi vừa thấy bạn là ai.)
Joe Z.

ha, thế giới nhỏ bé.
Eevee

3

Toán học , 1275 từ lặp đi lặp lại ...

Mã này không được đánh gôn vì câu hỏi không xuất hiện để gọi cho điều đó.

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

Số từ nhanh chóng (dưới 10 giây) phát triển thành 1275 trên hầu hết các lần chạy nhưng không bao giờ vượt quá điều đó. Tôi đã cố gắng làm nhiễu các chữ cái nhiều hơn một lần trong một nỗ lực để thoát khỏi mức tối đa theo lý thuyết địa phương nhưng nó không bao giờ giúp được. Tôi hoàn toàn nghi ngờ rằng 1275 là giới hạn cho danh sách từ đã cho. Đây là một hoạt động hoàn chỉnh:

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}

Dưới đây là một số lựa chọn "chiến thắng" khác:

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

Như Peter nhận xét đây thực sự là cùng một giải pháp theo các thứ tự khác nhau. Sắp xếp

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

@ Belisarius Cảm ơn! Nó thú vị hơn với ENABLE2k .
Mr.Wizard

Tôi đã xem xét NetworkFlow của Combinatorica cho cái này, nhưng chưa tìm thấy một cách hữu ích để sử dụng nó
Tiến sĩ belisarius

@ Belisarius Tôi hy vọng bạn tìm thấy một cách; Tôi muốn thấy điều đó.
Mr.Wizard

@ Belisarius bằng cách mã của tôi shortlistcảm thấy dài, và mặc dù đây không phải là Golf Tôi muốn một cái gì đó ngắn hơn. Bạn có thể giúp?
Mr.Wizard

1
Tôi nghĩ rằng các lựa chọn "chiến thắng" của bạn là tất cả các hoán vị modulo giống nhau trong các mặt số.
Peter Taylor

2

Python, 1210 từ (~ 29%)

Giả sử lần này tôi đã đếm chính xác các từ này, điều này tốt hơn một chút so với giải pháp của FakeRainBrigand. Sự khác biệt duy nhất là tôi thêm từng cuộn theo thứ tự, và sau đó xóa tất cả các từ khỏi danh sách không khớp với cuộn để tôi có được phân phối tốt hơn một chút cho các cuộn tiếp theo. Bởi vì điều này, nó cung cấp chính xác cuộn đầu tiên.

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)

Chương trình đầu ra

SBCAPFDTMG
AOREILUHTP
ARIOLENUTS
ENTLRCSAID
SEYDTKHRNL
1210

Nice, và 1210 hoạt động trong trình kiểm tra của tôi.
Brigand

1

iPython ( 273 210 byte, 1115 từ)

1115/4176 * ~ 27%

Tôi đã tính toán những thứ này trong iPython, nhưng lịch sử của tôi (được cắt bớt để gỡ lỗi) trông như thế này.

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]

Nếu chúng ta đi ngắn; Tôi có thể cắt nó để này.

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]

Rút gọn:

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]

Kết quả của tôi là : ['sbcapfdtmg', 'aoeirulhnt', 'aironeluts', 'etnlriaosc', 'seyrdtnlah'].

* Toán học của tôi trên 4176 có thể hơi ngắn do các từ có dấu gạch ngang hoặc dấu nháy đơn bị bỏ qua


1
Mặc dù giải pháp này là một heuristic tốt và có khả năng sẽ trả về một giải pháp tốt, tôi không tin rằng nó được đảm bảo để trả về giải pháp tối ưu. Lý do là bạn không nắm bắt được các ràng buộc giữa các cuộn phim: Bạn đang coi mỗi cuộn là một biến độc lập khi thực tế chúng phụ thuộc. Ví dụ, có thể là trường hợp các từ chia sẻ chữ cái đầu tiên phổ biến nhất có sự khác biệt lớn trong việc phân phối chữ cái thứ hai của chúng. Nếu đó là trường hợp, thì giải pháp của bạn có thể tạo ra các kết hợp các cuộn mà trên thực tế không cho phép bất kỳ từ nào.
ESultanik

1

Q

? (việc cần làm)

Các từ nên được lưu trữ trong một tập tin gọi là words

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

Chạy trong khoảng 170 ms trên i7 của tôi. Nó phân tích danh sách từ, tìm kiếm chữ cái phổ biến nhất ở mỗi vị trí (rõ ràng là lọc ra bất kỳ ứng cử viên nào). Đó là một giải pháp ngây thơ lười biếng nhưng tạo ra kết quả khá tốt với mã tối thiểu.

Các kết quả:

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

Bạn đã tìm thấy bao nhiêu từ 5 chữ cái?
DavidC

Tôi đã làm điều tương tự trong python và đã 16353.
cardboard_box

Đây có phải là thuật toán tham lam giống như của FakeRainBrigand không?
Peter Taylor

1
@cardboard_box, kết quả của bạn chắc chắn sai. Không có nhiều từ 5 chữ cái trong từ điển.
Peter Taylor

1
Đúng, đó là 1115. Tôi đã đếm số lượng chữ cái chính xác trong bất kỳ từ nào thay vì số lượng từ chính xác. Tôi nghĩ rằng tôi cần một cà phê khác.
tông_box

0

Chỉnh sửa: Bây giờ các quy tắc đã được sửa đổi, phương pháp này bị loại. Tôi sẽ để nó ở đây trong trường hợp có ai quan tâm cho đến khi cuối cùng tôi sửa đổi nó cho các quy tắc mới.

Python: 277 Ký tự

Tôi khá chắc chắn rằng phiên bản tổng quát của vấn đề này là NP-Hard và câu hỏi không yêu cầu tìm giải pháp nhanh nhất , vì vậy đây là một phương pháp mạnh mẽ để thực hiện:

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)

Lưu ý rằng tôi đã đổi tên tệp danh sách từ thành "w" để lưu một vài ký tự.

Đầu ra là số lượng từ có thể có từ một cấu hình nhất định, theo sau là chính cấu hình đó:

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

Dòng đầu ra cuối cùng trước khi chương trình kết thúc được đảm bảo là giải pháp tối ưu.


Tôi rất thích xem phiên bản C hoặc ASM của mã của bạn để nó thực sự có thể kết thúc trong năm nay :-) Hoặc ít nhất là chạy nó cho đến khi nó đến 1116. Bạn có thể viết nó mà không cần itertools không, vì vậy tôi có thể chạy nó trên jython ? (nhanh hơn trăn thông thường, nhưng dễ hơn cython.)
Brigand

Nevermind về điều jython. Tôi cần phải lấy alpha. Nó vẫn bị sập (quá nhiều bộ nhớ) nhưng điều đó dường như không thể tránh khỏi.
Brigand

Tôi khá chắc chắn rằng ngay cả khi điều này được triển khai trong lắp ráp, sẽ mất nhiều thời gian hơn cả đời để hoàn thành phần cứng hiện tại :-P
ESultanik

Vấn đề là tôi đang lặp đi lặp lại (26 chọn 10) ^ 5 ≈ 4.23 * 10 ^ 33 khả năng. Ngay cả khi chúng ta có thể kiểm tra một khả năng mỗi nano giây, thì sẽ mất khoảng 10 ^ 7 lần tuổi hiện tại của vũ trụ để kết thúc.
ESultanik

1
Có hai ký tự không xuất hiện ở vị trí thứ 5 trong bất kỳ từ nào trong danh sách từ đã cho, do đó bạn có thể giảm số lượng khả năng xuống khoảng 4. Đó là cách tôi nhận được "khoảng 110,3 bit" trong nhận xét của mình về câu hỏi.
Peter Taylor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.