How to convert an array into a 2D matrix in Lua? - lua

I have the following array of numbers.
arr = {3412323450, 8912745671, 3212367894}
I want to convert it into a simple two-dimensional matrix.
mat = {
{3, 4, 1, 2, 3, 2, 3, 4, 5, 0},
{8, 9, 1, 2, 7, 4, 5, 6, 7, 1},
{3, 2, 1, 2, 3, 6, 7, 8, 9, 4}
}
Initially, I would iterate over arr, convert it into a string, then split the string, iterate over each string char and convert it back to number storing every row and number in mat accordingly. This would be really ugly.
Is there a more conventional method to convert an array into a matrix in
Lua?
Is there a luarock package that people use frequently to convert an array to a matrix?

Personally I think converting to a string and grabbing all of the digits is far prettier than the alternatives (massively dividing by 10, or any other elaborate means you can think of). This is especially true if you wrap the operations up in functions, so your conversions are not constantly appearing throughout your code.
function Digits(n)
local digits = {}
for d in tostring(n):gmatch('%d') do
digits[#digits+1] = tonumber(d)
end
return digits
end
function ArrayToMatrix(array)
local matrix = {}
for i,v in ipairs(array) do
matrix[i] = Digits(v)
end
return matrix
end

Ok, here is my try.
arr = {3412323450, 8912745671, 3212367894}
function arr2matrix(arr)
local mat = {}
for i, row in ipairs(arr) do
mat[i] = {}
local j = 0
row_str = string.gsub(row, '%d', '%0 ')
for c in string.gmatch(row_str, '%S') do
j = j + 1
mat[i][j] = tonumber(c)
end
end
return mat
end
-- checking the result
m = arr2matrix(arr)
for i=1, #m do
for j=1, #m[i] do
io.write(m[i][j]..',')
end
io.write('\n')
end
Running the above gives:
3,4,1,2,3,2,3,4,5,0,
8,9,1,2,7,4,5,6,7,1,
3,2,1,2,3,6,7,8,9,4,

Related

Lua shuffle with repeating cycle

Having some Lua trouble with a a modification of Fisher-Yates shuffle in place. For example, let's say I have a 16 item table (sequence). I want to shuffle integers 1-4 then apply the shuffled pattern in the table to 1-4, 5-8, 9-12, 13-16. So:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
with a 4 item shuffling pattern of 4,2,3,1 would become:
{ 4, 2, 3, 1, 8, 6, 7, 5, 12, 10, 11, 9, 16, 14, 15, 13 }
The code here is from context and includes the "rising edge" input I am using to reshuffle. If you look at the test pic below you can see that yes, it shuffles each section in place, but it reshuffles each section -- I want the shuffled pattern to repeat.
t = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
range = 4
local function ShuffleInPlace(t)
for i = #t, 2, -1 do
local j = math.random(1, range)
local k = (math.floor(i/(range+.001)))*range + j
t[i], t[j] = t[j], t[i]
end
end
-- initialize new table for shuffling
if s == nil then s = {} end
-- use gate rising edge to shuffle
if prev == nil then prev = 0 end
if gate > 0 and prev <= 0 then
s = t
ShuffleInPlace(s)
end
prev = gate
Test pic:
LMD, thank you, your helpful reply is uncovering a solution (by creating the shuffled "pattern" sequence first, outside the iterator). (Still some issues with the first value I'm working out. And I might be looking at some biproducts of the not-so-great math.random function, but that's another story). I'm a novice so any suggestions are appreciated!
-- range input is 0 to 1
seqRange = math.floor(range*(#t*.99))
local function ShuffleRange(x)
if rdm == nil then rdm = {} end
for m = 1, x do rdm[m] = m end
for m = #rdm, 2, -1 do
local j = math.random(m)
rdm[m], rdm[j] = rdm[j], rdm[m]
return rdm[m]
end
end
local function ShuffleInPlace(t)
y = ShuffleRange(seqRange)
for i = #t, 2, -1 do
local j = (math.floor(i/(seqRange*1.001)))*seqRange + y
t[i], t[j] = t[j], t[i]
end
end
Here's how I would do it, implementing the simple approach of first generating a series of swaps and then applying that to the sublists of length n:
math.randomseed(os.time()) -- seed the random
local t = {}; for i = 1, 16 do t[i] = i end -- build table
local n = 4 -- size of subtables
local swaps = {} -- list of swaps of offsets (0-based)
for i = 0, n - 1 do
-- Insert swap into list of swaps to carry out
local j = math.random(i, n - 1)
table.insert(swaps, {i, j})
end
-- Apply swaps to every subtable from i to i + n
for i = 1, #t, n do
for _, swap in ipairs(swaps) do
-- Swap: First add offsets swap[1] & swap[2] respectively
local a, b = i + swap[1], i + swap[2]
t[a], t[b] = t[b], t[a]
end
end
print(table.concat(t, ", "))
Example output: 4, 2, 1, 3, 8, 6, 5, 7, 12, 10, 9, 11, 16, 14, 13, 15

Lua loop shuffle list

i have a problem with my Script if i try to loop thought my list the output is completly random shuffled
minimal Code:
list = {
numbers = {
number1 = 1,
number2 = 2,
number3 = 3,
number4 = 4,
number5 = 5,
number6 = 6,
number7 = 7,
}
}
for k, numbers in pairs(list) do
for k, number in pairs(numbers) do
print(number)
end
end
output:
5
7
2
3
4
6
1
the only fix i figured out is to remove the variables number1 to number7
and just enter the numbers
Lua tables do not have an order.
In addition to that you're using pairs which internally uses next.
From the Lua manual:
The order in which the indices are enumerated is not specified, even
for numeric indices. (To traverse a table in numerical order, use a
numerical for.)
In your case the keys have a numeric component so you could simply create them in a numeric loop.
local numbers = {
number1 = 1,
number2 = 2,
number3 = 3,
number4 = 4,
number5 = 5,
number6 = 6,
number7 = 7,
}
for i = 1, 7 do
print(numbers["number"..i])
end
For other non-numeric keys you would have to use a second table that lists the keys in an ordered sequence:
local numbers = { bob = 1, bill = 3, john = 2}
local orderedKeys = { "bob", "john", "bill"}
for k,v in ipairs(orderedKeys) do
print(numbers[v])
end
A numeric loop will always work for any integer keys.
local numbers = {
[0] = 0,
[5] = 5,
[3] = 3,
[1] = 0,
}
for i = 0, 5 do
if numbers[i] then
print(numbers[i])
end
end
Read through this carefully:
A table with exactly one border is called a sequence. For instance,
the table {10, 20, 30, 40, 50} is a sequence, as it has only one
border (5). The table {10, 20, 30, nil, 50} has two borders (3 and 5),
and therefore it is not a sequence. (The nil at index 4 is called a
hole.) The table {nil, 20, 30, nil, nil, 60, nil} has three borders
(0, 3, and 6) and three holes (at indices 1, 4, and 5), so it is not a
sequence, too. The table {} is a sequence with border 0. Note that
non-natural keys do not interfere with whether a table is a sequence.
Things like ipairs, the length operator #, table.sort, table.concat and others only work with sequences.
Keys that do not contribute to the sequence are ignored by those functions. You can only loop over all keys of a table with next or pairs respectively. But then order is not guaranteed.

How could i loop through every OTHER element in a table in Roblox.lua

I am trying to loop through every other element in an table but I cannot find a way to do so.
Any help is appreciated.
Thank you.
It depends what kind of table you're working with. If you have an array-like table, you can use a simple for-loop :
local t = {1, 2, 3, 4, 5, 6, 7, 8}
-- start at 1, loop until i > the length of t, increment i by 2 every loop
for i = 1, #t, 2 do
local val = t[i]
print(val) -- will print out : 1, 3, 5, 7
end
But if you have a dictionary-like table, you will need something to track which key to skip. You could use a simple boolean to keep track, but be aware that there is no guaranteed order of a dictionary-like table.
local t = {
a = 1,
b = 2,
c = 3,
d = 4,
}
local shouldPrint = true
for k, v in pairs(t) do
-- only print the value when it's true
if shouldPrint then
print(k, v) -- will probably print a, 1 and c, 3
end
-- swap shouldPrint's value every loop
shouldPrint = !shouldPrint
end
Maybe try this
local count = 0
for i = 1 , #table/2 do
table[count + i].value = value
count = count + 1
end
Add to the count as you go down

How do I split a string given an array of split positions?

I'm using Ruby 2.4 and Rails 5. I have an array of indexes within a line
[5, 8, 10]
How do I take the above array, and a string, and form anotehr array of strings that are split by the above indexes? FOr instance, if the string is
abcdefghijklmn
and split it based ont eh above indexes, I would have an array with the following strings
abcde
fgh
ij
klmn
Try this
str = "abcdefghijklmn"
positions = [5, 8, 10]
parts = [0, *positions, str.size].each_cons(2).map { |a, b| str[a...b] }
# => ["abcde", "fgh", "ij", "klmn"]
Or,
If the positions are constant and known ahead of runtime (for example if they were the format for a phone number or credit card) just use a regexp
str.match(/(.....)(...)(..)(.*)/).captures
# => ["abcde", "fgh", "ij", "klmn"]
This will get the Job done
str = "abcdefghijklmn"
arr_1 = [5, 8, 10]
arr_2, prev = [], 0
(arr_1.length + 1).times do |x|
if arr_1[x] == nil then arr_1[x] = str.size end
arr_2 << str[prev..arr_1[x] -1]
prev = arr_1[x]
end
p arr_2
---------------------------------------
Program Run Output
["abcde", "fgh", "ij", "klmn"]
---------------------------------------
I hope this Helps

insert table values with string keys into Lua table

I'm relatively new to the Lua language and there's something I'm obviously missing about table structures.
I'm trying to create a table of tables, with each table in the table having a key and the value being the respective table.
Ok, that statement can be confusing. Here's an example:
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
for this I used the following algorithm:
local listOfLists = {};
...
if condition1 then
listOfLists[key1] = list1;
end
...
if condition2 then
listOfLists[key2] = list2;
end
...
And so on...
I hope to use the keys to later determine which lists have been added to the table.
But the thing is, no lists seem to be added to the table even if all the conditions are met.
I can use table.insert(listOfLists, list1) in place of listOfLists[key1] = list1 but then I won't be able to tell which lists were added to the collection.
Ant suggestions?
Lua tables are a flexible data structure. Elements are key-value pairs. A key is any Lua value except nil. A value can have any value except nil. Assigning nil to the value obliterates the pair.
The (possibly empty) subset of a table that has key values of the number type that are integers from 1 to n is called a sequence. n is determined as the last such key that is paired with a nil value. Several table functions and operators work only with sequences.
Table constructors allow several syntaxes for keys:
Implied via a sequence: {1, 2, 3}
Explicit keys: {[1] = 1, [3] = 3, ["two"] = "value"}
Identifier keys: {one = 1, two = 2}
A table constructor can use any combination of them.
You have defined a sequence of elements, each of which is a table with two elements, the
second of which is a sequence.
It appears you want keys to be strings and values to be sequences:
{
RC = {1, 2, 3, 4},
M = {4, 8, 7},
D = {3, 8, 9}
}
It's hard to understand, what do you wanna achieve. So, if you want more specific answer, provide more info.
You can create associative table of tables.
local map = {}
map["key"] = { 1, 2, 3, 4 }
print(map.key[3])
Or you can create an array of tables
local vector = {}
vector[1] = { 1, 2, 3, 4 }
print(vector[1][2])
Or you can combine approaches.
To create
{{ key = "RC", value = {1, 2, 3, 4}},
{ key = "M", value = {4, 8, 7}},
{ key = "D", value = {3, 8, 9}}
...}
You can use table constructor or smth from code.
local tbl = { { key = "RC", value = {1, 2, 3, 4}} } -- init first elem from constructor
table.insert(tbl, { key = "M", value = {4, 8, 7}}) -- table insert & constructor
tbl[2] = {} -- Array-based access.
tbl[2].key = "D" --key access
tbl[2]["value"] = { 3, 8, 9 } -- other way
Note, that each table consists of two parts: vector for sequental keys from 1 to N, and map otherwise. Some functions, like table length operator or ipairs iterator are guaranteed to work only with vector-part of table. But they are significantly faster.
EDIT: (last paragraph explanation)
If you have a table with some keys and want to iterate through, you can use ipairs or pairs.
ipairs is ordered, and goes from 1 to first not-nil element. It doesn't iterate over not-integer keys. pairs goes trough any key, but doesn't guarantee order.
local map = { 1, 2, 3, key = 6, [5] = 5 }
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3. first nil element is map[4]. map[5] will mot be visited.
end
for i, v in pairs(map) do -- NOTE pairs usage
print(v) -- will output 1, 2, 3, 5, 6 in ANY order
end
map[4] = 4 -- Fill gap
for i, v in ipairs(map) do
print(v) -- will output 1, 2, 3, 4, 5. Now first nil element is map[6]
end
Length operator works similar to ipairs, it doesn't count elements not visited by ipairs method.
table.maxn works with numerical indices, and will return zero for your table.
Reference say that table.maxn
Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.)
Little example about length and table.maxn
local a = { 1, 2, 3, [5] = 5}
print(table.maxn(a)) -- 5
print(#a) -- 3
a = { key = 4 }
print(table.maxn(a)) -- 0
print(#a) -- 0
print(a["key"]) -- 4, nothing is lost
local num = 0
for _, __ in pairs(a) do num = num + 1 end
print(num) -- 1 We find it.

Resources