Can't declare table element with number from another table - arrays

Code is very simple. Declaring two tables, a simple and a multi-dimensional:
Player = {X_Pos = 1, Y_Pos = 1, Current_Sprite_Num = 100}
for j=1, Max_col_length do -- value ofMax_col_length doesn't matter here; positive integer anyway
MapLayer_B[j] = {}
for i=1, Max_row_length do --same here
MapLayer_B[j][i] = 1
end
end
Then I try to do this operation:
MapLayer_B[Player[X_Pos]][Player[Y_Pos]] = Player[Current_Sprite_Num]
It should replace the Player[X_Pos]th element of the Player[Y_Pos]th rowtable in MapLayer_B. Instead, I got this error with LÖVE compiler:
Error: attempt to index field '?' (a nil value)
I don't really get, why it happens, since all elements of both MapLayer_B andPlayer tables are declared and not kept in nil.
Any ideas?

You need to use Player.X_Pos instead of Player[X_Pos] and so on.
The brackets notation will interpret "X_Pos" as a variable and try to access taht key instead (the reason for the error is that undefined variables default to null)
t = {a = 17}
print( t.a ) --dot notation is simpler
print( t["a"] ) --bracket notation expects a string
key = "a" --that string can be from a variable
print( t[key] )

Related

Minizinc: counting number of different variables in array associated with initial output array

