Related
I'm having problem returning spesific amount of decimal numbers from this function, i would like it to get that info from "dec" argument, but i'm stuck with this right now.
Edit: Made it work with the edited version bellow but isn't there a better way?
local function remove_decimal(t, dec)
if type(dec) == "number" then
for key, num in pairs(type(t) == "table" and t or {}) do
if type(num) == "number" then
local num_to_string = tostring(num)
local mod, d = math.modf(num)
-- find only decimal numbers
local num_dec = num_to_string:sub(#tostring(mod) + (mod == 0 and num < 0 and 3 or 2))
if dec <= #num_dec then
-- return amount of deciamls in the num by dec
local r = d < 0 and "-0." or "0."
local r2 = r .. num_dec:sub(1, dec)
t[key] = mod + tonumber(r2)
end
end
end
end
return t
end
By passing the function bellow i want a result like this:
result[1] > 0.12
result[2] > -0.12
result[3] > 123.45
result[4] > -1.23
local result = remove_decimal({0.123, -0.123, 123.456, -1.234}, 2)
print(result[1])
print(result[2])
print(result[3])
print(result[4])
I tried this but it seems to only work with one integer numbers and if number is 12.34 instead of 1.34 e.g, the decimal place will be removed and become 12.3. Using other methods
local d = dec + (num < 0 and 2 or 1)
local r = tonumber(num_to_string:sub(1, -#num_to_string - d)) or 0
A good approach is to find the position of the decimal point (the dot, .) and then extract a substring starting from the first character to the dot's position plus how many digits you want:
local function truncate(number, dec)
local strnum = tostring(number)
local i, j = string.find(strnum, '%.')
if not i then
return number
end
local strtrn = string.sub(strnum, 1, i+dec)
return tonumber(strtrn)
end
Call it like this:
print(truncate(123.456, 2))
print(truncate(1234567, 2))
123.45
1234567
To bulk-truncate a set of numbers:
local function truncate_all(t, dec)
for key, value in pairs(t) do
t[key] = truncate(t[key], dec)
end
return t
end
Usage:
local result = truncate_all({0.123, -0.123, 123.456, -1.234}, 2)
for key, value in pairs(result) do
print(key, value)
end
1 0.12
2 -0.12
3 123.45
4 -1.23
One could use the function string.format which is similar to the printf functions from C language. If one use the format "%.2f" the resulting string will contain 2 decimals, if one use "%.3f" the resulting string will be contain 3 decimals, etc. The idea is to dynamically create the format "%.XXXf" corresponding to the number of decimal needed by the function. Then call the function string.format with the newly created format string to generate the string "123.XXX". The last step would be to convert back the string to a number with the function tonumber.
Note that if one want the special character % to be preserved when string.format is called, you need to write %%.
function KeepDecimals (Number, DecimalCount)
local FloatFormat = string.format("%%.%df", DecimalCount)
local String = string.format(FloatFormat, Number)
return tonumber(String)
end
The behavior seems close to what the OP is looking for:
for Count = 1, 5 do
print(KeepDecimals(1.123456789, Count))
end
This code should print the following:
1.1
1.12
1.123
1.1235
1.12346
Regarding the initial code, it's quite straight-forward to integrate the provided solution. Note that I renamed the function to keep_decimal because in my understanding, the function will keep the requested number of decimals, and discard the rest.
function keep_decimal (Table, Count)
local NewTable = {}
local NewIndex = 1
for Index = 1, #Table do
NewTable[NewIndex] = KeepDecimal(Table[Index], Count)
NewIndex = NewIndex + 1
end
return NewTable
end
Obviously, the code could be tested easily, simply by copy and pasting into a Lua interpreter.
Result = keep_decimal({0.123, -0.123, 123.456, -1.234}, 2)
for Index = 1, #Result do
print(Result[Index])
end
This should print the following:
0.12
-0.12
123.46
-1.23
Edit due to the clarification of the need of truncate:
function Truncate (Number, Digits)
local Divider = Digits * 10
local TruncatedValue = math.floor(Number * Divider) / Divider
return TruncatedValue
end
On my computer, the code is working as expected:
> Truncate(123.456, 2)
123.45
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 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
I am trying to adapt the pure Lua implementation of the SecureHashAlgorithm found here for SHA2 512 instead of SHA2 256. When I try to use the adaptation, it does not give the correct answer.
Here is the adaptation:
--
-- UTILITY FUNCTIONS
--
-- transform a string of bytes in a string of hexadecimal digits
local function str2hexa (s)
local h = string.gsub(s, ".", function(c)
return string.format("%02x", string.byte(c))
end)
return h
end
-- transforms number 'l' into a big-endian sequence of 'n' bytes
--(coded as a string)
local function num2string(l, n)
local s = ""
for i = 1, n do
--most significant byte of l
local remainder = l % 256
s = string.char(remainder) .. s
--remove from l the bits we have already transformed
l = (l-remainder) / 256
end
return s
end
-- transform the big-endian sequence of eight bytes starting at
-- index 'i' in 's' into a number
local function s264num (s, i)
local n = 0
for i = i, i + 7 do
n = n*256 + string.byte(s, i)
end
return n
end
--
-- MAIN SECTION
--
-- FIRST STEP: INITIALIZE HASH VALUES
--(second 32 bits of the fractional parts of the square roots of the first 9th through 16th primes 23..53)
local HH = {}
local function initH512(H)
H = {0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}
return H
end
-- SECOND STEP: INITIALIZE ROUND CONSTANTS
--(first 80 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
local k = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
}
-- THIRD STEP: PRE-PROCESSING (padding)
local function preprocess(toProcess, len)
--append a single '1' bit
--append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K = 896mod1024
local extra = 128 - (len + 9) % 128
len = num2string(8 * len, 8)
toProcess = toProcess .. "\128" .. string.rep("\0", extra) .. len
assert(#toProcess % 128 == 0)
return toProcess
end
local function rrotate(rot, n)
return (rot >> n) | ((rot << 64 - n))
end
local function digestblock(msg, i, H)
local w = {}
for j = 1, 16 do w[j] = s264num(msg, i + (j - 1)*4) end
for j = 17, 80 do
local v = w[j - 15]
local s0 = rrotate(v, 1) ~ rrotate(v, 8) ~ (v >> 7)
v = w[j - 2]
w[j] = w[j - 16] + s0 + w[j - 7] + ((rrotate(v, 19) ~ rrotate(v, 61)) ~ (v >> 6))
end
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
for i = 1, 80 do
a, b, c, d, e, f, g, h = a , b , c , d , e , f , g , h
local s0 = rrotate(a, 28) ~ (rrotate(a, 34) ~ rrotate(a, 39))
local maj = ((a & b) ~ (a & c)) ~ (b & c)
local t2 = s0 + maj
local s1 = rrotate(e, 14) ~ (rrotate(e, 18) ~ rrotate(e, 41))
local ch = (e & f) ~ (~e & g)
local t1 = h + s1 + ch + k[i] + w[i]
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
end
H[1] = (H[1] + a)
H[2] = (H[2] + b)
H[3] = (H[3] + c)
H[4] = (H[4] + d)
H[5] = (H[5] + e)
H[6] = (H[6] + f)
H[7] = (H[7] + g)
H[8] = (H[8] + h)
end
local function finalresult512 (H)
-- Produce the final hash value:
return
str2hexa(num2string(H[1], 8)..num2string(H[2], 8)..num2string(H[3], 8)..num2string(H[4], 8)..
num2string(H[5], 8)..num2string(H[6], 8)..num2string(H[7], 8)..num2string(H[8], 8))
end
-- Returns the hash512 for the given string.
local function hash512 (msg)
msg = preprocess(msg, #msg)
local H = initH512(HH)
-- Process the message in successive 1024-bit (128 bytes) chunks:
for i = 1, #msg, 128 do
digestblock(msg, i, H)
end
return finalresult512(H)
end
Given hash512("a"):
Expect: 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
Actual: e0b9623f2194cb81f2a62616a183edbe390be0d0b20430cadc3371efc237fa6bf7f8b48311f2fa249131c347fee3e8cde6acfdab286d648054541f92102cfc9c
I know that I am creating a message of the correct bit size (1024 bits) and also working in 1024-bit chunks, or at least I believe I am.
I am not sure if it has to do with the handling of the integers (the standard requires unsigned integers) or whether I made a mistake in one of the utility functions, or both. If it is indeed an issue with the handling of the integers, how would I go about taking care of the problem. I was able to resolve this when working on the 256-bit version of the adaptation by using mod 2^32 when working with numbers in the digestblock method. I attempted to do mod 2^64 and 2^63 with the 512-bit version and it does not correct the problem. I am stumped.
I should mention that I cannot use one of the many library implementations as I am using a sandboxed Lua that does not provide this access, which is why I need a pure lua implementation. Thanks in advance.
Unfortunately, after introducing integers in Lua 5.3 writing scripts for Lua becomes a more complicated task.
You must always think about transformations between integers and floating point numbers.
ALWAYS. Yes, that's boring.
One of your mistakes is an excellent example of this "dark corner of Lua".
local remainder = l % 256
s = string.char(remainder) .. s
--remove from l the bits we have already transformed
l = (l-remainder) / 256
Your value l is initially a 64-bit integer.
After cutting off its first byte l contains (64-8) = 56 bits, but now it's a floating point-number (with 53-bit precision, of course).
Possible solution: use l = l >> 8 or l = l // 256 instead of l = (l-remainder) / 256
Another mistake is using s264num(msg, i + (j - 1) * 4) instead of s264num(msg, i + (j - 1) * 8)
One more mistake is in the following line:
local extra = 128 - (len + 9) % 128
The correct code is
local extra = - (len + 17) % 128 + 8
(Please note that -a%m+b is not the same as b-a%m due to operator precedence)
After fixing these 3 mistakes your code works correctly.
I try to parse gpx files and to output encoded polylines (Google algorithm)
test.gpx
<trkseg>
<trkpt lon="-120.2" lat="38.5"/>
<trkpt lon="-120.95" lat="40.7"/>
<trkpt lon="-126.453" lat="43.252"/>
</trkseg>
I managed most of it, but have trouble with encoding the numbers
gpx2epl:
file = io.open(arg[1], "r")
io.input(file)
--
function round(number, precision)
return math.floor(number*math.pow(10,precision)+0.5) / math.pow(10,precision)
end
function encodeNumber(number)
return number
end
--
local Olatitude = 0
local Olongitude = 0
--
while true do
local line = io.read()
if line == nil
then
break
end
if string.match(line, "trkpt") then
local latitude
local longitude
local encnum
latitude = string.match(line, 'lat="(.-)"')
longitude = string.match(line, 'lon="(.-)"')
latitude = round(latitude,5)*100000
longitude = round(longitude,5)*100000
encnum = encodeNumber(latitude-Olatitude)
print(encnum)
encnum = encodeNumber(longitude-Olongitude)
print(encnum)
Olatitude = latitude
Olongitude = longitude
end
end
This script produces the expected output (see: Google Link), with the exception of encoded latitude and longitude.
3850000
-12020000
220000
-75000
255200
-550300
Mapquest provides an implementation in Javascript:
function encodeNumber(num) {
var num = num << 1;
if (num < 0) {
num = ~(num);
}
var encoded = '';
while (num >= 0x20) {
encoded += String.fromCharCode((0x20 | (num & 0x1f)) + 63);
num >>= 5;
}
encoded += String.fromCharCode(num + 63);
return encoded;
}
Can this be done in Lua? Can somebody please help me out. I have no idea how to implement this in Lua.
Edit:
Based on Doug's advice, I did:
function encodeNumber(number)
local num = number
num = num * 2
if num < 0
then
num = (num * -1) - 1
end
while num >= 32
do
local num2 = 32 + (num % 32) + 63
print(string.char(num2))
num = num / 32
end
print(string.char(num + 63) .. "\n-----")
end
encodeNumber(3850000) -- _p~iF
encodeNumber(-12020000) -- ~ps|U
encodeNumber(220000) -- _ulL
encodeNumber(-75000) -- nnqC
encodeNumber(255200) -- _mqN
encodeNumber(-550300) -- vxq`#
It's near expected output, but only near ... Any hint?
Taking encodeNumber piecemeal...
var num = num << 1;
This is just num = num * 2
num = ~(num);
This is num = (- num) - 1
0x20 | (num & 0x1f)
Is equivalent to 32 + (num % 32)
num >>= 5
Is equivalent to num = math.floor(num / 32)
ADDENDUM
To concatenate the characters, use a table to collect them:
function encodeNumber(number)
local num = number
num = num * 2
if num < 0
then
num = (num * -1) - 1
end
local t = {}
while num >= 32
do
local num2 = 32 + (num % 32) + 63
table.insert(t,string.char(num2))
num = math.floor(num / 32) -- use floor to keep integer portion only
end
table.insert(t,string.char(num + 63))
return table.concat(t)
end