What is this function doing in Lua? - lua

function splitSat(str, pat, max, regex)
pat = pat or "\n" --Patron de búsqueda
max = max or #str
local t = {}
local c = 1
if #str == 0 then
return {""}
end
if #pat == 0 then
return nil
end
if max == 0 then
return str
end
repeat
local s, e = str:find(pat, c, not regex) -- Dentro del string str, busca el patron pat desde la posicion c
-- guarda en s el numero de inicio y en e el numero de fin
max = max - 1
if s and max < 0 then
if #(str:sub(c)) > 0 then -- Si la longitud de la porcion de string desde c hasta el final es mayor que 0
t[#t+1] = str:sub(c)
else values
t[#t+1] = "" --create a table with empty
end
else
if #(str:sub(c, s and s - 1)) > 0 then -- Si la longitud de la porcion de string str entre c y s
t[#t+1] = str:sub(c, s and s - 1)
else
t[#t+1] = "" --create a table with empty values
end
end
c = e and e + 1 or #str + 1
until not s or max < 0
return t
end
I'd like to know what this function is doing. I know that it makes a kind of table taking a string and a pattern. Especially I want to know what *t[#t+1] = str:sub(c, s and s - 1)* is doing.

From what I get, it splits a long string into substrings that match a certain pattern and ignores everything in between the pattern maches. For example, it might match the string 11aa22 to the pattern \d\d, resulting in the table ["11", "22"].
t[#t+1] = <something> inserts a value at the end of table t, it's the same as table.insert(t, <something>)
#t returns the length of an array (that is, a table with consecutive numeric indices), for example, #[1, 2, 3] == 3
str:sub(c, s and s - 1) takes advantage of many of luas features. s and s - 1 evaluates to s-1 if s is not nil, and nil otherwise. Just s-1 would throw an error if s was nil
10 and 10 - 1 == 9
10 - 1 == 9
nil and nil - 1 == nil
nil - 1 -> throws an error
str:sub(a, b) just returns a substring starting at a and ending at b (a and b being numeric indices)
("abcde"):sub(2,4) == "bcd"

Related

Reversing an decode function

I'm trying to reverse a decode function. This function takes a string and a key and encodes the string with that key. This is the code:
function decode(key, code)
return (code:gsub("..", function(h)
return string.char((tonumber(h, 16) + 256 - 13 - key + 255999744) % 256)
end))
end
If I input 7A as code and 9990 as key, it returns g
I tried reversing the operators and fed back the output of the decode function but I get an error becauase tonumber() returns nil. How can I reverse this function?
By using the answer to this Lua base coverter and flipping the operators of the decode function, I was able to convert back the input.
This is the whole code:
function encodes(key, code)
return (code:gsub("..", function(h)
return string.char((tonumber(h, 16) + 256 - 13 - key + 255999744) % 256)
end))
end
local floor,insert = math.floor, table.insert
function basen(n,b)
n = floor(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % b) + 1
n = floor(n / b)
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,"")
end
function decodes(key, code)
return (code:gsub(".", function(h)
out = (string.byte(h) - 256 + 13 + key - 255999744) % 256
return basen(out,16)
end))
end
a = encodes(9999, "7c7A")
print(a) --prints: `^
print("----------")
b = decodes(9999, a)
print(b) --prints: 7C7A

Finding a prime with Miller Rabin

I have what I believe is a proper implementation of the miller-rabin algorithm using Lua, and I am trying to get a consistent return for prime numbers. It seems my implementation only works half of the time. Although if I try implementing similar code within python, that code works 100% of the time. Could someone point me in the right direction?
--decompose n-1 as (2^s)*d
local function decompose(negOne)
exponent, remainder = 0, negOne
while (remainder%2) == 0 do
exponent = exponent+1
remainder = remainder/2
end
assert((2^exponent)*remainder == negOne and ((remainder%2) == 1), "Error setting up s and d value")
return exponent, remainder
end
local function isNotWitness(n, possibleWitness, exponent, remainder)
witness = (possibleWitness^remainder)%n
if (witness == 1) or (witness == n-1) then
return false
end
for _=0, exponent do
witness = (witness^2)%n
if witness == (n-1) then
return false
end
end
return true
end
--using miller-rabin primality testing
--n the integer to be tested, k the accuracy of the test
local function isProbablyPrime(n, accuracy)
if n <= 3 then
return n == 2 or n == 3
end
if (n%2) == 0 then
return false
end
exponent, remainder = decompose(n-1)
--checks if it is composite
for i=0, accuracy do
math.randomseed(os.time())
witness = math.random(2, n - 2)
if isNotWitness(n, witness, exponent, remainder) then
return false
end
end
--probably prime
return true
end
if isProbablyPrime(31, 30) then
print("prime")
else
print("nope")
end
Python has arbitrary length integers. Lua doesn't.
The problem is in witness = (possibleWitness^remainder)%n.
Lua is unable to calculate exact result of 29^15 % 31 directly.
There is a workaround working for numbers n < sqrt(2^53):
witness = mulmod(possibleWitness, remainder, n)
where
local function mulmod(a, e, m)
local result = 1
while e > 0 do
if e % 2 == 1 then
result = result * a % m
e = e - 1
end
e = e / 2
a = a * a % m
end
return result
end

Changing number as a word to the number value

I am trying to change a string that is the word for a number between one and fifty to the number value, i.e. if
local = "twelve" it will make local_num = 12, if local = "one" then local_num = 1, etc. Do I just use an array and loop a compare?
There is no need for a loop. Just use this table directly:
Word2Number={
["zero"]=0,
["one"]=1,
["two"]=2,
["three"]=3,
["four"]=4,
["five"]=5,
["six"]=6,
["seven"]=7,
["eight"]=8,
["nine"]=9,
["ten"]=10,
["eleven"]=11,
["twelve"]=12,
["thirteen"]=13,
["fourteen"]=14,
["fifteen"]=15,
["sixteen"]=16,
["seventeen"]=17,
["eighteen"]=18,
["nineteen"]=19,
["twenty"]=20,
["twenty-one"]=21,
["twenty-two"]=22,
["twenty-three"]=23,
["twenty-four"]=24,
["twenty-five"]=25,
["twenty-six"]=26,
["twenty-seven"]=27,
["twenty-eight"]=28,
["twenty-nine"]=29,
["thirty"]=30,
["thirty-one"]=31,
["thirty-two" ]=32,
["thirty-three" ]=33,
["thirty-four"]=34,
["thirty-five"]=35,
["thirty-six"]=36,
["thirty-seven"]=37,
["thirty-eight"]=38,
["thirty-nine"]=39,
["forty"]=40,
["forty-one"]=41,
["forty-two"]=42,
["forty-three"]=43,
["forty-four"]=44,
["forty-five"]=45,
["forty-six"]=46,
["forty-seven"]=47,
["forty-eight"]=48,
["forty-nine"]=49,
["fifty"]=50,
}
This is the code to spell an integer
local append, concat, floor, abs = table.insert, table.concat, math.floor, math.abs
local num = {'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'}
local tens = {'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'}
local bases = {{floor(1e18), ' quintillion'}, {floor(1e15), ' quadrillion'}, {floor(1e12), ' trillion'},
{floor(1e9), ' billion'}, {1000000, ' million'}, {1000, ' thousand'}, {100, ' hundred'}}
local insert_word_AND = false -- 101 = "one hundred and one" / "one hundred one"
local function IntegerNumberInWords(n)
-- Returns a string (spelling of integer number n)
-- n should be from -2^53 to 2^53 (-2^63 < n < 2^63 for integer argument in Lua 5.3)
local str = {}
if n < 0 then
append(str, "minus")
end
n = floor(abs(n))
if n == 0 then
return "zero"
end
if n >= 1e21 then
append(str, "infinity")
else
local AND
for _, base in ipairs(bases) do
local value = base[1]
if n >= value then
append(str, IntegerNumberInWords(n / value)..base[2])
n, AND = n % value, insert_word_AND or nil
end
end
if n > 0 then
append(str, AND and "and") -- a nice pun !
append(str, num[n] or tens[floor(n/10)-1]..(n%10 ~= 0 and '-'..num[n%10] or ''))
end
end
return concat(str, ' ')
end
And this is how to use it:
local function digitize(number_as_text)
number_as_text = number_as_text:lower():gsub("%W", "")
for i = 1, 50 do
if IntegerNumberInWords(i):lower():gsub("%W", "") == number_as_text then
return i
end
end
end
print(digitize(io.read()))

Lua - Error Attempt to perform arithmetic on field '?' -- This occurs at the end of the for loop

I'm developing a program for the Ti-nspire CX CAS calculator and at the time of execution it indicates an error on line 52, this is presented at the end of the for loop in the "area" function.
Sorry for my English.
local coX = {0,2,2,0}
local coY = {0,0,2,0}
local xmax = 2
local ymax = 2
-- Matriz de coordenadas para función "on.paint(gc)"
function conCoor(x,y)
local nx = x
for i=1, #x do
table.insert(nx,i*2,y[i])
end
return nx
end
-- Valor absoluto
function math.abs(valor)
if valor < 0 then
valor = valor*(-1)
end
return valor
end
-- Inercia del polígono respecto el eje X
function inerciex(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (x[i+1]-x[i])*(y[i+1]+y[i])*((y[i+1])^2+(y[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Inercia del polígono respecto el eje Y
function inerciey(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (y[i+1]-y[i])*(x[i+1]+x[i])*((x[i+1])^2+(x[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Área del poligono
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
-- Centro de masa del polígono (eje x)
function centroix(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (x[i]+x[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Centro de masa del polígono (eje y)
function centroiy(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (y[i]+y[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Escala de figura
function escala(xmax,ymax)
local sc = 0
if xmax > ymax then
sc = 81/xmax
else
sc = 81/ymax
end
return math.floor(sc)
end
-- Coordenadas del origen en pantalla
function oriDispX(x,y,xmax,ymax)
return math.floor(212 + (-1)*centroix(x,y)*escala(xmax,ymax))
end
function oriDispY(x,y,xmax,ymax)
return math.floor(105 + (-1)*centroiy(x,y)*escala(xmax,ymax))
end
-- Cambio de coordenadas real
function coorCamb(x,y,xmax,ymax)
-- Escalado de coordenadas
local escx = x
local escy = y
local orix = oriDispX(escx,escy,xmax,ymax)
local oriy = oriDispY(escx,escy,xmax,ymax)
for i = 1, #escx do
escx[i] = math.floor(escx[i]*escala(xmax,ymax))
escy[i] = math.floor(escy[i]*escala(xmax,ymax))
end
-- Cambio de coordenadas
for i = 1, #escx do
escx[i] = escx[i] + orix
escy[i] = escy[i] + oriy
end
return conCoor(escx,escy)
end
function on.paint(gc)
local ox = oriDispX(coX,coY,xmax,ymax)
local oy = oriDispY(coX,coY,xmax,ymax)
local c = coorCamb(coX,coY,xmax,ymax)
gc:drawPolyLine(c)
gc:drawLine(ox-3,oy,ox+3,oy)
gc:drawLine(ox,oy-3,ox,oy+3)
gc:fillArc(ox-1,oy-1,2,2,0,360)
gc:fillArc(212-1,105-1,2,2,0,360)
gc:drawString(tostring(area(coX,coY)),10,10)
platform.window:invalidate()
end
More specifically, the error occurs here:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
Your code assumes both X and Y arrays are of equal size (because you use i index for both X and Y array), or at least Y never smaller than X. i index, however, runs from 1 to the size of X array which will be invalid for Y array of smaller size.
So, if the Y array is smaller than the X array, you get that error. And, here's the proof:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end
return math.abs(z/2)
end
print(area({1,2,3},{4,5,6})) -- OK
print(area({1,2,3},{4,5})) -- ERROR
The solution was to initialize the variables and tables at the beginning of the whole script and then call the new values ​​using "var.recall" inside the on.paint function.

(Lua) Condition statements not behaving as expected

My math teacher has an extra credit halloween problem that goes like this:
each letter represents a digit 2-9, and you need the following problem to work:
trick + or = treat
I decided I want to find ALL possible solutions to the problem (To impress him) so I decide to write a computer program that would tell me the all the answers. Here is my following code:
local function checkAdd()
local trick =k+(10*c)+(100*i)+(1000*r)+(10000*t) local _or =r+(10*o)
local treat = t+(10*a)+(100*e)+(1000*r)+(10000*t) if trick + _or ==
treat then print(trick) print(" ".._or) print(treat)
print(t) print(r) print(i) print(c) print(k) print(o) print(e) print(a) end --print("end")
timer.performWithDelay(1,newNumbers) end local function
checkNumbers8() if t or r or i or c or k or o or e or a == "9" then
checkAdd() else newNumbers() end end
local function checkNumbers7() if t or r or i or c or k or o or e or
a == "8" then checkNumbers8() else newNumbers() end end
local function checkNumbers6() if t or r or i or c or k or o or e or
a == "7" then checkNumbers7() else newNumbers() end end
local function checkNumbers5() if t or r or i or c or k or o or e or
a == "6" then checkNumbers6() else newNumbers() end end
local function checkNumbers4() if t or r or i or c or k or o or e or
a == "5" then checkNumbers5() else newNumbers() end end
local function checkNumbers3() if t or r or i or c or k or o or e or
a == "4" then checkNumbers4() else newNumbers() end end
local function checkNumbers2() if t or r or i or c or k or o or e or
a == "3" then checkNumbers3() else newNumbers() end end
local function checkNumbers() if t or r or i or c or k or o or e or a
== "2" then checkNumbers2() else newNumbers()
end end
function newNumbers() t = mRandom(2,9) r = mRandom(2,9) i =
mRandom(2,9) c = mRandom(2,9) k = mRandom(2,9) o = mRandom(2,9) e
= mRandom(2,9) a = mRandom(2,9) checkNumbers() end
newNumbers()
*Please note that on in the function checkAdd I call the function timer.performwithdelay ( waits 1 milisecond before calling the function). This is because if I run this code just regularly without the function call, I get a stack overflow error. So i put my code into a framework I use for app developement that had the timer.performwithdelay call, and I implemented that into my code so the computer won't be so overwhelmed and cause an overflow error.
I get the following print statements:
97552
27
97579
9
7
5
5
2
2
5
7
and:
49325
59
49384
4
9
3
2
5
5
3
8
I am getting some letters equaling the same as other letters! and not all numbers 2-9 are used! What is wrong with my code? I test to see if every number 2-9 is used
I think there are two main issues. I don't see the function mRandom, but I assume it returns a number and you are comparing it with a string. Number 2 is not the same as string '2', so 2 == '2' returns false.
The second issue is that (it seems) you are trying to compare if either of variables has a specific value, but you can't do if a or b == 2 then meaning: execute if either a or b equals 2. For that you need to write if a == 2 or b == 2. What you have is evaluated as: if a is evaluated as true (which is when it's not nil or false) or b equals 2.

Resources