(Lua) Condition statements not behaving as expected - lua

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.

Related

My program filters some uneven numbers but also some even numbers

So I need to write a program which gets a table as an input and gives the same table as an output without the values with even keys. So basically I need to filter out the even keys and their values and leave the uneven keys with their values.
local function selecteer_oneven(tabel)
for q, n in ipairs(tabel) do
if (q % 2) == 0 then
table.remove(tabel, q)
end
end
return tabel
end
local function printtabel(tabel)
for k,v in pairs(tabel) do
print(k,v)
end
end
io.write("Geef een lua-tabel: ")
local tabelstring = "t = "..io.read()
local string2tab = loadstring(tabelstring)
string2tab()
local resultaat = selecteer_oneven(t)
printtabel(resultaat)
my input is
{ "aap", "kat", "hond", "paard", "kip", "salamander", "programmeren is leuk" }
and my output is
1 aap
2 hond
3 paard
4 salamander
5 programmeren is leuk
(sorry it is in Dutch)
"Aap", "Hond", "Programmeren is leuk" are the only uneven ones. "paard", and "salamander" are even.
Dont do table.remove on the table you are checking at same time.
Better do a second local table and insert q.
And finaly return the second table...
local function selecteer_oneven(tabel)
local tabel2={}
for q, n in ipairs(tabel) do
if (q % 2) ~= 0 then
table.insert(tabel2, q)
end
end
return tabel2
end
...dont tested - yet ;-)
EDIT: Tested with lua -i
-- <ready>
>function selecteer_oneven(tabel)
local tabel2={}
for q, n in ipairs(tabel) do
if (q % 2) ~= 0 then
table.insert(tabel2, q)
end
end
return tabel2
end
-- <ready>
>dump(selecteer_oneven({1,2,3,4,5,6,7,8,9,10}))
1=1
2=3
3=5
4=7
5=9
-- <ready>
>-- whats dump?
-- <ready>
>code.dump
-- dump()
return function(dump)
for key,value in pairs(dump) do
io.write(string.format("%s=%s\n",key,value))
end
end
-- <ready>

How to implement combinations tail-recursively?

