paint-brush
SAINE về mặt toán học là một trong những từ bắt đầu WORDLE Tốt nhất - Đây là lý do tại saotừ tác giả@picocreator
1,910 lượt đọc
1,910 lượt đọc

SAINE về mặt toán học là một trong những từ bắt đầu WORDLE Tốt nhất - Đây là lý do tại sao

từ tác giả picocreator2022/04/15
Read on Terminal Reader
Read this story w/o Javascript

dài quá đọc không nổi

Làm thế nào SAINE được cho là từ bắt đầu dễ hiểu nhất. Được chứng minh bằng toán học và thống kê. Đánh bại những lời khuyên phổ biến như CRANE và ADEPT Mặc dù nó không nằm trong danh sách câu trả lời, nhưng nó là một từ hợp lệ. Vì vậy, nó có 0% cơ hội lúc đầu hãy thử đoán, nhưng tỷ lệ trúng cao hơn khoảng 2%. Mô hình thống kê trước đây tự giới hạn mình trong danh sách câu trả lời hợp lệ - do đó có sự khác biệt.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - SAINE về mặt toán học là một trong những từ bắt đầu WORDLE Tốt nhất - Đây là lý do tại sao
picocreator HackerNoon profile picture


TLDR: Tôi đã viết một bot giải Wordle với Javascript và UIlicious. Bạn có thể chạy lại hoặc chỉnh sửa đoạn mã này bất kỳ ngày nào để nhận giải pháp Wordle hàng ngày của mình. Hãy thử xem bạn có thể đạt điểm cao hơn bot không nhé! Hãy thoải mái chỉnh sửa nó và tối ưu hóa thuật toán giải!


Tiết lộ đầy đủ: Tôi là đồng sáng lập và CTO của Uilicious.com (được giới thiệu trong bài viết này)


Bộ giải wordler được bao gồm 3 phần, bao gồm

  • Mã tương tác giao diện người dùng (được liên kết tại đây)
  • Mô hình thống kê Wordle và toán học đằng sau nó (bài viết này)
  • Kiểm tra đơn vị và điểm chuẩn của trình giải từ ngữ (@todo)


Tất cả các ví dụ thống kê có thể được tìm thấy tại liên kết sau: https://uilicio.us/wordle-stosystem-sample Và được tạo thông qua mã được sử dụng tại đây: https://github.com/uilicious/wordle-solver-and-tester


Mèo lên kế hoạch cho chiến lược Wordle của chúng tôi


Chiến lược WORDLE của chúng tôi

Tuyên bố từ chối trách nhiệm, tôi không khẳng định đây là chiến lược WORDLE tốt nhất (chưa), nhưng nó là một chiến lược khá tốt =)


Trước khi đi vào các số liệu thống kê, trước tiên hãy đề cập đến chiến lược WORLDE của chúng tôi.


Một điều mà con người thực sự làm tốt mà các máy tính cổ điển không tốt là "trực giác" tìm ra mọi thứ. Trừ khi tôi định đào tạo mạng nơ-ron, chương trình máy tính mà tôi đang phát triển sẽ cần sử dụng danh sách từ điển cổ điển để đưa ra các phỏng đoán.


Tuy nhiên, một điều mà máy tính làm tốt là ghi nhớ danh sách từ hoặc dữ liệu khổng lồ. Và thực hiện toán học trên đó. Vì vậy, hãy sử dụng điều này để làm lợi thế của chúng tôi bằng cách thực hiện trình tự sau.


Đưa ra danh sách 2 từ, một có đầy đủ các câu trả lời có thể (~ 2,3 nghìn từ) và một danh sách khác có danh sách từ đầy đủ (13 nghìn từ) ...


  • Lọc ra các từ trong danh sách câu trả lời có thể có so với trạng thái trò chơi hiện tại từ các lần đoán trong quá khứ.

  • Đếm số lần mỗi ký tự xuất hiện trong danh sách từ trả lời ở các vị trí từ tương ứng của chúng.

  • Từ danh sách từ đầy đủ, hãy chọn từ có nhiều khả năng tìm được một phép đoán ký tự chính xác nhất. Ghi bàn một cách độc lập, ưu tiên những từ cung cấp nhiều thông tin hơn trong 4 vòng đầu tiên với một trận đấu chính xác hoặc một phần.

  • Chọn từ đạt điểm cao nhất và thử nó.

  • Lặp lại từ đầu nếu cần.


