How to update/reload table key values - lua

How can i update a key value using another key value as variable which is inside the same table?
local t = {}
t.playerPosition = {x = 0, y = 0, z = 0}
t.positions = {t.playerPosition.x + 1, t.playerPosition.y + 1, t.playerPosition.z + 1}
Then few lines later i update playerPosition
t.playerPosition = {x = 125, y = 50, z = 7}
And then if i print out...
result
t.positions[1] -- outputs 1
t.positions[2] -- outputs 1
t.positions[3] -- outputs 1
expected result
t.positions[1] -- outputs 126
t.positions[2] -- outputs 51
t.positions[3] -- outputs 8
As you can see key positions isnt updating, what could i do to make it possible?

t.positions = {t.playerPosition.x + 1, t.playerPosition.y + 1, t.playerPosition.z + 1}
In the above line, the expressions are evaluated once, and the resulting values are assigned to fields of the subtable. After this point, changes to the fields of t.playerPosition will not cause a reflected change in t.positions.
Metatables can be used to enable such behaviour, by dynamically calculating results when accessing the fields of t.positions.
local t = {}
t.playerPosition = { x = 0, y = 0, z = 0 }
t.positions = setmetatable({}, {
__newindex = function () return false end,
__index = function (_, index)
local lookup = { 'x', 'y', 'z' }
local value = t.playerPosition[lookup[index]]
if value then
return value + 1
end
end
})
print(t.positions[1], t.positions[2], t.positions[3])
t.playerPosition = {x = 125, y = 50, z = 7}
print(t.positions[1], t.positions[2], t.positions[3])

Related

Why is Lua treating tables as numbers?