I'm teaching myself Lua by reading Ierusalimschy's Programming in Lua (4th edition), and doing the exercises. Exercise 6.5 is
Write a function that takes an array and prints all combinations of the elements in the array.
After this succinct statement the book gives a hint that makes it clear that what one is expected to do is to write a function that prints all the C(n, m) combinations of m elements from an array of n elements.
I implemented the combinations function shown below:
function combinations (array, m)
local append = function (array, item)
local copy = {table.unpack(array)}
copy[#copy + 1] = item
return copy
end
local _combinations
_combinations = function (array, m, prefix)
local n = #array
if n < m then
return
elseif m == 0 then
print(table.unpack(prefix))
return
else
local deleted = {table.unpack(array, 2, #array)}
_combinations(deleted, m - 1, append(prefix, array[1]))
_combinations(deleted, m, prefix)
end
end
_combinations(array, m, {})
end
It works OK, but it is not tail-recursive.
Can someone show me a tail-recursive function that does the same thing as combinations above does?
(For what it's worth, I am using Lua 5.3.)
NB: I realize that the exercise does not require that the function be tail-recursive. This is a requirement I have added myself, out of curiosity.
EDIT: I simplified the function slightly, but removing a couple of nested functions that were not adding much.
There is a third option, one that doesn't have a snake eating it's tail. Although recursion with tail-calls don't lead to stack overflow, I avoid doing so out of personal preference. I use a while loop and a stack that holds the information for each iteration. Within the loop you pop the next task from the stack, do the work, then push next task onto the stack. I feel it looks cleaner and it's easier to visualize the nesting.
Here is how I would translate your code into the way I would write it:
function combinations(sequence, item)
local function append(array, item)
local copy = {table.unpack(array)}
copy[#copy + 1] = item
return copy
end
local stack = {}
local node = { sequence, item, {} }
while true do
local seq = node[ 1 ]
local itm = node[ 2 ]
local pre = node[ 3 ]
local n = #seq
if itm == 0 then
print(table.unpack(pre))
elseif n < itm then
-- do nothing
else
local reserve = {table.unpack(seq, 2, #seq)}
table.insert(stack, { reserve, itm, pre })
table.insert(stack, { reserve, itm-1, append(pre, seq[ 1 ]) })
end
if #stack > 0 then
node = stack[ #stack ] -- LIFO
stack[ #stack ] = nil
else
break
end
end
end
You can use this while-loop stack/node technique for just about any recursive method. Here is an example where it's applied to printing deeply nested tables: https://stackoverflow.com/a/42062321/5113346
My version, using your input example gives the same output:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5.
Forgive me if it doesn't work with other passed params because I didn't try to solve the answer to the exercise but rather just rewrite the code in your original post.
OK, I think I found one way to do this:
function combinations (array, m)
local dropfirst = function (array)
return {table.unpack(array, 2, #array)}
end
local append = function (array, item)
local copy = {table.unpack(array)}
copy[#copy + 1] = item
return copy
end
local _combinations
_combinations = function (sequence, m, prefix, queue)
local n = #sequence
local newqueue
if n >= m then
if m == 0 then
print(table.unpack(prefix))
else
local deleted = dropfirst(sequence)
if n > m then
newqueue = append(queue, {deleted, m, prefix})
else
newqueue = queue
end
return _combinations(deleted, m - 1,
append(prefix, sequence[1]),
newqueue)
end
end
if #queue > 0 then
newqueue = dropfirst(queue)
local newargs = append(queue[1], newqueue)
return _combinations(table.unpack(newargs))
end
end
_combinations(sequence, m, {}, {})
end
This version is, I think, tail-recursive. Unfortunately, it does not print out the results in as nice an order as did my original non-tail-recursive version (not to mention the added complexity of the code), but one can't have everything!
EDIT: Well, no, one can have everything! The version below is tail-recursive, and prints its results in the same order as does the original non-tail-recursive version:
function combinations (sequence, m, prefix, stack)
prefix, stack = prefix or {}, stack or {}
local n = #sequence
if n < m then return end
local newargs, newstack
if m == 0 then
print(table.unpack(prefix))
if #stack == 0 then return end
newstack = droplast(stack)
newargs = append(stack[#stack], newstack)
else
local deleted = dropfirst(sequence)
if n > m then
newstack = append(stack, {deleted, m, prefix})
else
newstack = stack
end
local newprefix = append(prefix, sequence[1])
newargs = {deleted, m - 1, newprefix, newstack}
end
return combinations(table.unpack(newargs)) -- tail call
end
It uses the following auxiliary functions:
function append (sequence, item)
local copy = {table.unpack(sequence)}
copy[#copy + 1] = item
return copy
end
function dropfirst (sequence)
return {table.unpack(sequence, 2, #sequence)}
end
function droplast (sequence)
return {table.unpack(sequence, 1, #sequence - 1)}
end
Example:
> combinations({1, 2, 3, 4, 5}, 3)
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
Ironically, this version achieves tail-recursion by implementing its own stack, so I am not sure it is ultimately any better than the non-tail-recursive version... Then again, I guess the function's stack actually lives in the heap (right?), because Lua's tables are passed around by reference (right?), so maybe this is an improvement, after all. (Please correct me if I'm wrong!)

"translating" One character to another in lua

I want to make a lua script that takes the input of a table, then outputs the strings in that table in their full width counterparts, eg
input = {"Hello", " ", "World"}
print(full(table.concat(input)))
and it will print "Hello World"
I tried it using this:
local encoding = [[ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!゛#$%&()*+、ー。/:;〈=〉?@[\\]^_‘{|}~]]
function char(i)
return encoding:sub(i:len(),i:len())
end
function decode(t)
for i=1,#t do t[i]=char(t[i]) end
return table.concat(t)
end
function returns(word, word_eol)
print(char(word_eol[2]))
end
but that did not work
note: it is a plugin for hexchat that's why I have it as print(char(word_eol[2])))
Because when you hook a command in hexchat it spits out a table that is the command name, then what was entered after
If (string) = [[ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!゛#$%&()*+、ー。/:;〈=〉?@[\]^_‘{|}~]], you're finding the n th character of (string), with n being the length of the character, which will always be one. If I understand correctly, this will do the job, by having a separate alphabet and matching the characters.
local encoding = [[ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!゛#$%&()*+、ー。/:;〈=〉?@[]^_‘{|}~]]
local decoding = [[ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&()*+,-./:;{=}?#[]^_'{|}~]]
function char(i)
local l = decoding:find(i,1,true)
return encoding:sub(l,l)
end
function decode(t)
for i=1,#t do t[i]=char(t[i]) end
return table.concat(t)
end
function returns(word, word_eol)
print(char(word_eol[2]))
end
function full(s)
return (s:gsub('.', function(c)
c = c:byte()
if c == 0x20 then
return string.char(0xE3, 0x80, 0x80)
elseif c >= 0x21 and c <= 0x5F then
return string.char(0xEF, 0xBC, c+0x60)
elseif c >= 0x60 and c <= 0x7E then
return string.char(0xEF, 0xBD, c+0x20)
end
end))
end

Element by Element comparison in Lua

I'm trying to find a way to do element-by-element comparison in Lua using the standard < operator. For example, here's what I'd like to do:
a = {5, 7, 10}
b = {6, 4, 15}
c = a < b -- should return {true, false, true}
I already have code working for addition (and subtraction, multiplication, etc). My issue is that Lua forces the result of a comparison to a boolean. I don't want a boolean, I want a table as the result of the comparison.
Here is my code so far, with addition working, but less-than comparison not working:
m = {}
m['__add'] = function (a, b)
-- Add two tables together
-- Works fine
c = {}
for i = 1, #a do
c[i] = a[i] + b[i]
end
return c
end
m['__lt'] = function (a, b)
-- Should do a less-than operator on each element
-- Doesn't work, Lua forces result to boolean
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
end
a = {5, 7, 10}
b = {6, 4, 15}
setmetatable(a, m)
c = a + b -- Expecting {11, 11, 25}
print(c[1], c[2], c[3]) -- Works great!
c = a < b -- Expecting {true, false, true}
print(c[1], c[2], c[3]) -- Error, lua makes c into boolean
The Lua programming manual says that the result of the __lt metamethod call is always converted to a boolean. My question is, how can I work around that? I heard that Lua is good for DSL, and I really need the syntax to work here. I think it should be possible using MetaLua, but I'm not really sure where to start.
A coworker suggested that I just use << instead with the __shl metamethod. I tried it and it works, but I really want to use < for less than, rather than a hack using the wrong symbol.
Thanks!
You only have two choices to make this work with your syntax:
Option 1: Patch the Lua core.
This is probably going to be very difficult, and it'll be a maintenance nightmare in the future. The biggest issue is that Lua assumes on a very low level that the comparison operators <, >, ==, ~= return a bool value.
The byte-code that Lua generates actually does a jump on any comparison. For example, something like c = 4 < 5 gets compiled to byte-code that looks much more like if (4 < 5) then c = true else c = false end.
You can see what the byte-code looks like with luac -l file.lua. If you compare the byte-code of c=4<5 with c=4+5 you'll see what I mean. The addition code is shorter and simpler. Lua assumes you'll do branching with comparisons, not assignment.
Option 2: Parse your code, change it, and run that
This is what I think you should do. It would be very hard, expect most of the work is already done for you (using something like LuaMinify).
First of all, write a function you can use for comparisons of anything. The idea here is to do your special comparison if it's a table, but fall back on using < for everything else.
my_less = function(a, b)
if (type(a) == 'table') then
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
else
return a < b
end
end
Now all we need to do is replace every less than operator a<b with my_less(a,b).
Let's use the parser from LuaMinify. We'll call it with the following code:
local parse = require('ParseLua').ParseLua
local ident = require('FormatIdentity')
local code = "c=a*b<c+d"
local ret, ast = parse(code)
local _, f = ident(ast)
print(f)
All this will do is parse the code into a syntax tree, and then spit it back out again. We'll change FormatIdentity.lua to make it do the substitution. Replace the section near line 138 with the following code:
elseif expr.AstType == 'BinopExpr' then --line 138
if (expr.Op == '<') then
tok_it = tok_it + 1
out:appendStr('my_less(')
formatExpr(expr.Lhs)
out:appendStr(',')
formatExpr(expr.Rhs)
out:appendStr(')')
else
formatExpr(expr.Lhs)
appendStr( expr.Op )
formatExpr(expr.Rhs)
end
That's all there is to it. It will replace something like c=a*b<c+d with my_less(a*b,c+d). Just shove all your code through at runtime.
Comparisons in Lua return a boolean value.
There is nothing you can do about it short of changing the core of Lua.
Can you put up with a bit verbose v()-notation:
v(a < b) instead of a < b ?
local vec_mt = {}
local operations = {
copy = function (a, b) return a end,
lt = function (a, b) return a < b end,
add = function (a, b) return a + b end,
tostring = tostring,
}
local function create_vector_instance(operand1, operation, operand2)
local func, vec = operations[operation], {}
for k, elem1 in ipairs(operand1) do
local elem2 = operand2 and operand2[k]
vec[k] = func(elem1, elem2)
end
return setmetatable(vec, vec_mt)
end
local saved_result
function v(...) -- constructor for class "vector"
local result = ...
local tp = type(result)
if tp == 'boolean' and saved_result then
result, saved_result = saved_result
elseif tp ~= 'table' then
result = create_vector_instance({...}, 'copy')
end
return result
end
function vec_mt.__add(v1, v2)
return create_vector_instance(v1, 'add', v2)
end
function vec_mt.__lt(v1, v2)
saved_result = create_vector_instance(v1, 'lt', v2)
end
function vec_mt.__tostring(vec)
return
'Vector ('
..table.concat(create_vector_instance(vec, 'tostring'), ', ')
..')'
end
Usage:
a = v(5, 7, 10); print(a)
b = v(6, 4, 15); print(b)
c = a + b ; print(c) -- result is v(11, 11, 25)
c = v(a + b); print(c) -- result is v(11, 11, 25)
c = v(a < b); print(c) -- result is v(true, false, true)
As others have already mentioned, there is no straight-forward solution to this. However, with the use of a generic Python-like zip() function, such as the one shown below, you can simplify the problem, like so:
--------------------------------------------------------------------------------
-- Python-like zip() iterator
--------------------------------------------------------------------------------
function zip(...)
local arrays, ans = {...}, {}
local index = 0
return
function()
index = index + 1
for i,t in ipairs(arrays) do
if type(t) == 'function' then ans[i] = t() else ans[i] = t[index] end
if ans[i] == nil then return end
end
return table.unpack(ans)
end
end
--------------------------------------------------------------------------------
a = {5, 7, 10}
b = {6, 4, 15}
c = {}
for a,b in zip(a,b) do
c[#c+1] = a < b -- should return {true, false, true}
end
-- display answer
for _,v in ipairs(c) do print(v) end

Lua Operator Overloading

I've found some places on the web saying that operators in Lua are overloadable but I can't seem to find any example.
Can someone provide an example of, say, overloading the + operator to work like the .. operator works for string concatenation?
EDIT 1: to Alexander Gladysh and RBerteig:
If operator overloading only works when both operands are the same type and changing this behavior wouldn't be easy, then how come the following code works? (I don't mean any offense, I just started learning this language):
printf = function(fmt, ...)
io.write(string.format(fmt, ...))
end
Set = {}
Set.mt = {} -- metatable for sets
function Set.new (t)
local set = {}
setmetatable(set, Set.mt)
for _, l in ipairs(t) do set[l] = true end
return set
end
function Set.union (a,b)
-- THIS IS THE PART THAT MANAGES OPERATOR OVERLOADING WITH OPERANDS OF DIFFERENT TYPES
-- if user built new set using: new_set = some_set + some_number
if type(a) == "table" and type(b) == "number" then
print("building set...")
local mixedset = Set.new{}
for k in pairs(a) do mixedset[k] = true end
mixedset[b] = true
return mixedset
-- elseif user built new set using: new_set = some_number + some_set
elseif type(b) == "table" and type(a) == "number" then
print("building set...")
local mixedset = Set.new{}
for k in pairs(b) do mixedset[k] = true end
mixedset[a] = true
return mixedset
end
if getmetatable(a) ~= Set.mt or
getmetatable(b) ~= Set.mt then
error("attempt to 'add' a set with a non-set value that is also not a number", 2)
end
local res = Set.new{}
for k in pairs(a) do res[k] = true end
for k in pairs(b) do res[k] = true end
return res
end
function Set.tostring (set)
local s = "{"
local sep = ""
for e in pairs(set) do
s = s .. sep .. e
sep = ", "
end
return s .. "}"
end
function Set.print (s)
print(Set.tostring(s))
end
s1 = Set.new{10, 20, 30, 50}
s2 = Set.new{30, 1}
Set.mt.__add = Set.union
-- now try to make a new set by unioning a set plus a number:
s3 = s1 + 8
Set.print(s3) --> {1, 10, 20, 30, 50}
The metatable function only works on tables, but you can use debug.metatable to set the strings metatable...
> mt = {}
> debug.setmetatable("",mt)
> mt.__add = function (op1, op2) return op1 .. op2 end
> ="foo"+"bar"
foobar
>
Another approach is to use debug.getmetatable to augment the built-in string metatable (answering the question in the comment below):
~ e$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> debug.getmetatable("").__add = function (op1, op2) return op1 .. op2 end
> ="foo"+"bar"
foobar
>
See the Metatables section of Lua Programming Manual and Metatables and Metamethods chapter of the Programming in Lua 2nd edition.
Note that for comparison operators operator overloading works only when both operand types are the same.

Resources