Cũng cần làm rõ: Chúng tôi không ghi nhớ các giải pháp Wordle trước đó (tôi cảm thấy điều đó đang gian lận vì cuối cùng hệ thống có thể chỉ ghi nhớ danh sách hàng ngày theo trình tự).


Trong khi các chi tiết chính xác của điểm thay đổi một chút tùy thuộc vào vòng - để tối ưu hóa mọi thứ. Nó không thay đổi khái niệm tổng thể ở cấp độ cao.


Vậy điều này hoạt động như thế nào trong thực tế? Đối với lần lặp lại chiến lược Wordle hiện tại của chúng tôi, chúng tôi sẽ xem điều này trong thực tế từng bước (không có mã).


Đếm số liệu thống kê là "dễ dàng"

Từ bắt đầu của chúng tôi: SAINE - và tại sao bạn nên sử dụng nó

Một bí danh cho sain, có nghĩa là: làm dấu thánh giá trên (chính mình) để ban phước hoặc bảo vệ khỏi điều ác hoặc tội lỗi


Đã có rất nhiều lời khuyên về 2 từ bắt đầu. Và có nghĩa là từ này theo sau với:

  • 3 nguyên âm rất phổ biến
  • Tất cả các ký tự duy nhất


Nhưng hãy tìm ra lý do tại sao người giải chọn từ này bằng cách nhìn vào các con số.


Thống kê các ký tự trong Wordle.


Dựa trên các số liệu thống kê. "SAINE" có cơ hội cao nhất để tìm thấy một ký tự màu xanh lá cây khớp chính xác làm từ mở đầu trong khi có 3 trong số các nguyên âm hàng đầu.


Đọc bảng phân phối thô có thể khó hiểu. Vì vậy, hãy để tôi văn bản hóa lại những con số đó ở đây. SAINE có một…

  • 91,06% cơ hội khớp một phần ít nhất 1 ký tự (vàng / xanh lá cây);
  • 55,94% cơ hội khớp một phần ít nhất 2 ký tự (vàng / xanh lá cây);
  • 50,24% cơ hội khớp chính xác ít nhất 1 ký tự (màu xanh lá cây).


Cơ hội thực sự cao để có được ít nhất một hoặc 2 manh mối chính. Ngược lại, vì có ít từ không có A, I và E nên việc không ghép được là một "manh mối lớn".


Không tệ cho một buổi khai mạc phải không?


Còn những từ mở đầu phổ biến khác như "CRANE" và "ADEPT" thì sao?


Thống kê đoán từ đầu tiên cho SAINE, CRANE và ADEPT.


Lợi thế chính duy nhất, đối với "CRANE / ADEPT" là cả hai đều có 0,04% cơ hội thực hiện thành công phép đoán 1 từ. Tôi nghi ngờ lỗ hổng của phân tích công khai trước đó là cách họ giới hạn từ mở đầu trong danh sách câu trả lời đã biết. Tuy nhiên, tôi tin rằng chúng ta nên sử dụng danh sách từ đầy đủ để tối đa hóa xác suất của các manh mối có lợi cho cơ hội thực hiện phỏng đoán 1 từ rất hẹp.


Quan trọng hơn, SAINE có cơ hội đoán chính xác trận đấu (màu xanh lá cây) cao hơn đáng kể (khoảng 7%) trong lần thử đầu tiên. Đó là một đầu mối cực kỳ hữu ích.


Với cuộc tranh luận từ bắt đầu, chúng ta sẽ xem cách hệ thống phản ứng với các kết quả khác nhau!


Wordle kết quả trước và sau khi chuyển sang NYTimes.


Hiểu cách PLUTO dự đoán thứ 2, dẫn đến TẠM DỪNG