I'm trying to count occurrences within an array that are constrained by first having the same value in the array then by the number of different variables found an associated array.
I am starting with this model
set of int: OPTS = 1..4;
set of int: ASSIGN = 1..12;
array[ASSIGN] of var OPTS: result;
that can generate a result [ 1,2,1,3,3,4,1,3,1,1,2,4 ]
and would like to combine with these statements
enum CONDS = {A,B,C,D};
array[ASSIGN] of CONDS : const = [A,A,A,B,B,B,C,C,C,D,D,D];
array[OPTS] of var 0..max(CONDS): result2;
output ["\(result) \(result2)"]
and produce an output that counts how many different CONDS appear for each OPTS
[ 1,2,1,3,3,4,1,3,1,1,2,4 ] [3,2,2,2]
implying that OPTS[1] is associated with at least one of A,C and D, OPTS[2] has As and Ds, OPTS[3] has Bs and Cs, and OPTS[4] has Cs and Ds. I've scrambled my brains a bit with this and earlier questions and can't determine whether to look at creating a less complex constraint, or a more complex one. I could have missed a simple trick here...or maybe it's not so obvious?
I would love to know why my attempt with the following produces unsatisfiable when X = j, [0,0,3,0] when X = 1 and '[0,0,0,0]' when X = i (which would make east sense to me, but clearly I don't know how this position 'X' is supposed to work with the rest).
constraint forall(i in OPTS, j in CONDS)(
result2[i] =
count([ k == j /\ result[k] = i | k in const],X)
);
Here's a model that solves your original question. The construct card({const[i] | i in ASSIGN where result[i]=o} ), counts the number of different values of OPTS with the set comprehension {....}, using card (the cardinality of the set) to do the counting.
include "globals.mzn";
set of int: OPTS = 1..4;
set of int: ASSIGN = 1..12;
array[ASSIGN] of var OPTS: result = [1,2,1,3,3,4,1,3,1,1,2,4];
enum CONDS = {A,B,C,D};
array[ASSIGN] of CONDS : const = [A,A,A,B,B,B,C,C,C,D,D,D];
array[OPTS] of var 0..max(ASSIGN): result2;
solve satisfy;
constraint
forall(o in OPTS) (
% count the number of different CONDS for this OPTS value o
result2[o] = card({const[i] | i in ASSIGN where result[i]=o} )
)
;
output [
"result:\(result)\n",
"result2:\(result2)\n",
];
The solution is
result:[1, 2, 1, 3, 3, 4, 1, 3, 1, 1, 2, 4]
result2:[3, 2, 2, 2]
Update: Answer to the additional question
You asked why this constraint don't give the proper answer:
constraint forall(i in OPTS, j in CONDS)(
result2[i] =
count([ k == j /\ result[k] = i | k in const],X)
);
Here are some problems with this approach.
First I should say that this kind of loop might in general be a good approach, but the problem statement requires that we count the number of different chunks (were each chunk contains many values), not the number of all occurrences.
The k in const loops through all the values A,A,A,B,B,... (not the indices) which mean thatresult[k] is interpreted as result[A] ... result[D] which is then translated to as result[1] ... result[4] (A=1,B=2,C=3,D=4) which is not what you want.
Instead, k should loop though ASSIGN and instead of the plaink is should then be conds[k].
Another problem is that result2[i] is evaluated for every j in CONDS, i.e. it do "double counting" which almost always mean trouble. (Note also that in constraint programming values are never updated. If one got one value in results[i] in one loop and another value in another, then the model is UNSAT.)
Instead a nested loop should be used:
constraint
forall(i in OPTS) (
forall(j in CONDS) (
% ...
)
);
However, using count (or sum) means that you count all the
occurrences of the CONDS, e.g. for the value 1 this counts
two A's (from the first chunk) which is not correct.
To fix this one have to just count one occurrence of the CONDS. In the model above I use the set approach. Here's another way, using exists which just count one of each matching CONDS values.
constraint
forall(o in OPTS) (
result2[o] = sum(c in CONDS) (
exists(k in ASSIGN) ( const[k] = c /\ result[k] = o)
)
)
;

LUA - Arrays management (add/remove elements)

I have two arrays:
A={4,8,12}
B={1,2,3,5,6,7,9,10,11}
And these code, the essence of which is, when calling the function, take a random value from array B, insert it in the order of the queue into array A, and, in another loop, remove that random value from array B.
local function Change ()
local q= math.random(1, #B)
for i = 1, #A do
if B[q]<A[i] then
for t=#A, i, -1 do
A[t+1]=A[t]
end
A[i]=B[q]
break
end
end
while q<= #B-1 do
B[q]=B[q+1]
q=q+1
end
B[q]=nil
for x = 1, #A do print ("Current: ", A[x]) end
for y = 1, #B do print ("Free: ", B[y]) end
end
Now I want to use the same code, for the inverse problem - take a random value from array A, insert it in the order of the queue into array B, and then delete the value from array A.
So I want something like this:
Change (A, B) – find random value in B and insert to A (arrays)
Change (B, A) – find random value in A and insert to B (arrays)
Is there any way in Lua to do this? Pointers or so...
P.S. I dont want to use "table.sort/table.insert", etc for this task.
P.P.S. We found solution in thread with pointer, but today I found another solution:
C={{4,8,12},{1,2,3,5,6,7,9,10,11}}
Local function Change (x,y)
a= math.random(1, #C[y])
for i = 1, #C[x] do
if C[y][a]<C[x][i] then
for t=#C[x], i, -1 do
C[x][t+1]=C[x][t]
end
C[x][i]=C[y][a]
break
end
end
while a<= #C[y]-1 do
C[y][a]=C[y][a+1]
a=a+1
end
C[y][a]=nil
for i = 1, #C[x] do print ("in C"..x, C[x][i]) end
for i = 1, #C[y] do print ("in C"..y, C[y][i]) end
end
and call Change(1,2) or Change (2,1)
How do you think, which method is better in performance?
Also I have another question in LUA syntax
When I make
C={ A={4,8,12}, B={1,2,3,5,6,7,9,10,11} }
And try inside the function #C[1] or #C[2] I got error «attempt to get length of field '?' (a nil value)» but it was very clear to write C.A or C.B instead of C[1], C[2] later in code
I had to initialize them like
A={4,8,12}, B={1,2,3,5,6,7,9,10,11}, C={A,B}
but got other error «attempt to get length of field ‘C’ (a nil value)» when use C.A or C.B.
In Lua, tables are the only objects which are shared when placed in variables.
mytable = {1,2,3}
newtable = mytable
newtable[1] = "one"
print(mytable[1]) --> prints: "one"
So in your code, we can change the hardcoded tables to variables:
local function Change(insertTable, valueTable)
local q = math.random(1, #valueTable)
for i = 1, #insertTable do
if valueTable[q] < insertTable[i] then
for t = #insertTable, i, -1 do
insertTable[t+1] = insertTable[t]
end
insertTable[i] = valueTable[q]
break
end
end
while q <= #valueTable-1 do
valueTable[q] = valueTable[q+1]
q = q+1
end
valueTable[q] = nil
for x = 1, #insertTable do print("Current: ", insertTable[x]) end
for y = 1, #valueTable do print("Free: ", valueTable[y]) end
end

Moving PostgreSQL bigint array unique value to another index

How can I move the array bigint value from one index to another? For example, I have an array ARRAY[1, 2, 3, 4] of bigint unique values and want to move value 1 to index 3 so the final result would be ARRAY[2, 3, 1, 4]
The assumptions:
Element in the array identified by the value.
The uniqueness of the elements guaranteed.
Any element can be moved to any place.
Null values not involved on any side.
The value is contained in the array if not we have 2 options. First is do nothing and second handling of this exception by exception mechanism. It's an extreme case that can happen only because of some BUG
Arrays are 1-dimensional.
General assumptions:
Array elements are UNIQUE NOT NULL.
Arrays are 1-dimensional with standard subscripts (1..N). See:
Normalize array subscripts for 1-dimensional array so they start with 1
Simple solution
CREATE FUNCTION f_array_move_element_simple(_arr bigint[], _elem bigint, _pos int)
RETURNS bigint[] LANGUAGE sql IMMUTABLE AS
'SELECT a1[:_pos-1] || _elem || a1[_pos:] FROM array_remove(_arr, _elem) a1'
All fine & dandy, as long as:
The given element is actually contained in the array.
The given position is between 1 and the length of the array.
Proper solution
CREATE FUNCTION f_array_move_element(_arr ANYARRAY, _elem ANYELEMENT, _pos int)
RETURNS ANYARRAY AS
$func$
BEGIN
IF _pos IS NULL OR _pos < 1 THEN
RAISE EXCEPTION 'Target position % not allowed. Must be a positive integer.', _pos;
ELSIF _pos > array_length(_arr, 1) THEN
RAISE EXCEPTION 'Target position % not allowed. Cannot be greater than length of array.', _pos;
END IF;
CASE array_position(_arr, _elem) = _pos -- already in position, return org
WHEN true THEN
RETURN _arr;
WHEN false THEN -- remove element
_arr := array_remove(_arr, _elem);
ELSE -- element not found
RAISE EXCEPTION 'Element % not contained in array %!', _elem, _arr;
END CASE;
RETURN _arr[:_pos-1] || _elem || _arr[_pos:];
END
$func$ LANGUAGE plpgsql IMMUTABLE;
Exceptions are raised if any of the additional assumptions for the simple func are violated.
The "proper" function uses polymorphic types and works for any data type, not just bigint - as long as array and element type match.
db<>fiddle here
Postgresql supports slicing and appending so:
SELECT c, c[2:3] || c[1] || c[4:] AS result
FROM (SELECT ARRAY[1, 2, 3, 4] c) sub
db<>fiddle demo
Another variant using 'WITH .. SELECT ..' avoid searching elements by value, just array element numbers. jsonb[] with big jsons for example.
test_model.data - field to update.
:idx_from, :idx_to - placeholders, 1-based.
WITH from_removed AS (
SELECT
test_model.id,
ARRAY_CAT(
data[: :idx_from - 1],
data[:idx_from + 1 :]
) AS "d"
FROM test_model
)
UPDATE test_model AS source
SET data =
from_removed.d[: :idx_to - 1] ||
data[:idx_from : :idx_from] ||
from_removed.d[:idx_to :]
FROM from_removed
WHERE source.id = from_removed.id AND source.id = :id

Lua doesn't go over 'nil' in table

I have such an anonymous Lua function:
an_func = function(x) return x == nil end
I need to test it on a table from 4 values: {'None', nil, 1, '1'}.
So, I wrote the following code:
for num, element in pairs({'None', nil, 1, '1'}) do
print(num .. ': ' .. tostring(an_func(element)))
end
When I ran it, I got only three lines:
1: false
3: false
4: false
The line with the true value (corresponding to nil table element) didn't print.
Can you explain, why did Lua print all results, but true? How can I fix the snipped make it output all 4 lines?
P.S. I'm newbee in Lua.
When using pairs(), it goes over all elements of a table. nil means nothing, so it won't go over it. Why should it tell you there's nothing in the table? If you have a totally new table, it'll return nil if you index it with anything. print(({}).test) --> nil
If you really want to get the nil, you could use a dummy value:
local NIL = setmetatable({},{__tostring=function() return "nil" end})
an_func = function(x) return x == NIL end
for num, element in pairs({'None', NIL, 1, '1'}) do
print(num .. ': ' .. tostring(an_func(element)))
end
Output:
1: false
2: true
3: false
4: false
In Lua, everything (a function, string, thread, ...) is a value, with nil (and technically none/void) being the only exception(s). To put simply, nil represents the absence of value. So when iterating over a table, why would Lua say there is nothing there. If it did it would have to iterate over every virtually possible index you can create.
However it appears you are using an array. You technically can iterate over it assuming you know the length. I'll make the assumption that the last item in the table is NOT nil, and that there wasn't any holes assigned after the initial length of the table with holes, however this may not necessarily be true in your case, if it isn't you will have to keep track of the length yourself and use it rather than the # operator:
for i = 1,#t do
local v = t[i]
print (v == nil)
end
Other answers address your second question well but the simple explanatory facts are Any key with value nil is not considered part of the table. Conversely, any key that is not part of a table has an associated value nil. Assigning a value of nil removes any existing key-value pair with the same key.
You would need to loop through all keys you want to print the values for.
Possible ways:
Know the length beforehand. (warspyking noted about this)
Using an end marker.
Calculate the length somehow (for example with maxn).
Use something to represent nil values. (EinsteinK showed an example
of this)
Each has their good and bad sides, here are some:
For the first you would need to know the length beforehand in all cases which may be difficult.
The end marker is convenient, but requires you to shift around the end marker.
Calculating length would not work if the last element is nil.
Example of calculating the length - assuming last element is not nil.
Note that lua 5.1 has table.maxn that you can use instead of this custom implementation of maxn.
an_func = function(x) return x == nil end
function maxn(t)
local n = 0
for k,v in pairs(t) do
if k%1 == 0 then
n = k
end
end
return n
end
local t = {'None', nil, 1, '1'}
for num = 1, maxn(t) do
print(num .. ': ' .. tostring(an_func(t[num])))
end
Example of using an end marker:
an_func = function(x) return x == nil end
local END = {}
local t = {'None', nil, 1, '1', END}
local num = 1
while t[num] ~= END do
print(num .. ': ' .. tostring(an_func(t[num])))
num = num+1
end

How to remove all 'nil' values from an array?

I have an array of objects (or just numbers), and I have another array which contains all the objects that should not be removed from the first array in any circumstances. It looks something like this:
-- Array of objects (just numbers for now)
Objects = {}
-- Array of objects that should always stay in the 'Objects' array
DontDestroyThese = {}
-- Populate the arrays
Objects[#Objects+1] = 1
Objects[#Objects+1] = 2
Objects[#Objects+1] = 3
Objects[#Objects+1] = 4
Objects[#Objects+1] = 5
DontDestroyThese[#DontDestroyThese+1] = 2
DontDestroyThese[#DontDestroyThese+1] = 5
Now, I have a method called destroy() that should remove all objects from the Objects array except those included in the DontDestroyThese array. The method looks something like this:
function destroy()
for I = 1, #Objects do
if(DontDestroyThese[Objects[I]] ~= nil) then
print("Skipping " .. Objects[I])
else
Objects[I] = nil
end
end
end
However, as the result, the Objects array now contains nil values here and there. I'd like to remove these nils so that the Objects array would consist only of the numbers that were left there after calling destroy(). How do I do that?
The most efficient way is probably to create a new table to hold the result. Trying to move values around in the array is likely to have a higher overhead than simply appending to a new table:
function destroy()
local tbl = {}
for I = 1, #Objects do
if(DontDestroyThese[Objects[I]] ~= nil) then
table.insert(tbl, Objects[I])
end
end
Objects = tbl
end
This method also means you don't have to deal with altering the contents of the table/array you're iterating over.
I think the solution is much simpler. To remove any nils ('holes' in your array), all you need to do is iterate your table using pairs(). This will skip over any nils returning only the non-nil values that you add to a new local table that is returned in the end of the 'cleanup' function. Arrays (tables with indices from 1..n) will remain with the same order. For example:
function CleanNils(t)
local ans = {}
for _,v in pairs(t) do
ans[ #ans+1 ] = v
end
return ans
end
Then you simply need to do this:
Objects = CleanNils(Objects)
To test it:
function show(t)
for _,v in ipairs(t) do
print(v)
end
print(('='):rep(20))
end
t = {'a','b','c','d','e','f'}
t[4] = nil --create a 'hole' at 'd'
show(t) --> a b c
t = CleanNils(t) --remove the 'hole'
show(t) --> a b c e f
local function remove(t, pred)
for i = #t, 1, -1 do
if pred(t[i], i) then
table.remove(t, i)
end
end
return t
end
local function even(v)
return math.mod(v, 2) == 0
end
-- remove only even numbers
local t = remove({1, 2, 3, 4}, even)
-- remove values you want
local function keep(t)
return function(v)
return not t[v]
end
end
remove(Objects, keep(DontDestroyThese))

Resources