打乱和解读字符串 (Lua)

Shuffle and unscramble a string (Lua)

我有一个函数可以随机播放 中的字符串,适用于使用 table 预定义数字重新排序字符。它工作得很好,所以我还需要一个函数来使用数字 table 来解读这个字符串,但我不知道该怎么做,尤其是在尝试并失败了几次之后。

随机播放功能:

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'.[8-1]*' 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

有什么建议吗?

我假设您要做的是:

  1. 将字符串拆分为 unicode 字符。
  2. 随机播放这些字符。
  3. 将字符恢复到原来的位置。

我将 unicode 字符的拆分和实际的随机播放分开了,以使其更容易理解。

1。拆分字符

从字符拆分开始:

-- Splits a string into a table of unicode characters.
local function splitLetters(str)
  local letters = {}
  for letter in str:gmatch'.[8-1]*' do
     table.insert(letters, letter)
  end
  return letters
end

这主要是从您函数的第一部分复制而来。

2。洗牌 table 个字符

现在我们已经有了可以使用的 table 个不错的字符,是时候洗牌了。可以通过按顺序遍历每个字符并将其与随机选择(但仍未打乱)的项目交换来完成打乱列表。在这样做的同时,我们还保留了所有已交换索引的 table,我在这里称之为 swapTable

-- Shuffles in place and returns a table, which can be used to unshuffle.
local function shuffle(items)
  local swapTable = {}
  for i = 1, #items - 1 do
    -- Swap the first item with a random item (including itself).
    local j = math.random(i, #items)
    items[i], items[j] = items[j], items[i]
    -- Keep track of each swap so we can undo it.
    table.insert(swapTable, j)
    -- Everything up to i is now random.
    -- The last iteration can be skipped, as it would always swap with itself.
    -- See #items - 1 at the top of the loop.
  end
  return swapTable
end

3。将字母恢复到原来的位置

使用此 swapTable,现在可以非常简单地再次进行整个洗牌,但相反。

-- Restores a previous shuffle in place.
local function unshuffle(items, swapTable)
  -- Go through the swap table backwards, as we need to do everything in reverse.
  for i = #swapTable, 1, -1 do
    -- Do the same as before, but using the swap table.
    local j = swapTable[i]
    items[i], items[j] = items[j], items[i]
  end
end

使用所有这些函数的完整示例

使用这几个函数(和table.concat再次将字母列表构建成字符串)我们可以做任何你想做的事:

-- Make our output reproducible
math.randomseed(42)

-- Split our test string into a table of unicode characters
local letters = splitLetters("Hellö Wörld! Höw are yoü?")

-- Shuffle them in-place, while also getting the swapTable
local swapTable = shuffle(letters)

-- Print out the shuffled string
print(table.concat(letters)) --> " rH?doröWüle Hl lwa eyöö!"

-- Unshuffle them in-place using the swapTable
unshuffle(letters, swapTable)

-- And we're back to the original string
print(table.concat(letters)) --> "Hellö Wörld! Höw are yoü?"

预先创建 swapTable

在您的示例中,您预先生成 swapTable(它对您的工作方式也略有不同)。您当然可以将那部分拆分出来,让 shuffle 函数的工作方式类似于 unshuffle 目前的实现方式。如果你想让我详细说明,请告诉我。