Vì vậy, chúng ta hãy xem xét cách từ thứ 2 được chọn cho câu trả lời "TẠM DỪNG" (phía bên tay trái).


Chúng tôi được cung cấp thông tin sau:

  • Chữ I & N không có trong từ.

  • A là ký tự thứ 2, E là ký tự thứ 5.

  • S là ký tự thứ 3 hoặc thứ 4 (nó không phải là ký tự đầu tiên).

  • Chỉ có 12 câu trả lời có thể có trong danh sách từ


Công cụ Wordle khá chuẩn. Nhưng hãy xem điều này ảnh hưởng như thế nào đến các số liệu thống kê đối với các câu trả lời có thể còn lại. Và “PLUTO” đã được chọn như thế nào.


Thống kê các ký tự từ thứ 2 khi câu trả lời là TẠM DỪNG.


Chỉ còn 12 từ, chúng ta hãy tìm cách hiệu quả nhất để loại bỏ các tùy chọn của chúng ta.


  • Bởi vì chúng tôi đã có thông tin về các chữ cái S, E, A, hệ thống tính điểm của chúng tôi sẽ tránh chúng bằng một hình phạt (được đánh dấu màu đỏ).
  • Xác suất lớn nhất tiếp theo của các ký tự ở các vị trí mà chúng ta chưa biết là P, U và T, lần lượt ở các vị trí 1, 3 và 4 (được đánh dấu bằng màu cam).
  • Cuối cùng, vì chúng ta đã giải quyết được vị trí 2 và 5, chúng ta có thể tận dụng điều này để có thêm thông tin. Vì vậy, chúng ta hãy cố gắng hết sức để sử dụng các ký tự L & C.


Từ các ràng buộc sau, từ hợp lệ duy nhất để thử là PLUTO. Mặc dù chúng tôi biết chữ O không có trong câu trả lời cuối cùng, nhưng không có từ nào cho “PLUTC”. Ngoài ra, mặc dù từ PLUTO không có trong danh sách câu trả lời, nhưng nó đã có trong danh sách từ đầy đủ, khiến nó trở thành một dự đoán hợp lệ.


Sau khi gửi, hệ thống bây giờ biết những điều sau:

  • L, T, O không có trong từ (O là xác nhận của một giả định).
  • P là ký tự thứ nhất, U là ký tự thứ 3.
  • S là ký tự thứ 4 (có thể không còn là ký tự thứ 3).


Điều này có nghĩa là tôi không cần số liệu thống kê nữa vì chỉ có một sự thật: TẠM DỪNG.


cúi đầu nhảy theo một câu trả lời thành công

Nhưng với mô hình đoán điên rồ là gì? Với MOHUR, BLYPE và cuối cùng là ULCER

Mohur là một đồng tiền vàng trước đây được đúc bởi một số chính phủ, bao gồm cả Ấn Độ thuộc Anh và một số quốc gia tư nhân tồn tại cùng với nó.


Các số liệu thống kê ở đây đang được đánh giá trực tiếp và những thay đổi phụ thuộc vào kết quả của mỗi hiệp đấu. Vì vậy, kết quả khác nhau ở chỗ:

  • Chữ S, A, I, N không có trong từ.

  • Chữ E có thể ở vị trí 1, 2, 3, 4 nhưng không phải là 5.


Lọc ra danh sách câu trả lời có thể dẫn đến các thống kê sau:


Thống kê các ký tự từ thứ 2. Khi câu trả lời là ULCER.


Điều này có thể không có ý nghĩa lúc đầu vì từ này không bắt đầu bằng C hoặc B. Với 187 từ còn lại, đây là lúc các chi tiết về điểm bắt đầu quan trọng.


  • Một lần nữa, chúng ta bỏ qua chữ E, đây là thông tin mà chúng ta đã biết (màu đỏ).
  • Chữ R ở cuối có trọng số cao nhất (62 từ) bởi một lề lớn. Việc tìm ra câu trả lời cho nhân vật này sẽ làm giảm một nửa (không khớp) danh sách khả năng hoặc một phần ba (khớp).
  • Từ đây, bước tiếp theo là tìm từ có nhiều chữ trùng khớp nhất với các chữ cái khác ở các vị trí tương ứng, chẳng hạn như O ở vị trí 2 (điểm 37), tiếp theo là bất kỳ ký tự nào còn lại. Khớp với danh sách vị trí của họ hoặc danh sách các chữ cái duy nhất.


