In pairs loop messed up - for-loop

A normal working code but it doesn't work as i expected, seriously but wth Lua
local Exceptions = {1,2,3,5,7}
local mt = {__mod = function(v1, v2)
for i, v in pairs (v1) do
if v2 == v then
return true
else
return false
end
end
end }
setmetatable(Exceptions, mt)
print(Exceptions % 2)
v2 == v ( inside Exceptions has 2 so it should return true, but hell no, it returned false. This is annoying)

You break out of the pairs() loop when you return the result of v2 == v comparison.
The value of 2 is never reached, you exit the __mod function prematurely, reporting the result of comparing 1 and 2.

In your first loop run v2 is 2 and v is 1. As 2 ~= 1 you return false and that's it. No more iteration. Move return false after the loop.
local Exceptions = {1,2,3,5,7}
local mt = {__mod = function(v1, v2)
for i, v in pairs (v1) do
if v2 == v then
return true
end
end
return false
end }
setmetatable(Exceptions, mt)
print(Exceptions % 2)
Instead of
if v2 == v then
return true
else
return false
end
you could have simply written
return v2 == v
I personally would discourage altering the modulus operator for other things than calculating the modulus. I would have expected an element-wise modulus calcuation without seeing the implementation or any comment. Why not simply write a function isInTable(someTable, someNumber) that does the same? Same result, no confusion.

Related

Function to find X numbers that add up to a certain value

