算法拼写比赛
今年早些时候,我写了一篇关于用MATLAB解决单词梯子的文章。这篇文章引起了很多人的兴趣,所以我想分享我对另一个基于文字的应用程序的调查。在这个脚本中,我试图创建一个基于文字的谜题纽约时报拼字比赛游戏。前提是:给你7个字母,你的任务是找出所有能用这7个字母组成的单词。您可以多次使用字母,但它们必须有四个或更多字母长,并且它们都必须包括特殊的中间字母。每个拼字比赛都至少有一个“pangram”,这是一个用了所有七个字母的单词。
举个例子,假设你遇到了这个难题。
从这个难题,你可以创建PORE, ADORE, ADOPT,以及pangram操作。但你不能创建POD(太短)或PAPER(不包括中间的字母“O”)。
这里我对解谜不太感兴趣。我想写一个可以创建拼写比赛的脚本。
建立字典
我们需要一些基本事实来解释所有的法律词汇。这是谷歌的万字英语字典。它很小,但对于我们这里的目的来说已经足够了。
url =“https://raw.githubusercontent.com/first20hours/google - 10000 english/master/google - 10000 english.txt”;
wordList = urlread(url);
将单词列表拆分为字符串。
words = split(string(wordList));
单词=较低(单词);
拼字比赛的谜题避免了字母S,这样就不用处理复数了。让我们使用逻辑索引来只保留不包含S的单词。
Keep = ~words.contains(“s”);
Words = Words (keep);
在这些单词中,只保留四个字母或更长的单词。
Keep =单词。Strlength >= 4;
Words = Words (keep);
我喜欢这些字符串命令易于阅读和理解!就像我们人类一样,能够清晰沟通的代码能够保持最长的工作时间。我们不想使用繁琐的、高维护的代码。
我们最后有多少个单词?
流("调整后的字典现在包含%d个单词\n"长度(字))
我们的字典里大约有一半的词被删掉了。
我们将几次将ASCII表示转换为字母数字,因此让我们投资一个小小的匿名帮助函数。这将使下面的代码更容易阅读。
一个匿名函数将ASCII值转换为A=1, B=2,…Z = 26。
Ascii2letter = @(chars) abs(low (chars))-96;
试试吧
ascii2letter (“ABCXYZ”)
看起来不错!
构建一个26列的稀疏矩阵来表示每个单词的唯一字母用法。字典里的每个单词都有一行。单词中出现的每个字母都是1。
dictionaryLength = nummel (words);
a = sparse(dictionaryLength,26);
为i = 1:dictionaryLength
uniqueLetters = unique(words(i).char);
a(i,ascii2letter(uniqueLetters)) = 1;
结束
nnz (a) /元素个数(a)
在22%满的情况下,这个矩阵并不像稀疏矩阵那样稀疏。但这是一个玩SPARSE的有趣借口,所以让我们继续吧。这是矩阵的间谍图。
间谍(a)
集(gca),…
XTick = 1,…
XTickLabel = num2cell (“一个”:“Z”),…
XTickLabelRotation = 0,…
XAxisLocation =“顶级”,…
PlotBoxAspectRatio=[1 1 1])
为了更好地理解这一点,我们需要放大。让我们看看单词LABEL是如何编码的。
Ix = 1002;
如果你想知道,我喜欢用“ix”作为“index”的缩写
单词(第九)
完整的((第九,:))
间谍((1001:1010:))
Xline ([1 2 5 12])
yline(2,颜色=“红色”)
集(gca),…
XTick = 1,…
XTickLabel = num2cell (“一个”:“Z”),…
XTickLabelRotation = 0,…
XAxisLocation =“顶级”,…
YTick = 1:10,…
YTickLabels =话说(1001:1010))
请注意,尽管L在单词中出现了两次,但它在矩阵中只有一个1。
为了好玩,我们做一个字母的直方图。这可能是一个有用的健全检查,我们是否在正确的轨道上。
allLetters = ascii2letter(char(join(words)”)));
直方图(allLetters)
集(gca),…
XTick = 1,…
XTickLabel = num2cell (“一个”:“Z”),…
XTickLabelRotation = 0)
不出所料,E是最常出现的字母。Q是最小的,但事实上我们完全消去了S。
有多少单词是由七个完全不同的字母组成的?也就是说,一款游戏有多少个潜在的pangram ?
行间字母使用的总和
使用FIND为所有恰好使用7个字母的单词建立索引
ix7LetterWords = find(sum(a,2)==7);
长度(ix7LetterWords)
让我们来看看这些七个字母的单词。
num7LetterWords = nummel (ix7LetterWords);
ix = ix7LetterWords(1:10);
disp(单词(第九(1:10)))
为我们的游戏选择一个优秀的“种子”。
Ix = Ix (9);
disp(话说(ix))
这7个字母能拼出多少个单词?找出所有只使用种子词中的字母的单词
lettersInSeedWord = a(ix,:);
找出所有没有一个种子词字母的单词。。
我们确保所有的信件除了。
种子字母的和为零。
ixWordsFromSeedWord = find(sum(a(:,~lettersInSeedWord),2) == 0);
流(%d单词只使用种子单词中出现的七个字母。元素个数(ixWordsFromSeedWord))
哪些字母出现频率最高?
栏(和((ixWordsFromSeedWord,:)))
集(gca),…
XTick = 1,…
XTickLabel = num2cell (“一个”:“Z”),…
XTickLabelRotation = 0)
我们需要指定一个字母作为“中心字母”,必须出现在每个单词中。让我们选出出现频率最低的字母。
vals = full(sum(a(ixWordsFromSeedWord,:)));
val (Vals ==0) = inf;
[~,ixlet] = min(vals);
centerLetter = char(ixlet+96);
去掉所有不含这个字母的单词
ixRequired = find(a(:,ixlet));
ix2a =相交(ixWordsFromSeedWord,ixRequired);
这是最初的种子词:
流(“% s \ n”、单词(ix))
以下是七个独特的字母:
sevenLetters = unique(char(words(ix)));
流(“% s \ n”, sevenLetters);
要求的中间字母是:
流(“% s \ n”上(centerLetter));
这是图
Ix3 = find(sum(a(ix2a,:),2)==7);
为I = 1:数字(ix3)
流(“% s \ n”单词(ix2a (ix3(我))));
结束
这里是完整的单词列表
为I = 1:数字(ix2a)
流(“% s \ n”单词(ix2a(我)));
结束
其中有些有点奇怪,但我们要感谢我们的字典。
sixLetters = setdiff(sevenLetters,centerLetter);
六字母=六字母(randperm(6));
现在来看图像!制作绘图
周长十六进制单元格以圆周率/6到11*圆周率/6弧度为中心
T = 2*pi*(0:5)/6 + 2*pi/12;
R = 1.08*√(3);
X = r*cos(t);
Y = r* sint;
班
hexplot(0, 0,上层(centerLetter),“# F7DA21”)
持有在
为I = 1:数字(x)
hexplot (x(我),(我),上层(sixLetters(我)),“# E6E6E6”)
结束
持有从
轴平等的
轴从
现在你知道了!一款优秀的算法生成游戏的价值显而易见。一旦你理清了逻辑,你只需要每天运行一次,你的谜题就准备好了。将这与填字游戏的劳动进行比较。不过谁知道呢?也许填字游戏将是人工智能被证明擅长的另一件事。
函数hexplot (x, y,字母,颜色)
T = linspace(0,2*pi,7);
补丁(cost + x,罪(t) + y,“白色”,…
EdgeColor =“没有”,…
FaceColor =颜色)
文本(x, y,信,…
字形大小= 24…
FontWeight =“大胆”,…
HorizontalAlignment =“中心”,…
VerticalAlignment =“中间”)
结束
评论
如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。