Đây có thể không phải là lựa chọn tối ưu nhất trong danh sách câu trả lời đã biết. Tuy nhiên, điều này là cố ý bởi vì, chúng tôi muốn tập trung vào thông tin một lần nữa cho đến khi chúng tôi có sự tin tưởng rất cao vào một từ. Và trong quá trình này, chúng tôi sẽ phạt các chữ cái trùng lặp để tập trung vào việc giảm số lượng tùy chọn. (Có thể cho rằng có chỗ cho những cải tiến ở đây)


Kết quả từ cuộc phỏng đoán thật thú vị.


Thống kê các ký tự từ thứ 3 khi câu trả lời là ULCER.


Kỳ lạ và khó hiểu như từ MOHUR, kết quả là giảm khả năng thành 12 từ. Một lần nữa, nó cố gắng ưu tiên thử các ký tự mới và gán cho nó từ khó hiểu là BLYPE.


BLYPE: một mảnh hoặc mảnh da


Từ này giảm danh sách các khả năng xuống còn một từ - ULCER, là câu trả lời cuối cùng.


Lưu ý phụ: Nếu bạn nhận thấy, nó sẵn sàng thử các ký tự mà nó biết không có trong danh sách câu trả lời chính thức. Đây là cố ý. Hãy tính đến các bản sao Wordle vì nếu câu trả lời thực được chọn không nằm trong danh sách câu trả lời ban đầu, hệ thống sẽ tự động quay trở lại sử dụng danh sách từ đầy đủ để thay thế. Làm cho điều này trở nên linh hoạt hơn trước các biến thể Wordle.


Minion đưa ra cảnh báo


⚠️ Cảnh báo mã phía trước: Nếu bạn chỉ ở đây để tính toán và số liệu thống kê thì hãy bỏ qua phần cuối. Nội dung còn lại trong bài viết này bao gồm mã JS.

Cho tôi xem mã

Lớp giải đầy đủ có thể được tìm thấy ở đây .


Bài viết này sẽ tập trung vào chức năng cốt lõi cần thiết để làm cho quá trình này hoạt động chứ không phải tất cả các phần của mã. Nếu bạn chưa đọc Phần 1, hãy đọc nó tại đây .


Mã ở đây đã được đơn giản hóa để bỏ qua nội dung "bảng mẫu".


Người giải cần thực hiện những việc sau:

  • Với trạng thái trò chơi hiện tại, hãy lọc danh sách từ có thể có.
  • Đưa ra danh sách từ đã lọc, hãy tính số liệu thống kê.
  • Với số liệu thống kê và trạng thái trò chơi, hãy ghi điểm từ sau chiến lược.
  • Đề xuất một từ.


Hãy để chúng tôi chia nhỏ nó ra, từng mảnh.

Chuẩn hóa Đối tượng trạng thái trò chơi (được tạo trong phần 1)

Đối với mỗi vòng, trạng thái trò chơi sẽ được tạo với:

  • .history []: Một loạt các phỏng đoán từ ngữ trong quá khứ.
  • .pos []: Một mảng các đối tượng chứa thông tin sau.
    • .hintSet: tập hợp các ký tự là "gợi ý" hợp lệ.
    • .foundChar: các ký tự được xác nhận cho vị trí đã cho.


Điều này được tạo ra bằng cách sử dụng thông tin trên màn hình trong phần 1.


Tuy nhiên, đối với trường hợp sử dụng của chúng tôi, chúng tôi sẽ cần chuẩn hóa một số tập dữ liệu phổ biến mà chúng tôi cần. Thông qua hàm _normalizeStateObj , chúng ta nhận được như sau.

  • badCharSet: Các ký tự mà chúng ta biết không có trong từ;
  • goodCharSet: Các ký tự mà chúng tôi đã xác nhận đều có trong từ.