I need a function that finds a variable amount of numbers, which together must add up to a certain value. In this case it is 8.
The numbers which can be added together are predefined in a table, to make things easier.
Current approach: Shuffle the table using a small algorithm, add first X values together, if they don't add up to 8, start over (including shuffling again) until the first X values add up to 8.
My code does work, just 2 problems: It takes a long time to process (obviously) and it can cause a stack overflow error if I don't add a cooldown.
Code can be dirty, it's not for a live production. Also im only an intermediate lua developer at best...
function sleep (a) -- random sleep function I found
local sec = tonumber(os.clock() + a);
while (os.clock() < sec) do
end
end
function shuffle(tbl) -- random shuffle function I found
for i = #tbl, 2, -1 do
math.randomseed( os.time() )
math.random();math.random();math.random();math.random();
local j = math.random(i)
tbl[i], tbl[j] = tbl[j], tbl[i]
end
return tbl
end
local times = {
0.5,
1.0,
1.5,
2.0,
2.5,
3.0,
3.5,
4.0
}
local timeunits = {} --refer to line 49, I did not want to do it like that...
function nnumbersto8(amount)
local sum = 0
local numbs = {}
times = shuffle(times) --reshuffle the set
for i = 1,amount,1 do --add first x values together
sum = sum + times[i]
numbs[i] = times[i]
end
if sum ~= 8 then sleep(0.1) nnumbersto8(amount) return end --if they are not 8, repeat process with cooldown to avoid stack overflow
--return numbs -- This doesn't work for some reason, nothing gets returned outside the function
timeunits = numbs
end
nnumbersto8(5) -- manual run it for now
print(unpack(timeunits))
There must be a simpler way, right?
Thanks in advance, any help is appreciated!
Here is a method that will work for large numbers of elements, and will pick a random solution with theoretically even likelihood for each.
function solution_node (value, count, remainder)
local node = {}
node.value = value
node.count = count
node.remainder = remainder
return node
end
function choose_solutions (node1, node2)
if node1 == nil then
return node2
elseif node2 == nil then
return node1
else
-- Make a random choice of which solution to pick.
if node1.count < math.random(node1.count + node2.count) then
node2.count = node1.count + node2.count
return node2
else
node1.count = node1.count + node2.count
return node1
end
end
end
function decode_solution (node)
if node == nil then
return nil
end
answer = {}
while node.value ~= nil do
table.insert(answer, node.value)
-- This causes the solution to be randomly shuffled.
local i = math.random(#answer)
answer[#answer], answer[i] = answer[i], answer[#answer]
node = node.remainder
end
return answer
end
function random_sum(tbl, count, target)
local choices = {}
-- Normally arrays are not 0-based in Lua but this is very convenient.
for j = 0,count do
choices[j] = {}
end
-- Make sure that the empty set is there.
choices[0][0.0] = solution_node(nil, 1, nil)
for i = 1,#tbl do
for j = count,1,-1 do
for this_sum, node in pairs(choices[j-1]) do
local next_sum = this_sum + tbl[i]
local next_node = solution_node(tbl[i], node.count, node)
-- Try adding this value in to a solution.
if next_sum <= target then
choices[j][next_sum] = choose_solutions(next_node, choices[j][next_sum])
end
end
end
end
return decode_solution(choices[count][target])
end
local times = {
0.2,
0.3,
0.5,
1.0,
1.2,
1.3,
1.5,
2.0,
2.5,
3.0,
3.5,
4.0
}
math.randomseed( os.time() )
local result = random_sum(times, 5, 8.0)
print("answer")
for k, v in pairs(result) do print(v) end
Sorry for my code. I haven't coded in Lua for a few years.
This is the subset sum problem with an extra restriction on the number of elements you are allowed to choose.
The solution is to use Dynamic Programming similar to regular Subset Sum, but add an extra variable that indicates how many items you have used.
This should go something among the lines of:
Failing stop clauses:
DP[-1][x][n] = false, for all x,n>0 // out of elements
DP[i][-1][n] = false, for all i,n>0 // exceeded X items
DP[i][x][n] = false n < 0 // Passed the sum limit. This is an optimization only if all elements are non negative.
Successful stop clause:
DP[i][0][0] = true for all i >= 0
Recursive formula:
DP[i][x][n] = DP[i-1][x][n] OR DP[i-1][x-1][n-item[i]] // Watch for n<item[i] case here.
^ ^
Did not take the item Used the item
There are no solutions for 1, 2 and for values greater than 5, so the function only accepts 3, 4 and 5.
Here we are doing a shallow copy of the times table then we get a random index from the copy and begin searching for the solution, removing values we use as we go.
local times = {
0.5,
1.0,
1.5,
2.0,
2.5,
3.0,
3.5,
4.0
}
function nNumbersTo8(amount)
if amount < 3 or amount > 5 then
return {}
end
local sum = 0
local numbers = {}
local set = {table.unpack(times)}
for i = 1, amount - 1, 1 do
local index = math.random(#set)
local value = set[index]
if not (8 < (sum + value)) then
sum = sum + value
table.insert(numbers, value)
table.remove(set, index)
else
break
end
end
local reminder = 8 - sum
for _,v in ipairs(set)do
if v == reminder then
sum = sum + v
table.insert(numbers, v)
break
end
end
if #numbers == amount then
return numbers
else
return nNumbersTo8(amount)
end
end
for i=1,100 do
print(table.unpack(nNumbersTo8(5)))
end
Example response:
1.5 0.5 3 2 1
3 0.5 1.5 1 2
2 3 1.5 0.5 1
3 2 1.5 1 0.5
0.5 1 2 3 1.5

Why is the function not matching the call?

I have a function blur_1D(v, l) which takes a vector v and an integer l and for each value v[i] in v, it gets the mean of i-l to i+l and replaces v[i] to create a blur. My function isn't getting matched to the call. Here's the code.
function mean(x)
sum = 0.0
for i in 1:length(x)
sum += x[i]
end
return sum / length(x)
end
function extend(v, i)
n = length(v)
if i < 1
return v[1]
elseif i > n
return v[n]
else
return v[i]
end
end
function blur_1D(v, l)
blur_v = zeros(typeof(v[1]), length(v))
for i in 1:length(v)
box = zeros(typeof(v[i]), ((2*l)+1))
k = 1
for j in i-l:i+l
box[k] = extend(v, j)
k += 1
end
blur_v[i] = mean(box)
end
return blur_v
end
n = 100
v = rand(n)
begin
colored_line(x::Vector{<:Real}) = Gray.(Float64.((hcat(x)')))
colored_line(x::Any) = nothing
end
colored_line(blur_1D(v))
Why does it give me an error?
MethodError: no method matching blur_1D(::Array{Float64,1})
Closest candidates are:
blur_1D(::Any, !Matched::Any) at /Users/...
Please excuse any inefficient, inelegant code/syntax, but I do welcome suggestions on how I could improve that as well. :)
Perhaps the l parameter in your blur function has some default value and you normally want to use a one-parameter version.
In that case you should define function with a default value:
function blur_1D(v, l=0)
BTW, I strongly discourage using l for variable name because it can be easily be mistaken with 1 (one), especially when the code is read by somebody else.

Algorithms, DFS

I've written a program to find shortest path in a N*N grid recursively.
def dfs(x,y,Map,p):
N = len(Map)
p += [[x,y]]
if Map[x][y] == 'E':
return p
for i in [[x-1,y],[x+1,y],[x,y-1],[x,y+1]]:
if N > i[0] >= 0 and N > i[1] >= 0 :
if (Map[i[0]][i[1]] == 'P' or Map[i[0]][i[1]] == 'E') and i not in p:
dfs(i[0], i[1], Map,p)
return []
When Map[x][y] = 'E' the recursion don't stop and return p. But it goes till the end. How to correct it and return the path(p).
By the looks of it, the code is prone to loop indefinitely. This is due to lack of checks whether you've entered a node before and moving in all (4) directions from a given node.
To solve it simply, add another array NxN of Boolean values answering the question: visited?. Then update the code to something along the lines:
def dfs(x,y,Map,visited,p):
visited[x,y] = true;
N = len(Map)
(...)
if (Map[i[0]][i[1]] == 'P' or Map[i[0]][i[1]] == 'E')
and i not in p
and visited[i[0], i[1]] == false:
dfs(i[0], i[1], Map,visited,p)

Lua: How can I concatenate methods, as with the string methods?

The string funtions can used with this ways:
string.FUNCTION('myString', PARAMETER)
or replace 'string' with the string to use and call it as method
('myString'):METHOD(PARAMETER)
The last way is very fine to read and allows to concatenate methods.
-- example string operation
some_str, pos = ' some string', 1
-- default string syntax
while string.find(string.sub(some_str, pos, pos), '%s') do pos = pos +1 end
-- the same with syntactic sugar
while some_str:sub(pos, pos):find('%s') do pos = pos +1 end
So I tried to get the same behaviour with my own functions. But this fails.
The only way I found, was to use an additional parameter to say: return the object itself or the result.
Here a simple example for this.
calc = {
result = 0,
operator = '',
run = function(self, a, b, r) -- return self with r='s'
if b == 's' then r, b = b, nil end
if not b then b, a = a, self.result end
if self.operator == '+' then self.result = (a) + (b)
elseif self.operator == '-' then self.result = (a) - (b)
elseif self.operator == '*' then self.result = (a) * (b)
elseif self.operator == '/' then self.result = (a) / (b) end
if r ~= nil then return self else return self.result end
end,
add = function(self, a, b, r) self.operator = '+' return self:run(a, b, r) end,
sub = function(self, a, b, r) self.operator = '-' return self:run(a, b, r) end,
mul = function(self, a, b, r) self.operator = '*' return self:run(a, b, r) end,
div = function(self, a, b, r) self.operator = '/' return self:run(a, b, r) end
}
-- single operation
result = calc:add(12, 5)
-- concatenated operations
result = calc:add(12, 5, 's'):sub(3, 's'):mul(2, 's'):div(7)
Exists any way to do it same like in string operations?
Thanks in advance.
Your subsequent calls assign 's' to b parameter, not to r. Of course check for return self fails. Rather than give different behaviour to methods with some flags make them always return self instead and make a separate method to return current result - it will be much cleaner to read and program.
After that your call will look like:
result = calc:new(12):add(5):sub(3):mul(2):div(7):result()
Also, you don't really need proxy functions that go into one big function that splits into ifs anyway - just do everything inside add/sub/mul/div themselves.
You'll probably want more than one calc object as well, with each one having its own separate current result. Store common functions in a metatable and make :new create new instances with this metatable and separate entry for result.
local calc_meta = { __index = {
add = function(self, number) self._r = self._r + number return self end,
sub = function(self, number) self._r = self._r - number return self end,
mul = function(self, number) self._r = self._r * number return self end,
div = function(self, number) self._r = self._r / number return self end,
result = function(self) return self._r end
}}
local calc = {
new = function(self, number)
return setmetatable({
_r = number or 0
}, calc_meta) end
}
result = calc:new(12):add(5):sub(3):mul(2):div(7):result()
print(result)
-- 4
You can't completely duplicate Lua's behavior with strings - it is built-in into VM to treat string table as metatable for string values and cannot be programmed without modifying VM itself. You can get rid of extra result at end though if you add __add/__sub and other numeric methods to metatable so they would automatically "unwrap" your object to basic number value. Of course you won't be able to apply your methods to "unwrapped" value after that.

Algorithm to check matching parenthesis

This relates to the Coursera Scala course so I want to directly ask you NOT to give me the answer to the problem, but rather to help me debug why something is happening, as a direct answer would violate the Coursera honor code.
I have the following code:
def balance(chars: List[Char]): Boolean = {
val x = 0
def loop(list: List[Char]): Boolean = {
println(list)
if (list.isEmpty) if(x == 0) true
else if (list.head == '(') pushToStack(list.tail)
else if (list.head == ')') if(x <= 0) false else decreaseStack(list.tail)
else loop(list.tail)
true
}
def pushToStack(myList: List[Char]) { x + 1; loop(myList)}
def decreaseStack(myList: List[Char]) { x - 1; loop(myList)}
loop(chars)
}
A simple explanation:
If the code sees a "(" then it adds 1 to a variable. If it sees a ")" then it first checks whether the variable is equal to or smaller than 0. If this is the case, it returns false. If the value is bigger than 0 then it simply decreases one from the variable.
I have tried running the following:
if(balance("This is surely bad :-( ) (".toList)) println("balanced") else println("not balanced");
Clearly this is not balanced, but my code is returning balanced.
Again: I am not asking for help in writing this program, but rather help in explained why the code is returning "balanced" when clearly the string is not balanced
--EDIT--
def balance(chars: List[Char]): Boolean = {
val temp = 0;
def loop(list: List[Char], number: Int): Boolean = {
println(list)
if (list.isEmpty) if(number == 0) true
else if (list.head == '(') loop(list.tail, number + 1)
else if (list.head == ')') if(number <= 0) false else loop(list.tail, number - 1)
else loop(list.tail,number)
true
}
loop(chars,0)
}
^^ Still prints out balanced
You are using an immutable x when you really want a mutable x.
Here, let me rewrite it for you in a tail recursive style to show you what you're actually doing:
#tailrec def loop(myList: List[Char], cur: Int = 0): Boolean = myList match{
case "(" :: xs =>
val tempINeverUse = cur+1
loop(xs, cur) //I passed in 0 without ever changing "cur"!
case ")" :: xs if cur < 0 => false //This is a bug, regardless if you fix the rest of it
case ")" :: xs =>
val tempINeverUse = cur-1
loop(xs, cur) //Passed in 0 again!
case x :: xs => loop(xs, cur)
case Nil => cur == 0 //Since I've never changed it, it will be 0.
}
You need to keep a context of parenthesis in comments or in quotes as well. You can use a counter to achieve that. If the counter is set for a comment or a double quote then ignore any parenthesis that comes your way. Reset the counter whenever you find a finishing comment or double quote

Resources