我目前的解决方案
1)获取可以用这些字母(anagram generator)制作的所有可能的4个字母单词的列表,并将它们分配给数组.
2)循环遍历每个单词,在每一行中尝试它,同时检查每个单词的正确数量是否被使用.
3)检查anagram数组中是否存在每列中创建的单词.
逻辑工作,但它已经运行了一个多小时,我在400字节的字谜词200.有什么建议?
namespace GridWords { class Program { static void Main(string[] args) { string[] words = new string[] { "zoon","zonk","zone","zona","zoea","zobo","zero","zerk","zeal","zack","rore","roon","rook","rood","rone","role","roke","roed","rode","rock","roch","robe","roar","roan","road","rhea","rend","redo","reck","rear","rean","real","reak","read","raze","rare","rank","rand","rana","rale","rake","rade","rack","rach","race","raca","orzo","orra","orle","ordo","orca","oral","orad","ooze","oner","once","oleo","olea","olde","okra","okeh","ohed","odor","odea","odal","odah","oche","obol","oboe","nork","noob","nook","nolo","nole","noel","node","nock","nerk","nerd","neck","near","neal","naze","nark","nare","nard","narc","nala","nada","nach","nabk","nabe","lorn","lore","lord","loor","loon","look","lone","loke","lode","loco","lock","loch","loca","lobo","lobe","loan","load","leno","lend","lehr","lech","lear","lean","leak","lead","lazo","laze","larn","lark","lare","lard","lank","lane","land","lana","lakh","lake","laer","lade","lack","lace","krab","kore","kora","kond","kolo","kola","kohl","koel","kobo","koan","knob","knar","khor","khan","kern","kerb","keno","kbar","karn","kara","kaon","kane","kana","kale","kaed","kade","horn","hore","hora","hoon","hook","hood","honk","hone","hond","holk","hole","hold","hoke","hoer","hoed","hock","hobo","hoar","hero","hern","herl","herd","herb","hend","helo","held","heck","hear","heal","head","haze","haro","harn","harl","hark","hare","hard","hank","hand","halo","hale","hake","haka","haen","haed","hade","hack","haar","eorl","eoan","enol","elan","ecod","echo","ecad","ebon","earn","earl","eard","each","dzho","drek","drab","doze","dorr","dork","dore","door","dool","dook","doob","done","dona","dole","doer","doen","doek","dock","doab","dhal","dhak","dern","deco","deck","dear","dean","deal","daze","darn","darl","dark","dare","darb","dank","dale","dahl","dace","daal","czar","cred","cran","crab","coze","corn","cork","core","cord","coon","cool","cook","conk","cone","cond","cole","cold","cola","coke","coho","coed","code","coda","coal","clon","clod","clan","clad","chon","chez","cher","char","chao","chal","chad","cero","carr","carn","carl","cark","care","card","carb","cane","calo","calk","cake","cade","caba","broo","brod","brer","bren","bred","bran","brae","brad","bozo","born","bork","bore","bord","bora","boor","boon","bool","book","booh","bonk","bone","bond","bona","bolo","bole","bold","bola","boko","boke","boho","bode","bock","boar","boak","bloc","bled","blah","blae","blad","bhel","berk","bend","beck","bear","bean","beak","bead","barn","bark","bare","bard","bank","bane","band","banc","balk","bale","bald","bake","bael","bade","back","bach","baal","azon","azan","arna","arle","ared","area","arco","arch","arba","arar","arak","anoa","ankh","ance","anal","aloe","alod","alec","albe","alba","alar","alan","alae","aked","ahed","aero","aeon","adze","acre","acne","ache","acer","aced","able","abed","abac" }; char[] letters = new char[] { 'a','a','b','c','d','e','h','k','l','n','o','r','z' }; for (int z = 0; z < words.Length; z++) { Console.WriteLine(z); for (int y = 0; y < words.Length; y++) { bool letterCountCorrect0 = true; char[] wordLetters0 = words[z].tocharArray().Concat(words[y].tocharArray()).ToArray(); for (int a = 0; a < wordLetters0.Length; a++) { if (countInstances(wordLetters0,wordLetters0[a]) != countInstances(letters,wordLetters0[a])) { letterCountCorrect0 = false; break; } } if (y != z && letterCountCorrect0) { for (int x = 0; x < words.Length; x++) { bool letterCountCorrect1 = true; char[] wordLetters1 = words[z].tocharArray().Concat(words[y].tocharArray()).Concat(words[x].tocharArray()).ToArray(); for (int a = 0; a < wordLetters0.Length; a++) { if (countInstances(wordLetters0,wordLetters0[a])) { letterCountCorrect1 = false; break; } } if (x != y && x != z && letterCountCorrect1) { for (int w = 0; w < words.Length; w++) { bool letterCountCorrect2 = true; char[] wordLetters2 = words[z].tocharArray().Concat(words[y].tocharArray()).Concat(words[x].tocharArray()).Concat(words[w].tocharArray()).ToArray(); for (int a = 0; a < wordLetters0.Length; a++) { if (countInstances(wordLetters0,wordLetters0[a])) { letterCountCorrect2 = false; break; } } if (w != x && w != y && w != z && letterCountCorrect2) { char[] row1 = words[z].tocharArray(); char[] row2 = words[y].tocharArray(); char[] row3 = words[x].tocharArray(); char[] row4 = words[w].tocharArray(); char[] wordLetterArray = row1.Concat(row2).Concat(row3).Concat(row4).ToArray(); Array.Sort(wordLetterArray); if (wordLetterArray == letters) { string col1 = new string(new char[] { row1[0],row2[0],row3[0],row4[0] }); if (col1 != words[z] && col1 != words[y] && col1 != words[x] && col1 != words[w]) { string col2 = new string(new char[] { row1[1],row2[1],row3[1],row4[1] }); if (col2 != words[z] && col2 != words[y] && col2 != words[x] && col2 != words[w]) { string col3 = new string(new char[] { row1[2],row2[2],row3[2],row4[2] }); if (col3 != words[z] && col3 != words[y] && col3 != words[x] && col3 != words[w]) { string col4 = new string(new char[] { row1[3],row2[3],row3[3],row4[3] }); if (col4 != words[z] && col4 != words[y] && col4 != words[x] && col4 != words[w]) { if (words.Contains<String>(col1.ToLower()) && words.Contains<String>(col2.ToLower()) && words.Contains<String>(col3.ToLower()) && words.Contains<String>(col4.ToLower())) { Console.WriteLine(new string(row1) + " " + new string(row2) + " " + new string(row3) + " " + new string(row4)); //Console.WriteLine(col1.ToString() + " " + col2.ToString() + " " + col3.ToString() + " " + col4.ToString()); } } } } } } } } } } } } } } private static int countInstances(char[] arrToSearch,char charToFind) { int count = 0; for (int x = 0; x < arrToSearch.Length; x++) { if (arrToSearch[x] == charToFind) { count++; } } return count; } } }
这是一个例子,按要求:
给定字母“N,O,O和T”找到一个解决方案,其中这些字母适合2×2网格,以便在横向和向下阅读时,可以创建英文单词.答案是:
T O O N
除了这个问题是4×4网格.
更新:谢谢你的帮助,但我是个白痴.我没有修复我的复制/粘贴变量(我想,这可以追溯到那个建议我重构的人).此外,我比较数组的方式是错误的.修正了这些问题,并针对已知的工作单词列表,像魅力一样工作.再次对着我的原始数据,花了13秒.没有结果.再次感谢你的帮助.
更新2:由于我没有足够的代表回答我自己的问题,这是我的工作代码(…代码已删除…请参阅下面的dasblinklight的答案)
更新3:请参阅下面的dasblinkenlight的答案.更优雅,更少的循环.谢谢!
解决方法
您需要一种有效的方法来管理您当前使用的字母集.处理它的一种方法是创建一个计数器数组,如下所示:
static readonly int[] Counts = new int[256]; static void Add(string s) { foreach (var c in s) { Counts[c]++; } } static bool Sub(string s) { var res = true; foreach (var c in s) { res &= --Counts[c] >= 0; } if (!res) { Add(s); } return res; }
Sub(string)尝试从计数中“减去”该单词,如果成功则返回true.添加(字符串)将单词添加回计数.
现在您可以编写代码的四向嵌套框架,如下所示:
foreach (var w0 in Words) { if (!Sub(w0)) continue; foreach (var w1 in Words) { if (!Sub(w1)) continue; foreach (var w2 in Words) { if (!Sub(w2)) continue; foreach (var w3 in Words) { if (!Sub(w3)) continue; // Check if the w0..w3 combination yields four valid words // when you read it vertically,and restore the state Add(w3); } Add(w2); } Add(w1); } Add(w0); }
垂直单词的检查会添加第五个和最后一个嵌套级别.我将单词转换为哈希集以加快检查:
var allExist = true; for (var i = 0; allExist && i != 4; i++) { vert[0] = w0[i]; vert[1] = w1[i]; vert[2] = w2[i]; vert[3] = w3[i]; allExist = Words.Contains(new string(vert)); } if (allExist) { found = true; Console.WriteLine(w0); Console.WriteLine(w1); Console.WriteLine(w2); Console.WriteLine(w3); Console.WriteLine(); }
您可以找到this program on the pastebin.它可以在我的计算机上完成几分钟而无需生成解决方案.我确认它找到了存在的解决方案(但是当您注释掉单词和字母并取消注释最后两行时,程序会找到有效组合及其转置图像).