Điều này dễ dàng được tạo ra bằng cách lặp lại .history và dữ liệu .pos để xây dựng danh sách ký tự tốt trước tiên. Sau đó, sử dụng nó để xây dựng danh sách nhân vật xấu ngược lại với danh sách từ lịch sử.


 /** * Given the state object, normalize various values, using the minimum "required" value. * This does not provide as much data as `WordleSolvingAlgo` focusing on the minimum required * to make the current system work * * @param {Object} state * * @return {Object} state object normalized */ function _normalizeStateObj( state ) { // Setup the initial charset state.badCharSet = new Set(); state.goodCharSet = new Set(); // Lets build the good charset for(let i=0; i<state.wordLength; ++i) { if( state.pos[i].foundChar ) { state.goodCharSet.add(state.pos[i].foundChar); } for(let char of state.pos[i].hintSet) { state.goodCharSet.add(char); } } // Lets iterate history and build badCharSet for(let i=0; i<state.history.length; ++i) { const word = state.history[i]; for( let w=0; w<word.length; ++w ) { // check the individual char let char = word.charAt(w); // If char is not in good set if( !state.goodCharSet.has(char) ) { // its in the bad set state.badCharSet.add(char); } } } // Return the normalize state object return state; }

Lọc danh sách từ có thể

Bây giờ chúng ta có trạng thái trò chơi hiện tại, chúng ta hãy xem xét việc lọc danh sách từ:

 /** * Given the wordList, filter only for possible answers, using the state object. * And returns the filtered list. This function just returns the wordList, if state == null * @param {Array<String>} wordList * @param {Object} state */ function filterWordList( wordList, state ) { // Skip if its not setup if( state == null || wordList.length <= 0 ) { return wordList; } // Get the word length const wordLength = wordList[0].length; // Filter and return return wordList.filter(function(s) { // Filtering logic // .... // all checks pass, return true return true; }); }


Đối với logic lọc, trước tiên chúng tôi xóa các từ trong badCharSET.

 // filter out invalid words (aka hard mode) for(const bad of state.badCharSet) { // PS : this does nothing if the set is empty if(s.includes(bad)) { return false; } }


Tiếp theo là lọc ra các từ có vị trí gợi ý sai:

 // filter out words with wrong hint locations, for each character position for(let i=0; i<wordLength; ++i) { // Get the word character let sChar = s.charAt(i); // Check if the chracter, conflicts with an existing found char (green) if(state.pos[i].foundChar && sChar != state.pos[i].foundChar) { return false; } // Check if the character is already a known mismatch (yellow, partial match) // for each position for(const bad of state.pos[i].hintSet) { if(sChar == bad) { return false; } } }


Đối với các từ tiếp theo mà không có tất cả các từ khớp đã biết (chính xác và một phần):

 // filter out words WITHOUT the hinted chars // PS : this does nothing if the set is empty for(const good of state.goodCharSet) { if(!s.includes(good)) { return false; } }


Ngoài ra, chúng tôi có một biến thể để lọc ra các từ duy nhất cho filterForUniqueWordList . Điều này không có ký tự trùng lặp và được sử dụng trong vài vòng đầu tiên:

 let wordCharSet = new Set(); // iterate the characters for(const char of s) { // Update the word charset wordCharSet.add(char); } // There is duplicate characters if( wordCharSet.size != s.length ) { return false; }

Tạo thống kê từ

Sau khi lọc tất cả các câu trả lời có thể còn lại, số liệu thống kê được tạo thông qua charsetStatistics( dictArray )


Điều này được thực hiện bằng cách xây dựng một đối tượng cho loại thống kê. Lặp lại danh sách từ và tăng các số:


 /** * Analyze the given dictionary array, to get character statistics * This will return the required statistics model, to be used in guessing a word. * * Which is provided in 3 major parts, using an object, which uses the character as a key, followed by its frequency as a number * * - overall : Frequency of apperance of each character * - unique : Frequency of apperance of each character per word (meaning, duplicates in 1 word is ignored) * - positional : An array of object, which provides the frequency of apperance unique to that word position * * Note that because it is possible for the dataset to not have characters in the list / positional location, * you should assume any result without a key, means a freqency of 0 * * @param {Array<String>} dictArray - containg various words, of equal length * * @return Object with the respective, overall / unique / positional stats **/ charsetStatistics( dictArray ) { // Safety check if( dictArray == null || dictArray.length <= 0 ) { throw `Unexpected empty dictionary list, unable to perform charsetStatistics / guesses`; } // The overall stats, for each character let overallStats = {}; // The overall stats, for each unique charcter // (ignore duplicates in word) let overallUniqueStats = {}; // The stats, for each character slot let positionalStats = []; // Lets initialize the positionalStats let wordLen = dictArray[0].length; for(let i=0; i<wordLen; ++i) { positionalStats[i] = {}; } // Lets iterate the full dictionary for( const word of dictArray ) { // Character set for the word const charSet = new Set(); // For each character, populate the overall stats for( let i=0; i<wordLen; ++i ) { // Get the character const char = word.charAt(i); // Increment the overall stat this._incrementObjectProperty( overallStats, char ); // Populate the charset, for overall unique stats charSet.add( char ); // Increment each positional stat this._incrementObjectProperty( positionalStats[i], char ); } // Populate the unique stats for( const char of charSet ) { // Increment the overall unique stat this._incrementObjectProperty( overallUniqueStats, char ); } } // Lets return the stats obj return { overall: overallStats, unique: overallUniqueStats, positional: positionalStats } }


Điều này khá đơn giản đối với các vòng lặp trên mọi từ và mọi ký tự tăng lên trong số thống kê tương ứng.


Điểm mấu chốt duy nhất là chúng ta không thể thực hiện tăng ++ trên một thuộc tính đối tượng khi nó chưa được khởi tạo. Điều này sẽ dẫn đến lỗi sau:

 // This will give an exception for // TypeError: Cannot read properties of undefined (reading 'a') let obj; obj["a"]++;


Vì vậy, chúng tôi sẽ cần sử dụng một hàm trợ giúp đơn giản để tăng trường hợp sử dụng cần thiết của chúng tôi một cách hợp lý:

 /** * Increment an object key, used at various stages of the counting process * @param {Object} obj * @param {String} key **/ _incrementObjectProperty( obj, key ) { if( obj[key] > 0 ) { obj[key]++; } else { obj[key] = 1; } } 


giám khảo cho điểm của họ

Cho điểm từng từ

Trọng tâm của bộ giải là logic tính điểm. Được xếp hạng trên mọi đầu vào từ có thể có với số liệu thống kê và trạng thái đã cho.


Tuyên bố từ chối trách nhiệm: Tôi không khẳng định rằng đây là chức năng chấm điểm từ tối ưu nhất dành cho Wordle. Nó chắc chắn có thể được cải thiện, nhưng nó khá tốt từ thử nghiệm của tôi cho đến nay. =)

 /** * The heart of the wordle solving system. * * @param {Object} charStats, output from charsetStats * @param {String} word to score * @param {Object} state object (to refine score) * * @return {Number} representing the word score (may have decimal places) **/ function scoreWord( charStats, word, state = null ) { // Character set for the word, used to check for uniqueness const charSet = new Set(); // the final score to return let score = 0; // Wordle Strategy note: // // - Penalize duplicate characters, as they limit the amount of information we get // - Priotize characters with high positional score, this helps increase the chances of "exact green matches" early // reducing the effort required to deduce "partial yello matches" // - If there is a tie, in positional score, tie break it with "unique" score and overall score // this tends to be relevent in the last <100 matches // // - We used to favour positional score, over unique score in the last few rounds only // but after several trial and errors run, we found it was better to just use positonal score all the way // Lets do scoring math // ... // Return the score return score; }


Điều này trải qua các giai đoạn khác nhau: Đầu tiên, chúng tôi thêm một mạng lưới an toàn để ngăn hệ thống đề xuất một từ lần nữa (điểm âm rất lớn).

 // Skip attempted words - like WHY ??? if( state && state.history ) { if( state.history.indexOf(word) >= 0 ) { return -1000*1000; } }


Sau đó, chúng tôi lặp lại từng ký tự của từ và cho điểm chúng tương ứng:

 // For each character, populate the overall stats for( let i=0; i<word.length; ++i ) { // Get the character const char = word.charAt(i); // Does scoring for each character // ... }


Xử phạt các từ có các ký tự lặp lại hoặc các ký tự đã biết:

 // skip scoring of known character matches // or the attempted character hints if( state ) { // Skip known chars (good/found) if( state.pos && state.pos[i].foundChar == char ) { score += -50; charSet.add( char ); continue; } // Skip scoring of duplicate char if( charSet.has( char ) ) { score += -25; continue; } // Skip known chars (good/found) if( state.goodCharSet && state.goodCharSet.has(char) ) { score += -10; charSet.add( char ); continue; } } else { // Skip scoring of duplicate char if( charSet.has( char ) ) { score += -25; continue; } } // Populate the charset, we check this to favour words of unique chars charSet.add( char );


Cuối cùng, chúng tôi tính điểm cho mỗi thống kê vị trí với điểm ký tự duy nhất được sử dụng làm điểm hòa:

 // Dev Note: // // In general - we should always do a check if the "character" exists in the list. // This helps handle some NaN situations, where the character has no score // this is possible because the valid list will include words, that can be inputted // but is not part of the filtered list - see `charsetStatistics` if( charStats.positional[i][char] ) { score += charStats.positional[i][char]*10000; } if (charStats.unique[char]) { score += charStats.unique[char] } // -- Loops to the next char -- //


Bây giờ chúng ta đã có chức năng tính điểm, chúng ta có thể bắt đầu tập hợp tất cả các phần lại cho hàm "suggestWord".


Đơn giản: bạn chỉ cần chọn một

Đề xuất một từ (ghép nó lại với nhau)

Chúng tôi có số liệu thống kê sau đó có thể được sử dụng để ghi điểm các từ. Bây giờ, chúng ta hãy tập hợp nó lại với nhau để đề xuất từ ghi điểm tốt nhất.


Chúng tôi bắt đầu với trạng thái trò chơi:

  • bình thường hóa trạng thái trò chơi;
  • tạo danh sách từ được lọc, duy nhất và đầy đủ.


 /** * Given the minimum state object, suggest the next word to attempt a guess. * * --- * # "state" object definition * * The solver, requires to know the existing wordle state information so this would consist of (at minimum) * * .history[] : an array of past wordle guesses * .pos[] : an array of objects containing the following info * .hintSet : set of characters that are valid "hints" * .foundChar : characters that are confirmed for the given position * * The above is compliant with the WordleAlgoTester state object format * Additional values will be added to the state object, using the above given information * --- * * @param {Object} state * * @return {String} word guess to perform */ suggestWord( state ) { // Normalize the state object state = this._normalizeStateObj(state); // Let'sLets get the respective wordlist let fullWordList = this.fullWordList; let filteredWordList = this.filterWordList( this.filteredWordList, state ); let uniqueWordList = this.filterForUniqueWords( this.uniqueWordList, state ); // As an object let wordList = { full: fullWordList, unique: uniqueWordList, filtered: filteredWordList }; // Lets do work on the various wordlist, and state // this is refactored as `suggestWord_fromStateAndWordList` // in the code base // .... }


Khi chúng tôi có các trạng thái trò chơi và danh sách từ khác nhau, Chúng tôi có thể quyết định "danh sách từ thống kê", chúng tôi sử dụng để tạo mô hình thống kê.


 // Let's decide on which word list we use for the statistics // which should be the filtered word list **unless** there is // no possible answers on that list, which is possible when // the system is being used against a WORDLE variant // // In such a case, lets fall back to the filtered version of the "full // word list", instead of the filtered version of the "answer list". let statsList = wordList.filtered; if( wordList.filtered == null || wordList.filtered.length <= 0 ) { console.warn("[WARNING]: Unexpected empty 'filtered' wordlist, with no possible answers : falling back to full word list"); statsList = this.filterWordList( wordList.full, state ); } if( wordList.filtered == null || wordList.filtered.length <= 0 ) { console.warn("[WARNING]: Unexpected empty 'filtered' wordlist, with no possible answers : despite processing from full list, using it raw"); statsList = wordList.full; }


Khi chúng tôi quyết định danh sách từ thống kê, chúng tôi nhận được số liệu thống kê:

 // Get the charset stats const charStats = this.charsetStatistics(statsList);


Bây giờ chúng ta quyết định danh sách từ sẽ sử dụng để quyết định một từ. Chúng tôi gọi danh sách này là "Danh sách ghi điểm".


Trong vài vòng đầu tiên, chúng tôi đặt mục tiêu sử dụng các từ độc đáo càng nhiều càng tốt. Điều này sẽ không bao gồm các ký tự mà chúng tôi đã thử trước đây. Điều này có thể bao gồm những từ mà chúng tôi biết không có trong danh sách câu trả lời có thể.


Điều này là có chủ đích vì chúng tôi đang tối ưu hóa để thu được thông tin nhưng thay vào đó dựa trên một cơ hội thành công sớm ngẫu nhiên.


Tuy nhiên khi điều này bị trống, hoặc trận đấu đang ở vài hiệp cuối, chúng tôi sẽ quay trở lại danh sách đầy đủ. Trong suốt vòng chung kết, chúng tôi sẽ luôn đoán bằng cách sử dụng danh sách đã lọc khi có thể: (chỉ cần đưa ra câu trả lời tốt nhất của chúng tôi).


 // sort the scored list, use unique words in first few rounds let scoredList = wordList.unique; // Use valid list from round 5 onwards // or when the unique list is drained if( scoredList.length == 0 || state.round >= 5 ) { scoredList = wordList.full; } // Use filtered list in last 2 round, or when its a gurantee "win" if( wordList.filtered.length > 0 && // (wordList.filtered.length < state.roundLeft || state.roundLeft <= 1) // ) { scoredList = wordList.filtered; }


Khi chúng tôi quyết định danh sách tính điểm để áp dụng số liệu thống kê, Hãy để chúng tôi chấm điểm và sắp xếp nó:

 // Self reference const self = this; // Score word sorting scoredList = scoredList.slice(0).sort(function(a,b) { // Get the score let bScore = self.scoreWord( charStats, b, state, finalStretch ); let aScore = self.scoreWord( charStats, a, state, finalStretch ); // And arrange them accordingly if( bScore > aScore ) { return 1; } else if( bScore == aScore ) { // Tie breakers - rare // as we already have score breakers in the algori if( b > a ) { return 1; } else if( a > b ) { return -1; } // Equality tie ??? return 0; } else { return -1; } });


Và trả về mục có điểm cao nhất:

 // Return the highest scoring word guess return scoredList[0]; 


4 chú chó con, hóa trang thành những người báo thù


Để tất cả chúng cùng nhau

Với mã tương tác giao diện người dùng được thực hiện trong phần 1. Nhấn nút "Chạy" để xem cách bot Wordle của chúng tôi hoạt động như thế nào!

Ghi màn hình từ ngữ đang được giải


Này, không tệ, bot của tôi đã giải được Wordle hôm nay!


Con người và robot là bạn


Mang đi - cho con người?

Vì các bot sẽ sử dụng một kỹ thuật tính toán xác suất khá “phi nhân tính” với những cuốn từ điển khổng lồ.


Hầu hết mọi người sẽ thấy rằng đây là ranh giới của việc thực hiện những phỏng đoán thực sự kỳ lạ và điên rồ. Hãy tin vào toán học bởi vì nó hoạt động.


Khi chơi cho đội con người, điều rút ra từ bài viết này là bạn chỉ nên bắt đầu bằng từ "SAINE", hoặc bất kỳ từ nào bạn muốn.


Đó là vào bạn vì đây là trò chơi của bạn sau tất cả! =) Chúc bạn vui vẻ.


Chúc mừng Wordling! 🖖🏼🚀


Lần đầu tiên được xuất bản tại đây