I have a Lua script that turns a table into segments:
function tablecut(t, n)
local result = {}
local j = 0
for i = 1, #t do
if (i-1) % n == 0 then
j = j + 1
result[j] = {}
end
result[j][#result[j]+1] = t[i]
end
return result
end
output = tablecut({'15', '62', '14', '91', '33', '55', '29', '4'}, 4)
for i = 1, #output do
for j = 1, #output[i] do
io.write(tostring(output[i][j])..' ')
end
print()
end
output:
15 62 14 91
33 55 29 4
And I am trying to find the minima from the cut lists so the output would look like this:
15 62 14 91
min = 14
33 55 29 4
min = 4
Edit: If its of any importance this is how I got it to work on Lua 5.3 but there is no table.move function on Lua 5.1. I can't remember how my thought function worked when I wrote this code.
function indexOf(array, value)
for i, v in ipairs(array) do
if v == value then
return i
end
end
return nil
end
Indicies = {}
Answers = {}
function chunks(lst, size)
local i = 1
local count = 0
return function()
if i > #lst then return end
local chunk = table.move(lst, i, i + size -1, 1, {})
i = i + size
count = count + 1
return count, chunk
end
end
local a = {91,52,19,59,38,29,58,11,717,91,456,49,30,62,43,8,17,15,26,22,13,10,2,23} --Test list
for i, chunk in chunks(a, 4) do
x=math.min(a)
print(string.format("#%d: %s", i, table.concat(chunk, ",")))
table.sort(chunk)
print(math.min(chunk[1]))
table.insert(Answers, chunk[1])
table.insert(Indicies, (indexOf(a, chunk[1])))
Output:
#1: 91,52,19,59
19
#2: 38,29,58,11
11
#3: 717,91,456,49
49
your table cut function could be simplified, and your output for loop needs you use an iterator if you want to get an output simply like you do in your 5.3 script.
function cuttable(t,n)
local binned = {}
for i=1,#t,n do
local bin = {}
for j=1,n do
table.insert(bin, t[i + ((j - 1) % n)])
end
table.insert(binned, bin)
end
return binned
end
For the for loop, we can use ipairs on the output of cuttable keeping things pretty simple, then we just do the same steps of concat then sort and print out our results.
for k, bin in ipairs(cuttable(a,4)) do
local output = "#" .. k .. ":" .. table.concat(bin, ",")
table.sort(bin)
print(output)
print(bin[1])
end
Output
#1:91,52,19,59
19
#2:38,29,58,11
11
#3:717,91,456,49
49
#4:30,62,43,8
8
#5:17,15,26,22
15
#6:13,10,2,23
2
One way to implement the cutting would be using a for loop & unpack. I have handled the case of the length not being divisible by 4 after the for loop to (1) maximize performance (check doesn't need to be done every iteration) and (2) be able to directly pass the values to math.min, which doesn't accept nils.
for i = 1, math.floor(#t / 4), 4 do
print(unpack(t, i, i+4))
print("min = " .. math.min(unpack(t, i, i+4)))
end
-- If #t is not divisible by 4, deal with the remaining elements
local remaining = #t % 4
if remaining > 0 then
print(unpack(t, #t - remaining, remaining))
print("min = " .. math.min(unpack(t, #t - remaining, remaining)))
end
I am writing a wireshark dissector of a custom protocol using LUA.For this custom protocol,there are no underlying TCP port or UDP port hence i have written a postdissector.
I am able to capture the payload from the below layers and convert it into a string.
local io_b = tostring(customprotocol)
After this, io_b has the following data
io_b = 10:10:10:10:01:0f:00:0d:00:00:00:00:01:00:00:00:00:20:0a:00:00
At first I split this string with : as the seperator and copy the elements into an array/table.
datafields = {}
index = 1
for value in string.gmatch(io_b, "[^:]+") do
datafields[index] = value
index = index + 1
end
Then I read each element of the datafield array as a uint8 value and check if a bit is set in that datafield element.How to make sure that each element of the table is uint8?
function lshift(x, by)
return x * 2 ^ by
end
--checks if a bit is set at a position
function IsBitSet( b, pos)
if b ~= nil then
return tostring(bit32.band(tonumber(b),lshift(1,pos)) ~= 0)
else
return "nil"
end
end
Then I want to display the value of each bit in the wireshark.I dont care about the first four bytes. The script displays each bit of the 5th byte(which is the 1st considered byte) correctly but displays all the bits value of the 6th byte and other remaining bytes as "nil".
local data_in_2 = subtree:add(customprotocol,"secondbyte")
data_in_2:add(firstbit,(IsBitSet((datafields[6]),7)))
data_in_2:add(secondbit,(IsBitSet((datafields[6]),6)))
data_in_2:add(thirdbit,(IsBitSet((datafields[6]),5)))
data_in_2:add(fourbit,(IsBitSet((datafields[6]),4)))
data_in_2:add(fivebit,(IsBitSet((datafields[6]),3)))
data_in_2:add(sixbit,(IsBitSet((datafields[6]),2)))
data_in_2:add(sevenbit,(IsBitSet((datafields[6]),1)))
data_in_2:add(eightbit,(IsBitSet((datafields[6]),0)))
What am i doing wrong?
Maybe i am wrong but it seems you can do it simpler with...
io_b = '10:10:10:10:01:0f:00:0d:00:00:00:00:01:00:00:00:00:20:0a:00:00'
-- Now replace all : on the fly with nothing and convert it with #Egor' comment tip
-- Simply by using string method gsub() from within io_b
b_num = tonumber(io_b:gsub('%:', ''), 16)
print(b_num)
-- Output: 537526272
#shakingwindow - I cant comment so i ask here...
Do you mean...
io_b = '10:10:10:10:01:0f:00:0d:00:00:00:00:01:00:00:00:00:20:0a:00:00'
-- Converting HEX to string - Replacing : with ,
io_hex = io_b:gsub('[%x]+', '"%1"'):gsub(':', ',')
-- Converting string to table
io_hex_tab = load('return {' .. io_hex .. '}')()
-- Put out key/value pairs by converting HEX value string to a number on the fly
for key, value in pairs(io_hex_tab) do
print(key, '=', tonumber(value, 16))
end
...that puts out...
1 = 16
2 = 16
3 = 16
4 = 16
5 = 1
6 = 15
7 = 0
8 = 13
9 = 0
10 = 0
11 = 0
12 = 0
13 = 1
14 = 0
15 = 0
16 = 0
17 = 0
18 = 32
19 = 10
20 = 0
21 = 0
...?
I want to make a script that takes any number, counts up to them and returns them in a format.
so like this
for i = 1,9 do
print(i)
end
will return
1
2
3
4
5
6
7
8
9
however I want it to print like this
1 2 3
4 5 6
7 8 9
and I want it to work even with things more than 9 so things like 20 would be like this
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
19 20
I'm sure it can be done using the string library in lua but I am not sure how to use that library.
Any help?
function f(n,per_line)
per_line = per_line or 3
for i = 1,n do
io.write(i,'\t')
if i % per_line == 0 then io.write('\n') end
end
end
f(9)
f(20)
The for loop takes an optional third step:
for i = 1, 9, 3 do
print(string.format("%d %d %d", i, i + 1, i + 2))
end
I can think of 2 ways to do this:
local NUMBER = 20
local str = {}
for i=1,NUMBER-3,3 do
table.insert(str,i.." "..i+1 .." "..i+2)
end
local left = {}
for i=NUMBER-NUMBER%3+1,NUMBER do
table.insert(left,i)
end
str = table.concat(str,"\n").."\n"..table.concat(left," ")
And another one using gsub:
local NUMBER = 20
local str = {}
for i=1,NUMBER do
str[i] = i
end
-- Makes "1 2 3 4 ..."
str = table.concat(str," ")
-- Divides it per 3 numbers
-- "%d+ %d+ %d+" matches 3 numbers divided by spaces
-- (You can replace the spaces (including in concat) with "\t")
-- The (...) capture allows us to get those numbers as %1
-- The "%s?" at the end is to remove any trailing whitespace
-- (Else each line would be "N N N " instead of "N N N")
-- (Using the '?' as the last triplet might not have a space)
-- ^ e.g. NUMBER = 6 would make it end with "4 5 6"
-- The "%1\n" just gets us our numbers back and adds a newline
str = str:gsub("(%d+ %d+ %d+)%s?","%1\n")
print(str)
I've benchmarked both code snippets. The upper one is a tiny bit faster, although the difference is almost nothing:
Benchmarked using 10000 interations
NUMBER 20 20 20 100 100
Upper 256 ms 276 ms 260 ms 1129 ms 1114 ms
Lower 284 ms 280 ms 282 ms 1266 ms 1228 ms
Use a temporary table to contain the values until you print them:
local temp = {}
local cols = 3
for i = 1,9 do
if #temp == cols then
print(table.unpack(temp))
temp = {}
end
temp[#temp + 1] = i
end
--Last minute check for leftovers
if #temp > 0 then
print(table.unpack(temp))
end
temp = nil
The following script finds prime numbers in a range from 1 to 13.
When I explicitly iterate over the table that contains the results I can see that the script works as expected. However, if I use unpack() function on the table only the first 3 numbers get printed out.
From docs: unpack is "a special function with multiple returns. It receives an array and returns as results all elements from the array, starting from index 1".
Why is it not working in the script below?
t = {}
for i=1, 13 do t[i] = i end
primes = {}
for idx, n in ipairs(t) do
local isprime = true
for i=2, n-1 do
if n%i == 0 then
isprime = false
break
end
end
if isprime then
primes[idx] = n
end
end
print('loop printing:')
for i in pairs(primes) do
print(i)
end
print('unpack:')
print(unpack(primes))
Running
$ lua5.3 primes.lua
loop printing:
1
2
3
5
7
13
11
unpack:
1 2 3
Change
primes[idx] = n
to
primes[#primes+1] = n
The reason is that idx is not sequential as not every number is a prime.
I'm trying to understand how are index applied in upvalue but unable to get so as led me to ask this question over here.
function newCounter ()
local t = 10
local n = 0
local k = 0
return function ()
l = t
k = n
n = n + 1
return n
end
end
counter = newCounter()
counter()
counter()
print("<==============>")
local i = 1
repeat
name, val = debug.getupvalue(counter, i)
if name then
print ("index", i, name, "=", val)
if (name == "n") then
debug.setupvalue(counter,2,10)
end
i = i + 1
end -- if
until not name
When I run this I get following o/p
index 1 _ENV = table: 0x7f8203c03ea0
index 2 t = 10
index 3 k = 1
index 4 n = 2
Note : I was assuming the o/p to be (based on the order in which they are initialise)
index 1 t = 10
index 2 k = 1
index 3 n = 2
index 4 _ENV = table: 0x7f8203c03ea0
Can any provide me an info as to what is the logical way to find the correct index associate with a given upvalue.
Every chunk in Lua starts with _ENV as its first upvalue.