Converting a number to its alphabetical counterpart in lua - lua

I am trying to make a lua script that takes an input of numbers seperated by commas, and turns them into letters, so 1 = a ect, however I have not found a way to do this easily because the string libray outputs a = 97, so I have no clue where to go now, any help?

You can use string.byte and string.char functions:
string.char(97) == "a"
string.byte("a") == 97
If you want to start from "a" (97), then just subtract that number:
local function ord(char)
return string.byte(char)-string.byte("a")+1
end
This will return 1 for "a", 2 for "b" and so on. You can make it handle "A", "B" and others in a similar way.
If you need number-to-char, then something like this may work:
local function char(num)
return string.char(string.byte("a")+num-1)
end

Merely just account for the starting value of a-z in the ascii table.
function convert(...)
local ar = {...}
local con = {}
for i,v in pairs(ar) do
table.insert(con, ("").char(v+96))
end
return con;
end
for i,v in pairs(convert(1,2,3,4)) do
print(v)
end

Alternatively to these answers, you could store each letter in a table and simply index the table:
local letters = {'a','b','c'} --Finish
print(letters[1], letters[2], letters[3])

Define your encoding as follows:
encoding = [[abc...]]
in whatever order you want.
Then use it as follows
function char(i)
return encoding:sub(i,i)
end
If the list of numbers is in a table, then you may use
function decode(t)
for i=1,#t do t[i]=char(t[i]) end
return table.concat(t)
end
You can also save the decoding in a table:
char = {}
for i=1,#encoding do char[i]=encoding:sub(i,i) end
and use char[t[i]] in decode.

Related

Lua recursive function with variable arguments

I am trying to write a string join function that will work with both tables and variable arguments as input. Here is what I have so far:
function join(separator, ...)
local result = ""
local vargs = {...}
local n = #vargs
for i = 1, n do
local varg = vargs[i]
if type(varg) == "table" then
result = join(separator, result, table.unpack(varg))
elseif varg ~= nil then
result = result..tostring(varg)
if i < n then
result = result..separator
end
end
end
return result
end
However, when I try to use it with the following input:
print(join(",", "1", "2", "3"))
print(join(",", {"a", "b", "c"}))
The output is this:
1,2,3
,a,b,c
I did not expect the , at the beginning of a,b,c.
From what I understand, it seems somehow the separator is getting added to the variable arguments when calling the function inside the function (recursiveness). But why is that? And how can I fix it? Thank you!
Try
...
if type(varg) == "table" then
varg = join(separator, table.unpack(varg))
end
if varg ~= nil then
...
Well uh sorry if it's not really useful but maybe it's because you put the: , into "" that it print the ,

Bubble Sort algorithm in Lua will not work

I am currently learning Lua, and I am attempting to create a bubble sort algorithm with it. However, I am unable to get this to work. Is anyone able to point out why?
Some details I can point out are that, on shorter lists such as lists 3 elements long, the algorithm does succeed in sorting it but then continues to sort it as if it was not sorted. On longer lists such as lists 5 elements long, the program does not sort it at all. I have gotten this information by making the program print the list every time two elements are swapped.
user_input = 0
list = {}
while user_input ~= "SORT" do
print("Input number value, or input SORT to start sort")
user_input = io.read()
if user_input ~= "SORT" then
table.insert(list, user_input)
end
end
done = false
while done == false do
done = true
for k, v in pairs(list) do
if k ~= 1 then
if list[k] < list[k - 1] then
list[k], list[k - 1] = list[k - 1], list[k]
done = false
for k, v in pairs(list) do
io.write(v .. " ")
end
print()
end
end
if k == 1 then
if list[k] < list[table.maxn(list)] then
list[k], list[table.maxn(list)] = list[table.maxn(list)], list[k]
done = false
for k, v in pairs(list) do
io.write(v .. " ")
end
print()
end
end
end
end
io.write("RESULT: ")
for k, v in pairs(list) do
io.write(v .. " ")
end
print()
In Lua there are 2 functions for creating iterators for tables pairs and ipairs
With pairs the order produced is indeterminate, it will returned all key, value pairs but the order can not be garenteed.
You can find this under next in the reference manual for Lua 5.1
example: {1,2,3,4,5} the output could be 5,2,4,1,3
the order of ipairs is 1 to the first nil it will not return any non-integer keys.
example: {1,2,3,nil,5} would give you 1,2,3
Using pairs your algorithm's output could be correct but could appear incorrect due to the ordering from pairs
You want you use ipairs to evaluate your algorithm's output, so that it will be ordered by index.
Your algorithm does not perform a bubble sort as it is now, I can include corrections for that if you want. For this initial answer I think clearing up what would create an inconsistent output should point you in the right direction.
A bubble sort should "sort" 1 index at a time, the first pass will get the last value of the array sorted. then each pass after sorts following position. for example:
before first pass 2,1,3,4,5,8,7,6
after first pass 1,2,3,4,5,7,6,8
Wikipedia has great pages for sorting algorithms with gif images that can really help understand how it should function: Bubble Sort
You're using pairs() instead of ipairs()
plus your code has an extra maxn() routine that isn't needed.
#! /usr/bin/env lua
local user_input = 0
local list = {}
while user_input ~= 'sort' do
print( 'Input number value, or input SORT to start sort' )
user_input = io.read() :lower()
-- the word 'sort' doesn't return a number, thus no final insertion
table.insert( list, tonumber( user_input ) )
end
local found_swap = true
while found_swap do
found_swap = false
for i = 2, #list do
if list[i] < list[i -1] then
list[i], list[i -1] = list[i -1], list[i]
found_swap = true
end
end
end
io.write( 'RESULT: ' )
for i, v in ipairs( list ) do
io.write( v ..' ' )
end
print()
here's my implementation, a couple notes:
My version of lua (luau) supports type checking etc. so you may need to remove : table from the paramater. (If you'd like to find more out about luau - here's the link: https://roblox.github.io/luau/ - it's really cool)
local function bubbleSort(t: table)
local function check(i, v)
local nextNum = t[i+1]
if nextNum and (nextNum < v) then
t[i] = nextNum
t[i + 1] = v
return true
end
end
local changeMade
repeat
changeMade = false
for i, v in next, t do
changeMade = check(i, v) or changeMade
end
until changeMade == false
end
local tableForSorting = {2,5,4} --2,4,5
bubbleSort(tableForSorting)
print(tableForSorting)
Hope this is of some help and shows how you can really slim down your codebase and it still work exactly the same! The reason yours wasn't working - as others - have mentioned is pairs() doesn't consistently order the list the same way.
In practise we use pairs() for dictionaries while we use ipairs() for arrays. You'll notice i'm using next in this example, next is exactly the same as ipairs(). Drop a question below if you have any follow up questions :)!

