第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
用 Lua 编程 | ||
第一部分。语言 第 10 章。完整示例 |
我们的第二个示例是马尔可夫链算法的实现。该程序生成随机文本,基于n 个前一个单词在基本文本中可能跟随的单词。对于此实现,我们将使用n=2。
程序的第一部分读取基本文本,并构建一个表,对于每个两个单词的前缀,给出在文本中跟随该前缀的单词列表。构建表后,程序使用该表生成随机文本,其中每个单词都以与基本文本相同的概率跟随前两个单词。结果是,我们得到的文本非常接近随机,但又不完全随机。例如,当应用于本书时,程序的输出有如下片段:“构造函数还可以遍历一个表构造函数,然后下一行中的括号将整个文件存储在一个字段 n
中,以存储每个函数的内容,但只显示其唯一参数。如果您想找到一个数组中的最大元素,可以同时返回最大值,并继续显示提示并运行代码。以下单词是保留字,不能用于在度数和弧度之间转换。”
我们将用两个单词用空格连接起来对每个前缀进行编码
function prefix (w1, w2) return w1 .. ' ' .. w2 end我们使用字符串
NOWORD
("\n"
) 来初始化前缀单词并标记文本的结尾。例如,对于以下文本
the more we try the more we do跟随单词的表将是
{ ["\n \n"] = {"the"}, ["\n the"] = {"more"}, ["the more"] = {"we", "we"}, ["more we"] = {"try", "do"}, ["we try"] = {"the"}, ["try the"] = {"more"}, ["we do"] = {"\n"}, }
程序将其表保存在全局变量 statetab
中。要在该表的某个前缀列表中插入一个新单词,我们使用以下函数
function insert (index, value) if not statetab[index] then statetab[index] = {value} else table.insert(statetab[index], value) end end它首先检查该前缀是否已经有一个列表;如果没有,它将使用新值创建一个新列表。否则,它将使用预定义函数
table.insert
在现有列表的末尾插入新值。
要构建 statetab
表,我们保留两个变量 w1
和 w2
,其中包含最后读取的两个单词。对于每个前缀,我们保留一个列表,其中包含所有紧随其后的单词。
构建表后,程序开始生成包含 MAXGEN
个单词的文本。首先,它重新初始化变量 w1
和 w2
。然后,对于每个前缀,它从有效后续单词列表中随机选择一个后续单词,打印该单词,并更新 w1
和 w2
。接下来,我们展示完整的程序。
-- Markov Chain Program in Lua function allwords () local line = io.read() -- current line local pos = 1 -- current position in the line return function () -- iterator function while line do -- repeat while there are lines local s, e = string.find(line, "%w+", pos) if s then -- found a word? pos = e + 1 -- update next position return string.sub(line, s, e) -- return the word else line = io.read() -- word not found; try next line pos = 1 -- restart from first position end end return nil -- no more lines: end of traversal end end function prefix (w1, w2) return w1 .. ' ' .. w2 end local statetab function insert (index, value) if not statetab[index] then statetab[index] = {n=0} end table.insert(statetab[index], value) end local N = 2 local MAXGEN = 10000 local NOWORD = "\n" -- build table statetab = {} local w1, w2 = NOWORD, NOWORD for w in allwords() do insert(prefix(w1, w2), w) w1 = w2; w2 = w; end insert(prefix(w1, w2), NOWORD)
-- generate text w1 = NOWORD; w2 = NOWORD -- reinitialize for i=1,MAXGEN do local list = statetab[prefix(w1, w2)] -- choose a random item from list local r = math.random(table.getn(list)) local nextword = list[r] if nextword == NOWORD then return end io.write(nextword, " ") w1 = w2; w2 = nextword end
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |