Currying operations in lua - lua

This question has some reference to the question Defining logical operator implies in lua. The following code works fine.
local function _implies(a, b)
if a == 1 and b == 0 then return 0
else return 1 end
end
local my_right = {
__mul = function(self, b)
return _implies(self.a, b)
end
}
local _mt = {
__mul = function(a)
return setmetatable({a=a}, my_right)
end
}
local my_left={}
setmetatable(my_left,_mt)
imp = my_left
local names={}
for i = 0,1 do
for j=0,1 do
names.i=i;names.j=j
print(i, j, names.i *imp* names.j)
end
end
The following code is similar to above code. It is for logical and. The question I want to ask is : Are both and_left and and_right are required in this case as well? Were they required because implies is not commutative? In other words, can the code be made somewhat efficient for defining logand?
local function _and(a, b)
if a == 1 and b == 1 then return 1
else return 0 end
end
local right_and = {
__mul = function(self, b)
return _and(self.a, b)
end
}
local and_mt = {
__mul = function(a)
return setmetatable({a=a}, right_and)
end
}
local and_left={}
setmetatable(and_left,and_mt)
log_and = and_left
local names={}
for i = 0,1 do
for j=0,1 do
names.i=i;names.j=j
print(i, j, names.i *log_and* names.j)
end
end
Note: I know bitwise operator & is there but for some reasons, I don't want to use it.

Are both and_left and and_right are required
They were introduced because there are two semantically different multiplications involved.
But the code can be optimized.
The version below does not create a new table on every multiplication.
It also uses only one metatable instead of two.
do
local function _implies(a, b)
if a == 1 and b == 0 then
return 0
else
return 1
end
end
local temp, imp = {}, {}
local _mt = {
__mul = function(a, b)
if b == imp then
temp[1] = a
return temp
elseif a == temp then
return _implies(temp[1], b)
end
end
}
setmetatable(temp, _mt)
setmetatable(imp, _mt)
_G.imp = imp
end
local names={}
for i = 0, 1 do
for j = 0, 1 do
names.i=i
names.j=j
print(i, j, names.i *imp* names.j)
end
end

Related

find all possible combination of these two sets of items? Lua

I see similar answers to this question given in different programming languages like Haskell and Python but all of them use build-in functionality that Lua doesn't have, so please don't mark this question as duplicate.
Let's say i have two tables like bellow:
table1 = {A,B,C}
table2 = {D,E,F}
I would like to find all unique ways of matching the items from two tables, the answer should be (in informal notation):
AD,BE,CF
AD,BF,CE
AE,BD,CF
AE,BF,CD
AF,BD,CE
AF,BE,CD
so the answer will store in a table that table[1] would be {{A, D}, {B, E}, {C, F}} and so on.
tables length can be anything but both will be the same size.
we can get all shuffles via induction (not the fastest way, but pretty easy to write/understand)
local function deepcopy(orig)
local copy
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else
copy = orig
end
return copy
end
local function get_shuffles(N)
if N == 1 then
return {{1}}
end
local shuffles = get_shuffles(N-1)
local result = {}
for index = 1, #shuffles do
local shuffle = shuffles[index]
for position = 1, #shuffle do
local new_shuffle = deepcopy(shuffle)
table.insert(new_shuffle, position, N)
table.insert(result, new_shuffle)
end
local new_shuffle = deepcopy(shuffle)
table.insert(new_shuffle, N)
table.insert(result, new_shuffle)
end
return result
end
table1 = {"A", "B", "C"}
table2 = {"D","E", "F"}
assert(#table1 == #table2)
local result = {}
local shuffles = get_shuffles(#table1)
for index = 1, #shuffles do
local shuffle = shuffles[index]
local part = {}
for i = 1, 3 do
table.insert(part, {})
table.insert(part[i], table1[i])
table.insert(part[i], table2[shuffle[i]])
end
table.insert(result, part)
end
for index = 1, #result do
print(result[index][1][1], result[index][1][2], result[index][2][1], result[index][2][2], result[index][3][1], result[index][3][2])
end
function get_all_combinations(arr1, arr2)
local n, e, all_comb = #arr1, {}, {}
for j = 1, n do
e[j] = arr2[j]
end
local function generate(m)
if m <= 1 then
local comb = {}
all_comb[#all_comb + 1] = comb
for j = 1, n do
comb[j] = arr1[j]..e[j] -- it should be {arr1[j], e[j]} to fulfill your requirements
end
else
for j = 1, m do
generate(m - 1)
local k = j < m and m % 2 == 1 and 1 or j
e[k], e[m] = e[m], e[k]
end
end
end
generate(n)
return all_comb
end
for i, v in ipairs(get_all_combinations({"A", "B", "C"}, {"D", "E", "F"})) do
print(i, table.concat(v, ";"))
end
An alternate way of doing it is with the following code. This was written to help with a game (Typeshift) to discover all possible combinations of variable groups of letters. I've modified it to fit your example, though.
-- table array: { {1, 2}, {3, 4}, {5, 6} }
-- Should return { 135, 136, 145, 146, 235, 236, 245, 246 }
--
-- This uses tail recursion so hopefully lua is smart enough not to blow the stack
function arrayCombine(tableArray)
-- Define the base cases
if (tableArray == nil) then
return nil
elseif (#tableArray == 0) then
return {}
elseif (#tableArray == 1) then
return tableArray[1]
elseif (#tableArray == 2) then
return arrayCombine2(tableArray[1], tableArray[2])
end -- if
-- We have more than 2 tables in the input parameter. We want to pick off the *last*
-- two arrays, merge them, and then recursively call this function again so that we
-- can work our way up to the front.
local lastArray = table.remove(tableArray, #tableArray)
local nextToLastArray = table.remove(tableArray, #tableArray)
local mergedArray = arrayCombine2(nextToLastArray, lastArray)
table.insert(tableArray, mergedArray)
return arrayCombine(tableArray)
end -- arrayCombine
function arrayCombine2(array1, array2)
local mergedArray = {}
for _, elementA in ipairs(array1) do
for _, elementB in ipairs(array2) do
table.insert(mergedArray, elementA .. elementB)
end -- for
end -- for
return mergedArray
end -- arrayCombine2
-- You can set it up this way:
combinedArray = {}
table.insert(combinedArray, {"A", "B", "C"})
table.insert(combinedArray, {"D", "E", "F"})
for i,v in ipairs(arrayCombine(combinedArray)) do
print(i,v)
end
-- Or go this way, which may be somewhat cleaner:
for i,v in ipairs(arrayCombine({{"A", "B", "C"}, {"D", "E", "F"}})) do
print(i,v)
end
Either way, it produces the results you're looking for.

how do you make a string dictionary function in lua?

Is there a way if a string is close to a string in a table it will replace it with the one in the table?
Like a spellcheck function, that searches through a table and if the input is close to one in the table it will fix it , so the one in the table and the string is the same?
You can use this code :) Reference code is from here : https://github.com/badarsh2/Algorithm-Implementations/blob/master/Levenshtein_distance/Lua/Yonaba/levenshtein.lua
local function min(a, b, c)
return math.min(math.min(a, b), c)
end
local function matrix(row,col)
local m = {}
for i = 1,row do m[i] = {}
for j = 1,col do m[i][j] = 0 end
end
return m
end
local function lev(strA,strB)
local M = matrix(#strA+1,#strB+1)
local i, j, cost
local row, col = #M, #M[1]
for i = 1, row do M[i][1] = i - 1 end
for j = 1, col do M[1][j] = j - 1 end
for i = 2, row do
for j = 2, col do
if (strA:sub(i - 1, i - 1) == strB:sub(j - 1, j - 1)) then cost = 0
else cost = 1
end
M[i][j] = min(M[i-1][j] + 1,M[i][j - 1] + 1,M[i - 1][j - 1] + cost)
end
end
return M[row][col]
end
local refTable = {"hell", "screen"}
local function getClosestWord(pInput, pTable, threesold)
cDist = -1
cWord = ""
for key, val in pairs(pTable) do
local levRes = lev(pInput, val)
if levRes < cDist or cDist == -1 then
cDist = levRes
cWord = val
end
end
print(cDist)
if cDist <= threesold then
return cWord
else
return pInput
end
end
a = getClosestWord("hello", refTable, 3)
b = getClosestWord("screw", refTable, 3)
print(a, b)
Third parameter is threesold, if min distance is higher than threesold, word is not replaced.

Count frequency of elements into an array in Lua

I have a table in Lua:
p = {'sachin', 'sachin', 'dravid', 'Dhoni', 'yuvraj', 'kohli'}
I want to count frequency of each name in table .
test1 = {sachin=2, dravid=1, Dhoni=1, yuvraj=1, kohli=1}
I tried this program with lot of for loops .Please see my code
> function exec(ele,p)
count = 0
for k,v in pairs(p) do
if ele == p[k] then
count = count +1
end
end
return count
end
> new_table = {}
> for k,v in pairs(p) do
new_table[v] = exec(v,p)
end
>
> for k,v in pairs(new_table) do
print(k,v)
end
dhone 1
yuvraj 1
kohli 1
sachin 2
dravid 1
I want to do this more efficient way. How can I achieve this?
You can count the frequency like this:
function tally(t)
local freq = {}
for _, v in ipairs(t) do
freq[v] = (freq[v] or 0) + 1
end
return freq
end
And here's another demo example.
Using metatable may be a little unnecessary for this simple case, just showing another option:
local mt = {__index = function() return 0 end}
local newtable = {}
setmetatable(newtable, mt)
for _, v in pairs(p) do
newtable[v] = newtable[v] + 1
end
The metamethod __index above gives the table 0 as the default value.

Error while useing a Method of a Metatable 'attempt to call method (a nil value)'

I get the error 'attempt to call method 'Dot' (a nil value)' while running the following code:
-- Vector2 Class
Vector2 = {X = 0, Y = 0, Magnitude = 0, Unit = nil}
function Vector2.new(XValue,YValue)
local Tmp = {}
setmetatable(Tmp,Vector2)
Tmp.X = XValue
Tmp.Y = YValue
Tmp.Magnitude = math.sqrt(Tmp.X * Tmp.X + Tmp.Y * Tmp.Y)
if Tmp.Magnitude ~= 1 then
Tmp.Unit = Tmp/Tmp.Magnitude
else
Tmp.Unit = Tmp
end
return Tmp
end
-- Arithmetic
function Vector2.__add(A,B)
if getmetatable(A) == getmetatable(B) then
return Vector2.new(A.X+B.X, A.Y+B.Y)
end
end
function Vector2.__sub(A,B)
if getmetatable(A) == getmetatable(B) then
return Vector2.new(A.X-B.X, A.Y-B.Y)
end
end
function Vector2.__mul(A,B)
if tonumber(B) ~= nil then
return Vector2.new(A.X*B, A.Y*B)
end
end
function Vector2.__div(A,B)
if tonumber(B) ~= nil then
return Vector2.new(A.X/B, A.Y/B)
end
end
function Vector2.__unm(Tmp)
return Vector2.new(-Tmp.X, -Tmp.Y)
end
-- Comparisons
function Vector2.__eq(A,B)
if getmetatable(A) == getmetatable(B) then
if A.X == B.X and A.Y == B.Y then
return true
else
return false
end
end
end
function Vector2.__lt(A,B)
if getmetatable(A) == getmetatable(B) then
if A.Magnitude < B.Magnitude then
return true
else
return false
end
end
end
function Vector2.__le(A,B)
if getmetatable(A) == getmetatable(B) then
if A.Magnitude <= B.Magnitude then
return true
else
return false
end
end
end
-- Functionals
function Vector2.__tostring(Tmp)
return Tmp.X..", "..Tmp.Y
end
function Vector2:Dot(B)
return self.X*B.X + self.Y*B.Y
end
function Vector2:Lerp(B,Amn)
return self + (B-self)*Amn
end
print(Vector2.new(1,0.3).Magnitude)
print(Vector2.new(1,0):Dot(Vector2.new(0,1)))
I'm not understanding what I've done wrong, could anyone lend a hand, I have good Lua experience, but have just started learning how to use metatables, so I'm new at this point, I am running it using SciTE, with LuaForWindows. Error is on the very last line, but the line above it runs perfectly
You have forgotten to set __index field:
Vector2 = {X = 0, Y = 0, Magnitude = 0, Unit = nil}
Vector2.__index = Vector2

Lua table constructor values as multi-value-return function calls

Using Lua (5.1) I would like to fill the table with functions which return several values. Unfortunately, due to Lua specification such function call will only be expanded for the last one.
function get2() return 1, 2 end
local t = { get2(), get2() }
for _,v in pairs(t) do print(v) end
Returns: 1, 1, 2
Is there any way of doing this besides
table = {};
res1, res2 = get2();
table[#table + 1] = res1;
table[#table + 1] = res2
or some other convoluted technique?
No, there is no direct way to do this.
But you can simplify the code with a helper function.
function get2() return 1, 2 end
function appendMultiple(t, ...)
for i=1, select('#', ...) do
t[#t+1] = select(i, ...)
end
end
local t = { }
appendMultiple(t, get2())
appendMultiple(t, get2())
for _,v in pairs(t) do print(v) end
--> 1 2 1 2

Resources