Lua How to remove apostrophe(s) from string

So I am having a issue with Lua gsub removing apostrophes from strings if there is one apostrophe on its own or loads of them i can't seem to get it to remove any of them.
local uri_without_args = "'" --one on its own
local uri_without_args = "''''''''lol''''" --in text
local uri_without_args = "''''''''''''" --loads
--etc--etc all occurrences must go
local list = {
"%'", --apostrophe
}
for k,v in ipairs(list) do
local uri_without_args_remove_duplicates, occurrences = uri_without_args:gsub(""..v.."","")
if occurrences > 0 then
occurrences = occurrences + 1
for i=1, occurrences do
if uri_without_args_remove_duplicates=="" then
--do nothing
else
uri_without_args = uri_without_args:gsub(""..v.."","")
end
end
end
end
print(uri_without_args)
The only time you assign a new value to uri_without_args is when uri_without_args_remove_duplicates is not empty. If you either remove the if statement from around the assignment to uri_without_args, or if uri_without_args starts off as "''''''''lol''''", then it works fine.
As Egor said in the comment, you also could simply use uri_without_args_remove_duplicates as the result value.

Count number of occurrences of a value in Lua table

Basically what I want to do is convert a table of this format
result={{id="abcd",dmg=1},{id="abcd",dmg=1},{id="abcd",dmg=1}}
to a table of this format:
result={{id="abcd",dmg=1, qty=3}}
so I need to know how many times does {id="abcd",dmg=1} occur in the table. Does anybody know a better way of doing this than just nested for loops?
result={{id="abcd",dmg=1},{id="defg",dmg=2},{id="abcd",dmg=1},{id="abcd",dmg=1}}
local t, old_result = {}, result
result = {}
for _, v in ipairs(old_result) do
local h = v.id..'\0'..v.dmg
v = t[h] or table.insert(result, v) or v
t[h], v.qty = v, (v.qty or 0) + 1
end
-- result: {{id="abcd",dmg=1,qty=3},{id="defg",dmg=2,qty=1}}
So you want to clear duplicate contents, although a better solution is to not let dupe contents in, here you go:
function Originals(parent)
local originals = {}
for i,object in ipairs(parent) do
for ii,orig in ipairs(originals) do
local dupe = true
for key, val in pairs(object) do
if val ~= orig[key] then
dupe = false
break
end
end
if not dupe then
originals[#originals+1] = object
end
end
return originals
end
I tried to make the code self explanatory, but the general idea is that it loops through and puts all the objects with new contents aside, and returns them after.
Warning: Code Untested

Comparing two index tables by index-value in lua

I'm attempting to compare two tables of equal length with a function, since I don't know of any other way to do so. However, with the following function, it fails to register, and I've no clue why. I'm hoping someone can provide insight to this problem or has a better way of comparing the two tables.
The tables are being populated with the following code:
str = "parameters determined by program (all digits)"
tableone = {}
for word in str:gmatch("%d") do table.insert(tableone,word) end
It's identical for both tables, except, of course, the individual table names. The tables are being populated properly, and display properly when I print them. Here are two tables for the sake of this question:
tableone = {}
tabletwo = {}
for i=1,4 do table.insert(tableone, i) end
for i=1,4 do table.insert(tabletwo, i) end
Obviously, these two tables are going to be equal to each other. The function I wrote to compare the index tables is as follows:
function comparetables(t1, t2)
matchct = 0
for i=1,#t1 do
if t1[i] == t2[i] then
matchct = matchct + 1
end
if matchct == #t1 then
return true
end
end
I tried doing
print(comparetables(tableone,tabletwo))
to see if it'll print "true" but no luck. To me, it seems like it should work without a problem. Yet it doesn't. What am I missing? I've tried searching for something like a table.compare function that someone may have already written, but no such luck in finding one. Thanks for any suggestions!
Additional information:
The reason I'm comparing tables is for a mastermaind-type game. That means the following three rules must apply when comparing tables. The function I created was to just get me started, thinking I could work from there.
When comparing the tables, if the numbers match, Ccount increases by 1.
When comparing tables, if the value exists in a different index position, increment Pcount by 1
For example, with a table of values {1, 3, 3, 4} and a guess of {4, 4, 3, 1}, it would return Pcount of 2 (the one 4 and the 1) and a Ccount of 1 (the three in the third position). I think one of the hardest parts is going to be getting the comparison to recognize that the second 4 in the guess should not increment the Pcount at all.
A slight variant on your code that should work is:
function comparetables(t1, t2)
if #t1 ~= #t2 then return false end
for i=1,#t1 do
if t1[i] ~= t2[i] then return false end
end
return true
end
However I use something more like this: It checks the types of the arguments, their metatables, and a few other cases.
-- This is not clever enough to find matching table keys
-- i.e. this will return false
-- recursive_compare( { [{}]:1 }, { [{}]:1 } )
-- but this is unusual enough for me not to care ;)
-- It can also get stuck in infinite loops if you use it on
-- an evil table like this:
-- t = {}
-- t[1] = t
function recursive_compare(t1,t2)
-- Use usual comparison first.
if t1==t2 then return true end
-- We only support non-default behavior for tables
if (type(t1)~="table") then return false end
-- They better have the same metatables
local mt1 = getmetatable(t1)
local mt2 = getmetatable(t2)
if( not recursive_compare(mt1,mt2) ) then return false end
-- Check each key-value pair
-- We have to do this both ways in case we miss some.
-- TODO: Could probably be smarter and not check those we've
-- already checked though!
for k1,v1 in pairs(t1) do
local v2 = t2[k1]
if( not recursive_compare(v1,v2) ) then return false end
end
for k2,v2 in pairs(t2) do
local v1 = t1[k2]
if( not recursive_compare(v1,v2) ) then return false end
end
return true
end
Here's an example of it in use:
print( recursive_compare( {1,2,3,{1,2,1}}, {1,2,3,{1,2,1}} ) ) -- prints true
print( recursive_compare( {1,2,3,{1,2,1}}, {2,2,3,{1,2,3}} ) ) -- prints false
If you're comparing objects that are more objecty than tabley in an Object oriented sense, then I'd look at implementing the functions in the lua OO way.
Something like this should do the trick:
GameState = {}
GameState.mt = {}
GameState.mt.fns = {}
GameState.mt.__index = GameState.mt.fns
function GameState.new(a,b,c,d)
-- TODO: put argument checks here...
local retval = {}
retval[1] = a
retval[2] = b
retval[3] = c
retval[4] = d
setmetatable(retval, GameState.mt)
return retval
end
function GameState.mt.fns.print( self )
print(" GameState: ", self[1], self[2], self[3], self[4] )
end
function GameState.mt.__tostring( self )
return "GameState: "..self[1].." "..self[2].." "..self[3].." "..self[4]
end
function GameState.mt.__eq(self, other)
-- Check it's actually a GameState, and all its bits match
return getmetatable(other)==GameState.mt and
(self[1] == other[1]) and
(self[2] == other[2]) and
(self[3] == other[3]) and
(self[4] == other[4])
end
Then you'd use it like this:
state1 = GameState.new(1,2,3,4)
state2 = GameState.new(1,2,3,4)
print("State 1 is:")
state1:print()
print("State 2 is:")
print(state2)
print( "state1 == state2 : ", state1 == state2 )
print( "Changing state 2")
state2[1]=2
print( "state1 == state2 : ", state1 == state2 )

Resources