Lua Array shuffle not working - lua

I was working on a script to randomize the data inside of my array but I get and error
that says
unexpected symbol near "#"
When I go to that line, and I remove the "#" I get
attempt to perform arithmetic on local `n' (a table value)
Here is my shuffle function
function shuffle(array)
local array = array
local n = #array
local j
local random = math.random
for i=n-1, 1, -1 do
j = random(i)
array[j],array[i] = array[i],array[j]
end
return array
end
and here is what I am trying to randomize
shuffle(new_players)
for name,character in pairs(new_players) do
if (character.inside == true and character.death == 0) then
local player = getPlayerByName(name, map_copy)
if (player ~= nil) then
addState(player)
break
end
end
end
Here is my array
new_players= { }
new_players[charName] = { death = 0, inside= true }
Any help? If i am doing something completely wrong?

1) Try change charName from string to a number.
2) For shuffle you can use this code:
function swap(array, index1, index2)
array[index1], array[index2] = array[index2], array[index1]
end
function shuffle(array)
local counter = #array
while counter > 1 do
local index = math.random(counter)
swap(array, index, counter)
counter = counter - 1
end
end

If your Lua version is < 5.1 then there is no # operator. Use table.getn instead:
local n = table.getn(array);
(Update) Note that your function, while it does shuffle the items around, it does not really shuffle all elements. Also since you reduce the range with each iteration, you will almost certainly swap the first 10% of your array around multiple times. Now swapping them multiple times is not bad by itself, but that you are, by comparison, almost never swapping the other elements is.
So one option to solve this would be to always use the same range for your random variable. And I would go even further and select two random indexes to swap:
function shuffle(array)
local n, random, j = table.getn(array), math.random
for i=1, n do
j,k = random(n), random(n)
array[j],array[k] = array[k],array[j]
end
return array
end
The other option would be to select random elements from the source array and put them into a new output array:
local rnd,trem,getn,ins = math.random,table.remove,table.getn,table.insert;
function shuffle(a)
local r = {};
while getn(a) > 0 do
ins(r, trem(a, rnd(getn(a))));
end
return r;
end

Related

save strings in lua table

Does someone know a solution to save the key and the values to an table? My idea does not work because the length of the table is 0 and it should be 3.
local newstr = "3 = Hello, 67 = Hi, 2 = Bye"
a = {}
for k,v in newstr:gmatch "(%d+)%s*=%s*(%a+)" do
--print(k,v)
a[k] = v
end
print(#a)
The output is correct.
run for k,v in pairs(a) do print(k,v) end to check the contents of your table.
The problem is the length operator which by default cannot be used to get the number of elements of any table but a sequence.
Please refer to the Lua manual: https://www.lua.org/manual/5.4/manual.html#3.4.7
When t is a sequence, #t returns its only border, which corresponds to
the intuitive notion of the length of the sequence. When t is not a
sequence, #t can return any of its borders. (The exact one depends on
details of the internal representation of the table, which in turn can
depend on how the table was populated and the memory addresses of its
non-numeric keys.)
Only use the length operator if you know t is a sequence. That's a Lua table with integer indexes 1,..n without any gap.
You don't have a sequence as you're using non-numeric keys only. That's why #a is 0
The only safe way to get the number of elements of any table is to count them.
local count = 0
for i,v in pairs(a) do
count = count + 1
end
You can put #Piglet' code in the metatable of a as method __len that is used for table key counting with length operator #.
local newstr = "3 = Hello, 67 = Hi, 2 = Bye"
local a = setmetatable({},{__len = function(tab)
local count = 0
for i, v in pairs(tab) do
count = count + 1
end
return count
end})
for k,v in newstr:gmatch "(%d+)%s*=%s*(%a+)" do
--print(k,v)
a[k] = v
end
print(#a) -- puts out: 3
The output of #a with method __len even is correct if the table holds only a sequence.
You can check this online in the Lua Sandbox...
...with copy and paste.
Like i do.

Generating all combinations from a table in Lua

I'm trying to iterate through a table with a variable amount of elements and get all possible combinations, only using every element one time. I've landed on the solution below.
arr = {"a","b","c","d","e","f"}
function tablelen(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end
function spellsub(table,start,offset)
local str = table[start]
for i = start+offset, (tablelen(table)+1)-(start+offset) do
str = str..","..table[i+1]
end
return str
end
print(spellsub(arr,1,2)) -- Outputs: "a,d,e" correctly
print(spellsub(arr,2,2)) -- Outputs: "b" supposed to be "b,e,f"
I'm still missing some further functions, but I'm getting stuck with my current code. What is it that I'm missing? It prints correctly the first time but not the second?
A solution with a coroutine iterator called recursively:
local wrap, yield = coroutine.wrap, coroutine.yield
-- This function clones the array t and appends the item new to it.
local function append (t, new)
local clone = {}
for _, item in ipairs (t) do
clone [#clone + 1] = item
end
clone [#clone + 1] = new
return clone
end
--[[
Yields combinations of non-repeating items of tbl.
tbl is the source of items,
sub is a combination of items that all yielded combination ought to contain,
min it the minimum key of items that can be added to yielded combinations.
--]]
local function unique_combinations (tbl, sub, min)
sub = sub or {}
min = min or 1
return wrap (function ()
if #sub > 0 then
yield (sub) -- yield short combination.
end
if #sub < #tbl then
for i = min, #tbl do -- iterate over longer combinations.
for combo in unique_combinations (tbl, append (sub, tbl [i]), i + 1) do
yield (combo)
end
end
end
end)
end
for combo in unique_combinations {'a', 'b', 'c', 'd', 'e', 'f'} do
print (table.concat (combo, ', '))
end
For a tables with consecutive integer keys starting at 1 like yours you can simply use the length operator #. Your tablelen function is superfluous.
Using table as a local variable name shadows Lua's table library. I suggest you use tbl or some other name that does not prevent you from using table's methods.
The issue with your code can be solved by printing some values for debugging:
local arr = {"a","b","c","d","e","f"}
function spellsub(tbl,start,offset)
local str = tbl[start]
print("first str:", str)
print(string.format("loop from %d to %d", start+offset, #tbl+1-(start+offset)))
for i = start+offset, (#tbl+1)-(start+offset) do
print(string.format("tbl[%d]: %s", i+1, tbl[i+1]))
str = str..","..tbl[i+1]
end
return str
end
print(spellsub(arr,1,2)) -- Outputs: "a,d,e" correctly
print(spellsub(arr,2,2)) -- Outputs: "b" supposed to be "b,e,f"
prints:
first str: a
loop from 3 to 4
tbl[4]: d
tbl[5]: e
a,d,e
first str: b
loop from 4 to 3
b
As you see your second loop does not ran as the start value is already greater than the limit value. Hence you only print the first value b
I don't understand how your code is related to what you want to achieve so I'll leave it up to you to fix it.

How can a Lua function return nil, even if the returned value is not nil inside the function?

I have created a function that (pseudo)randomly creates a table containing numbers. I then loop this function until at least correct result is found. As soon as I've confirmed that at least one such result exists, I stop the function and return the table.
When I create tables containing small values, there are no issues. However, once the random numbers grow to the range of hundreds, the function begins to return nil, even though the table is true the line before I return it.
local sort = table.sort
local random = math.random
local aMin, aMax = 8, 12
local bMin, bMax = 200, 2000
local function compare( a, b )
return a < b
end
local function getNumbers()
local valid = false
local numbers = {}
-- Generate a random length table, containing random number values.
for i = 1, random( aMin, aMax ) do
numbers[i] = random( bMin, bMax )
end
sort( numbers, compare )
-- See if a specific sequence of numbers exist in the table.
for i = 2, #numbers do
if numbers[i-1]+1 == numbers[i] or numbers[i-1] == numbers[i] then
-- Sequence found, so stop.
valid = true
break
end
end
for i = 1, #numbers-1 do
for j = i+1, #numbers do
if numbers[j] % numbers[i] == 0 and numbers[i] ~= 1 then
valid = true
break
end
end
end
if valid then
print( "Within function:", numbers )
return numbers
else
getNumbers()
end
end
local numbers = getNumbers()
print( "Outside function:", numbers )
This function, to my understanding, is supposed to loop infinitely until I find a valid sequence. The only way that the function can even end, according to my code, is if valid is true.
Sometimes, more often than not, with large numbers the function simply outputs a nil value to the outside of the function. What is going on here?
You're just doing getNumbers() to recurse instead of return getNumbers(). This means that if the recursion gets entered, the final returned value will be nil no matter what else happens.
In the else case of the if valid then, you are not returning anything. You only return anything in the valid case. In the else case, a recursive call may return something, but then you ignore that returned value. The print you see is corresponding to the return from the recursive call; it isn't making it out the original call.
You mean to return getNumbers().

What is the most efficient way to iterate numeric string in Lua?

I have a string which consists of numbers:
str = "1234567892"
And I want to iterate individual characters in it and get indices of specific numbers (for example, "2"). As I've learned, I can use gmatch and create a special iterator to store the indices (because, as I know, I just can't get indices with gmatch):
local indices = {}
local counter = 0
for c in str:gmatch"." do
counter = counter + 1
if c == "2" then
table.insert(indices, counter)
end
end
But, I guess, this is not the most efficient decision. I also can convert string to table and iterate table, but it seems to be even more inefficient. So what is the best way to solve the task?
Simply loop over the string! You're overcomplicating it :)
local indices = {[0]={},{},{},{},{},{},{},{},{},{}} --Remove [0] = {}, if there's no chance of a 0 appearing in your string :)
local str = "26842170434179427"
local container
for i = 1,#str do
container = indices[str:sub(i, i)]
container[#container+1] = i
end
container = nil
To find all indices and also do not use regexp but just plain text search
local i = 0
while true do
i = string.find(str, '2', i+1, true)
if not i then break end
indices[#indices + 1] = i
end

Redis: Lua script to return every other nth element of a sorted set

I am trying to put together a lua script to be called from Redis (via an EVAL call) in order to return every other nth element of a sorted set (nth being the rank in the set, not the score).
There are very few online examples of Lua scripts that can be used to build upon, would anyone be able to point me in the right direction?
local function copyNOtherElements(table, interval, startpos)
local elemno = 1
local rettab = {}
for k, v in ipairs(table) do
if k >= startpos and (k - startpos) % interval == 0 then
rettab[elemno] = v
elemno = elemno + 1
end
end
return rettab
end
Sorry about formatting, typing on a phone. that's assuming the table is a 1 based array
For future readers, adding Redis into the previous answer, and a bit more efficient code to iterate the Nth elements:
local function zrange_pick(zset_key, step, start, stop)
-- The next four lines can be removed along with the start/stop params if not needed as in OP Q.
if start == nil than
start = 0
if end == nil than
end = -1
local set_by_score = redis.call('ZRANGE', zset_key, start, end)
local result = {}
for n = 1, #set_by_score, step do
table.insert(result, set_by_score[n])
end
return result
end

Resources