I was playing around with Lua and neural networks, and I stumbled across a weird bug in my code, where Lua appears to be treating a table as a number. I have the following code...
function CreateEmptyNeuron()
local neuron = {
val = 0,
forward = { },
backward = { },
}
return neuron;
end
--layerSize is an integer representing the size of the layer we're creating.
function CreateLayer(layerSize)
local layer = {}
for i = 1, layerSize, 1 do
local n = CreateEmptyNeuron();
table.insert(layer, n)
end
return layer;
end
--layerSize is actually an array of integers representing the array sizes of
--each individual layer (first layer is the input layer, last layer is output layer)
function CreateLayers(numLayers, layerSize)
local layers = {}
for i = 1, numLayers, 1 do
local layer = CreateLayer(layerSize[i]);
table.insert(layers, layer)
end
return layers;
end
--This function initializes the "val" variable in each table, and
--forward connects each neuron to every node in the next layer...
function ForwardConnectLayers(network)
for i = 1, #network, 1 do
local layer = network[i]
local next_layer = nil
if (i+1) < #network then
next_layer = network[i+1]
else
print("We have reached the output layer...")
next_layer = nil
end
for j = 1, #layer, 1 do
local neuron = layer[j]
neuron.val = (math.random() + math.random(0, 100))/100;
if next_layer ~= nil then
for x = 1, #next_layer, 1 do
neuron.forward[x] = math.random(1, 100)/100
print("Found forward layer...")
end
else
print("We cannot forward connect the output layer...\n")
end
end
end
end
function BackwardConnectLayers(network)
for i = 1, #network, 1 do
local layer = network[i]
local prev_layer = nil
if (i-1) > 1 then
prev_layer = network[i-1]
else
print("We have reached the input layer...")
prev_layer = nil
end
for j = #layer, 1, -1 do
local neuron = layer[j]
--neuron.val = (math.random() + math.random(0, 100))/100;
if prev_layer ~= nil then
for x = 1, #prev_layer, 1 do
table.insert(neuron.backward, prev_layer[x])
print("Found input layer...")
end
else
print("We cannot backward connect the input layer...\n")
end
end
end
end
function CreateBrain()
local LAYER_SIZES = {
10, 20, 20, 5
}
local brain = CreateLayers(4, LAYER_SIZES)
ForwardConnectLayers(brain)
BackwardConnectLayers(brain)
return brain;
end
AI = CreateBrain();
AI.Run = function(inputs, expectedOutputs)
local input_layer = AI[1]
local output_layer = AI[#AI]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
--For each layer in the network...
for l = 1, #AI, 1 do
--Get the next layer and this layer...
local this_layer = AI[l]
local next_layer = AI[l+1]
--And for each neuron in the next layer...
--Multiply the value of the neuron in this layer by
--the value of the modifier, and set the value of the next
--Neuron to be nextneuron.val + sum(<x>.val*<x>[k])
if next_layer ~= nil then
for m = 1, #next_layer, 1 do
local prev_layer_sum = 0
for n = 1, #this_layer, 1 do
local neuron = this_layer[n]
print(neuron)
end
end
end
end
end
ai_inputs = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }
expected_outputs = { 8, 8, 8, 8, 8 }
AI.Run(ai_inputs, expected_outputs)
When I run the code as shown, it, as expected, prints a list of addresses to memory for Lua tables:
But then, if I alter AI.Run to the following:
AI.Run = function(inputs, expectedOutputs)
local input_layer = AI[1]
local output_layer = AI[#AI]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
--For each layer in the network...
for l = 1, #AI, 1 do
--Get the next layer and this layer...
local this_layer = AI[l]
local next_layer = AI[l+1]
--And for each neuron in the next layer...
--Multiply the value of the neuron in this layer by
--the value of the modifier, and set the value of the next
--Neuron to be nextneuron.val + sum(<x>.val*<x>[k])
if next_layer ~= nil then
for m = 1, #next_layer, 1 do
local prev_layer_sum = 0
for n = 1, #this_layer, 1 do
local neuron = this_layer[n]
for k, v in pairs(neuron) do
print(k .. ", " .. v)
end
end
end
end
end
end
I get the following error message:
Indicating that Lua thinks the table is a number... which is, suffice to say, confusing. There's probably some language technicality defining this behavior, but I can't find good documentation surrounding this (in part because I don't even know what term to search; I'm not usually a Lua programmer).
EDIT:
So, it appears, somewhere in the code, numbers are getting inserted into the layers...
(Link to online Lua compiler where you can run the code: http://tpcg.io/_WPRPQV)
Your AI.Run function does
local input_layer = AI[1]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
where inputs is a table of numbers, i.e. the first layer of your network is replaced by just numbers.
You probably want to replace the val of the neuron in that layer instead:
local input_layer = AI[1]
for i = 0, #inputs, 1 do
input_layer[i].val = inputs[i]
end

I don't Understand "How Lua save data on the same variable when we Iterate over it"

I know Lua remember value in the same field/function with the Same defined Variable. but I still lack the concept behind it. Let's say I'see Int Variable = 2 which can be modify if we iterate over it Int variable = 8
Same logic I was applying on the Code. I got the results, but I didn't understand the concept behind it.
You Can see in my Code I was saving some value in Var x and saveX
and I was doing saveX = x from my logic The value of x should be saved inside saveX instead it was saving the loop value as I'm applying over it. Why is that?
-- Graphical Representation of table1
--[[ { { {},{},{},{} },
{ {},{},{},{} },
{ {},{},{},{} },
{ {},{},{},{} } } ]]
_Gtable1 = {}
for y = 1, 4 do
table.insert(_Gtable1, {})
for x = 1, 4 do
table.insert(_Gtable1[y], {
x = (x - 1) * 10, --Coordinate value of X
y = (y - 1) * 10, --Coordinate value of Y
-- what if i want to save Coordinate value on another variable How should i do?
saveX = x, -- Saving Loop X
saveY = y, -- Saving Loo Y
t = "Check" -- to Debug
})
end
end
ti = _Gtable1
for y = 1, 4 do
for x = 1, 4 do
tim = ti[y][x]
-- print(tim.saveX) -- output 1, 2, 3, 4
print(tim.x) -- output 0, 10, 20, 30
end
end
I hope I understood the question:
Let's simplify the example:
local t = {
x = 10,
y = x,
}
You assume t.y is 10, because you declared it a line before that? But it is nil here, because x = 10, is no variable. It's part of the table constructor and can not be referenced in the same constructor. Check out https://www.lua.org/pil/3.6.html for more details.
After the constructor has finished, you can access that as t.x (not x!).
Now for your example, you need to move (x - 1) * 10 outside the constructor, e.g.: local tempX = (x - 1) * 10. Then use tempX inside the constructor. Or you can set your values individually, e.g. _Gtable1[y][x].saveX = _Gtable1[y][x].x. I would prefer the former.

How to add more then one array on same "for" in lua

how can I use "for k, j in pairs() do" for 2 arrays in lua?
local blipmarker1 = {
{ x = 10 , y = 5, z = 3 },
{ x = 5, y = 5, z= 3}
}
local blipmarker2 = {
{ x = 100, y= 150, z=30 }
}
function createtext(){
local pos = GetEntityCoords(PlayerPedId(), true)
for k, j in pairs(blipmarker1,blimarker2) do
draw3DText(pos.x, pos.y, pos.z, j.x, j.y, j.z)
end
}
Function pairs() accepts only one argument of type table. You need a loop for each table:
for k,j in pairs(blipmarker1) do
...
end
for k,j in pairs(blipmarker2) do
...
end
You could write your own stateful multipairs iterator. Consult Chapter 9.3 “Coroutines as Iterators” of Programming in Lua for more details: https://www.lua.org/pil/9.3.html
local function multipairs(tables)
return coroutine.wrap(function()
for _, t in pairs(tables) do -- Maybe you want ipairs here
for k, v in pairs(t) do
coroutine.yield(k, v)
end
end
end)
end
local blipmarker1 = {
{ x = 10 , y = 5, z = 3 },
{ x = 5, y = 5, z= 3}
}
local blipmarker2 = {
{ x = 100, y= 150, z=30 }
}
for _, j in multipairs{blipmarker1, blipmarker2} do
print(j.x, j.y, j.z)
end

Find the nearest value

I'm looking for a way to find out which value is closest to x in a table and return that.
Lets assume, for a second, X is x=15, we have the table with 4 values {12, 190, 1, 18}, How do I make it so in this case the first key&value is returned?
x = 15
table = {190, 1, 12, 18}
function NearestValue(table, number)
local smallestSoFar, smallestIndex
for i, y in ipairs(table) do
if not smallestSoFar or (math.abs(number-y) < smallestSoFar) then
smallestSoFar = math.abs(number-y)
smallestIndex = i
end
end
return smallestIndex, table[smallestIndex]
end
index, value = NearestValue(table,x)
print(index)
print(value)
I would do something like this:
initialdiff = 1000000000000
selectedkey = -1
values = {12, 190, 1, 18}
x = 15
for key, val in pairs (values) do
currentdiff = math.fabs(val - x)
if (currentdiff < initialdiff) do
initialdiff = currentdiff
selectedkey = key
end
end
-- selectedkey now holds key for closest match
-- values[selectedkey] gives you the (first) closest value

Reading and parsing files with LUA

I am trying to get it to read from a file x y z coordinates into a 3d array. But it does not seem to be working.
file is located in same folder as the .lua script
-9649.481 666.4141 117.3444
-9475.624 563.4871 116.0533
-9338.459 432.295 137.4043
function lines_from(file)
if not file_exists(file) then return {} end
for line in io.lines(file) do
tokens = {};
itr = 1;
for token in string.gmatch(line, "[^%s]+") do
tokens[ itr ] = token;
itr = itr + 1;
end
x = tokens[1];
y = tokens[2];
z = tokens[3];
g_lines_from[g_lines_fromCount] = { x, y, z };
g_lines_fromCount = g_lines_fromCount + 1;
end
end
function AddAll()
for i = 1, g_lines_from, 1 do
x, y, z = g_lines_from[i];
ListBoxEntry.Create( g_lbWaypoints, "X: " .. math.floor( x ) .. ", Y: " .. math.floor( y ) .. ", Z: " .. math.floor( z ) );
end
end
function OnAddWaypointClicked( eventID, button )
local file = "mine1-75.txt";
lines_from(file);
AddAll();
end;
Try the following function:
function readwaypoints(filename, numberofwaypoints)
local file = io.open(filename)
local waypoints = {}
for n = 1, numberofwaypoints do
local x, y, z
x = file:read('*n')
y = file:read('*n')
z = file:read('*n')
waypoints[#waypoints+1] = {['x'] = x, ['y'] = y, ['z'] = z}
end
file:close()
return waypoints
end
It takes a file name and the number of lines in the file. For your example file, it should return a table like this:
{[1] = {x = -9649.481, y = 666.4141, z = 117.3444},
[2] = {x = -9475.624, y = 563.4871, z = 116.0533},
[3] = {x = -9338.459, y = 432.295, z = 137.4043}}

Resources