如何为Lua预定义随机数表实现的字符串shuffle函数编写对应还原函数
实现思路
首先明确这套shuffle的核心逻辑:
- 长度为n的原字符串,每个原索引位置
i(从1开始计数)会绑定固定权重randomValues[i] - 按权重从小到大排序所有(原索引, 字符)对,排序后的顺序就是打乱后的字符串顺序,即:打乱后字符串的第j位 = 原字符串的第sorted_index[j]位,其中
sorted_index是所有原索引按对应randomValues值升序排序后的数组
还原逻辑是反向映射即可:
- 对目标长度n,提前计算出
sorted_index数组:把1~n的索引按randomValues[i]升序排序,得到sorted_index,sorted_index[j]就是打乱后第j位对应的原索引 - 构建还原数组:还原后的字符串的第
sorted_index[j]位 = 打乱后字符串的第j位 - 拼接还原数组得到原字符串
完整实现代码
-- 保留你原有的shuffle相关代码 randomValues = {} for i = 1, 60 do table.insert(randomValues, 1, math.random()) end function shuffle(str) math.randomseed(4) local letters = {} local idx = 0 for letter in str:gmatch'.[\128-\191]*' do idx = idx + 1 table.insert(letters, {letter = letter, rnd = randomValues[idx]}) end table.sort(letters, function(a, b) return a.rnd < b.rnd end) for i, v in ipairs(letters) do letters[i] = v.letter end return table.concat(letters) end -- 新增unscramble还原函数 function unscramble(shuffled_str) -- 拆分打乱后的字符串为字符数组,兼容UTF-8 local shuffled_letters = {} for letter in shuffled_str:gmatch'.[\128-\191]*' do table.insert(shuffled_letters, letter) end local n = #shuffled_letters -- 生成排序后的原索引映射 local indices = {} for i = 1, n do table.insert(indices, {idx = i, rnd = randomValues[i]}) end table.sort(indices, function(a, b) return a.rnd < b.rnd end) -- 按反向映射填充原字符串 local original_letters = {} for j = 1, n do original_letters[indices[j].idx] = shuffled_letters[j] end return table.concat(original_letters) end
验证方法
可以直接用以下代码测试功能正确性:
local test_str = "测试字符串123abc" local shuffled = shuffle(test_str) local restored = unscramble(shuffled) print(restored == test_str) -- 输出true即代表功能正常
注意:你当前生成的randomValues数组长度只有60,最多支持长度60以内的字符串加解密,如果需要处理更长的字符串,把randomValues的生成上限调整到对应长度即可
内容的提问来源于stack exchange,提问作者Happy Coder
相关产品推荐
相关产品推荐

