value created from loop index incorrect - loops
I'm probably overlooking something simple.
I'm looping through a 2D Array assigning values to variables in each object in the array. However when 'j' increments the value assigned to gameArray[1][1].x changes from 100 to 400, while it shouldn't be changed after the initial assignment.
--create tilemap 5x5 array
for i = 1, gridSize.x, 1 do
gameArray[i] = {}
for j = 1, gridSize.y, 1 do
gameArray[i][j] = tileArray[math.random(numTiles)]
gameArray[i][j].x = (i * 100)
gameArray[i][j].y = (j * 100)
debug.debug()
end
end
tileArray[x] is an object containing 4 integers and a love2D image loaded from a PNG.
--tUD
tileArray[1].u = 1
tileArray[1].r = 0
tileArray[1].d = 1
tileArray[1].l = 0
tileArray[1].img = love.graphics.newImage('tiles/tUD.png')
Below is a copy of the debug console while testing:
lua_debug> print(gameArray[1][1].y)
100
lua_debug> cont
lua_debug> print(gameArray[1][1].y)
100
lua_debug> cont
lua_debug> print(gameArray[1][1].y)
100
lua_debug> cont
lua_debug> print(gameArray[1][1].y)
400
lua_debug>
Any ideas what may be causing this?
Your inner loop is overwriting previously stored values in gameArray[i][j].y. This is because of this line:
gameArray[i][j] = tileArray[math.random(numTiles)]
Here, a random number, presumably from 1 to 25, is used to select a tile. But, it is likely that the same tile will be selected more that once, leading to the first value written to gameArray[i][1].y being overwritten when j is larger. I don't know exactly what functionality you desire here, but one solution is to build an array of indices, and to randomly select an index when selecting a tile, removing the index from the list so that it can not be selected again.
Here is an example of how this might be implemented. I have included some dummy initializations so that the code runs and displays results:
-- Dummy initializations
tileArray = {}
for i = 1, 25 do
tileArray[i] = {}
end
gameArray = {}
gridSize = {}
-- Initialize gridSize
gridSize.x = 5
gridSize.y = 5
-- List of available tile indices
indices = {}
for i = 1, 25 do
indices[i] = i
end
-- Create tilemap 5x5 array
for i = 1, gridSize.x do
gameArray[i] = {}
for j = 1, gridSize.y do
k = math.random(#indices)
index = indices[k]
table.remove(indices, k)
gameArray[i][j] = tileArray[index]
gameArray[i][j].x = (i * 100)
gameArray[i][j].y = (j * 100)
end
end
-- Display results
for i = 1, gridSize.x do
for j = 1, gridSize.y do
fmt = string.format("[%d][%d].x = %d, [%d][%d].y = %d\n",
i, j, gameArray[i][j].x, i, j, gameArray[i][j].y)
io.write(fmt)
end
end
Program output:
[1][1].x = 100, [1][1].y = 100
[1][2].x = 100, [1][2].y = 200
[1][3].x = 100, [1][3].y = 300
[1][4].x = 100, [1][4].y = 400
[1][5].x = 100, [1][5].y = 500
[2][1].x = 200, [2][1].y = 100
[2][2].x = 200, [2][2].y = 200
[2][3].x = 200, [2][3].y = 300
[2][4].x = 200, [2][4].y = 400
[2][5].x = 200, [2][5].y = 500
[3][1].x = 300, [3][1].y = 100
[3][2].x = 300, [3][2].y = 200
[3][3].x = 300, [3][3].y = 300
[3][4].x = 300, [3][4].y = 400
[3][5].x = 300, [3][5].y = 500
[4][1].x = 400, [4][1].y = 100
[4][2].x = 400, [4][2].y = 200
[4][3].x = 400, [4][3].y = 300
[4][4].x = 400, [4][4].y = 400
[4][5].x = 400, [4][5].y = 500
[5][1].x = 500, [5][1].y = 100
[5][2].x = 500, [5][2].y = 200
[5][3].x = 500, [5][3].y = 300
[5][4].x = 500, [5][4].y = 400
[5][5].x = 500, [5][5].y = 500
UPDATE
Given some more information about the goals of the OP code, it became apparent that you need to be able to use tiles from tileArray more than once. The problem is that by assigning an element from tileArray to gameArray[i][j], and then modifying gameArray[i][j], you are also modifying the original tile element.
The solution is to assign a copy of the tile element to gameArray[i][j]. Lua does not come with a function to copy tables, but you can look at this link to read about ways to copy tables. For a simple table requiring only a shallow copy, the page linked provides a function called shallowcopy(). Here is a modification of the above code that uses shallowcopy():
function shallowcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
-- Dummy initializations
numTiles = 5
tileArray = {}
for i = 1, numTiles do
tileArray[i] = {}
tileArray[i].tile_type = i
end
gameArray = {}
gridSize = {}
-- Initialize gridSize
gridSize.x = 5
gridSize.y = 5
-- Create tilemap 5x5 array
for i = 1, gridSize.x do
gameArray[i] = {}
for j = 1, gridSize.y do
gameArray[i][j] = shallowcopy(tileArray[math.random(numTiles)])
gameArray[i][j].x = (i * 100)
gameArray[i][j].y = (j * 100)
end
end
-- Display results
for i = 1, gridSize.x do
for j = 1, gridSize.y do
fmt = string.format("[%d][%d].x = %d, [%d][%d].y = %d : type %d\n",
i, j, gameArray[i][j].x, i, j, gameArray[i][j].y,
gameArray[i][j].tile_type)
io.write(fmt)
end
end
Program output:
[1][1].x = 100, [1][1].y = 100 : type 1
[1][2].x = 100, [1][2].y = 200 : type 1
[1][3].x = 100, [1][3].y = 300 : type 5
[1][4].x = 100, [1][4].y = 400 : type 2
[1][5].x = 100, [1][5].y = 500 : type 3
[2][1].x = 200, [2][1].y = 100 : type 5
[2][2].x = 200, [2][2].y = 200 : type 4
[2][3].x = 200, [2][3].y = 300 : type 2
[2][4].x = 200, [2][4].y = 400 : type 4
[2][5].x = 200, [2][5].y = 500 : type 3
[3][1].x = 300, [3][1].y = 100 : type 3
[3][2].x = 300, [3][2].y = 200 : type 5
[3][3].x = 300, [3][3].y = 300 : type 2
[3][4].x = 300, [3][4].y = 400 : type 4
[3][5].x = 300, [3][5].y = 500 : type 3
[4][1].x = 400, [4][1].y = 100 : type 4
[4][2].x = 400, [4][2].y = 200 : type 3
[4][3].x = 400, [4][3].y = 300 : type 5
[4][4].x = 400, [4][4].y = 400 : type 2
[4][5].x = 400, [4][5].y = 500 : type 2
[5][1].x = 500, [5][1].y = 100 : type 5
[5][2].x = 500, [5][2].y = 200 : type 5
[5][3].x = 500, [5][3].y = 300 : type 1
[5][4].x = 500, [5][4].y = 400 : type 5
[5][5].x = 500, [5][5].y = 500 : type 3
While the above answer written by David Bowling works and is beautiful code, it does not fix the original problem as the duplication of tiles is prevented as part of the fix.
The original problem was fixed by using a shallow copy function for the table. Which was borrowed from the following site:
http://lua-users.org/wiki/CopyTable
Changing the line
gameArray[i][j] = tileArray[math.random(numTiles)]
to
gameArray[i][j] = shallowcopy(tileArray[math.random(numTiles)])
Adding this is as a second answer for anyone that has a similar problem
Related
Storing and Accessing variable/values in amibroker afl code
I am inputting few values with Param functions. selecting timeframe Assigning period to the selected timeframe. Now if i want to store the timeframe and corresponding period to a array and later in the code if to retrieve it, how do i do it in amibroker AFL? say like storing data similar to below at start of program setting period[in3minutes] = 10; setting period[in5minutes] = 20; setting period[in10minutes] = 30; and at end the getting assigned data period1 = period[in3minutes]; period2 = period[in5minutes]; period3 = period[in10minutes]; Here is the sample code of setting the data with Param. swing_tf = ParamList ("Custom TimeFrames0 (default is 15min)", "in1Minute|in3Minute|in5Minute|in15Minute|in25Minute|in30Minute|in45Minute|inHourly|in75Minute|in90Minute|inDaily|inWeekly|inMonthly", 3); swing_period = Param ("Custom TimeFrames0 Periods", 20, 1, 200, 1); swing_tf1 = ParamList ("Custom TimeFrames1 (default is 30min)", "in1Minute|in3Minute|in5Minute|in15Minute|in25Minute|in30Minute|in45Minute|inHourly|in75Minute|in90Minute|inDaily|inWeekly|inMonthly", 5); swing_period1 = Param ("Custom TimeFrames1 Periods", 20, 1, 200, 1); swing_tf2 = ParamList ("Custom TimeFrames2 (default is hourly)", "in1Minute|in3Minute|in5Minute|in15Minute|in25Minute|in30Minute|in45Minute|inHourly|in75Minute|in90Minute|inDaily|inWeekly|inMonthly", 7); swing_period2 = Param ("Custom TimeFrames2 Periods", 20, 1, 200, 1); swing_tf3 = ParamList ("Custom TimeFrames3 (default is 90min)", "in1Minute|in3Minute|in5Minute|in15Minute|in25Minute|in30Minute|in45Minute|inHourly|in75Minute|in90Minute|inDaily|inWeekly|inMonthly", 9); swing_period3 = Param ("Custom TimeFrames3 Periods", 20, 1, 200, 1); Thanks in advance for your time in helping me out with this query.
Try a matrix, m = Matrix(1, 4, Null); m[0][0] = in1Minute; // 1 Minute m[0][1] = in1Minute * 3; // 3 Minute m[0][2] = in5Minute; // 5 Minute m[0][3] = in15Minute; // 15 Minute p = [0][2] // in5Minute It can be initialized easier if you are just looking for a set of constants. m = MxFromString("{{10,20,30,40}}");
Input file for a Fortran program, containing "&PROBIN"
I have the following code (it's an input file for a Fortran code from some link): &PROBIN model_file = "model_file" drdxfac = 5 max_levs = 1 n_cellx = 106 n_celly = 106 n_cellz = 106 max_grid_size = 32 anelastic_cutoff = 1.e3 base_cutoff_density = 1.e3 sponge_center_density = 3.d6 sponge_start_factor = 3.333d0 sponge_kappa = 10.0d0 max_mg_bottom_nlevels = 3 mg_bottom_solver = 4 hg_bottom_solver = 4 spherical_in = 1 dm_in = 3 do_sponge = .true. prob_hi_x = 2.e10 prob_hi_y = 2.e10 prob_hi_z = 2.e10 max_step = 100 init_iter = 1 stop_time = 30000. plot_int = 10 plot_deltat = 10.0d0 chk_int = 100 cflfac = 0.7d0 init_shrink = 0.1d0 max_dt_growth = 1.1d0 use_soundspeed_firstdt = T use_divu_firstdt = T bcx_lo = 12 bcx_hi = 12 bcy_lo = 12 bcy_hi = 12 bcz_lo = 12 bcz_hi = 12 verbose = 1 mg_verbose = 1 cg_verbose = 1 do_initial_projection = T init_divu_iter = 3 drive_initial_convection = T stop_initial_convection = 20 do_burning = F velpert_amplitude = 1.d6 velpert_radius = 2.d7 velpert_scale = 1.d7 velpert_steep = 1.d5 enthalpy_pred_type = 1 evolve_base_state = F dpdt_factor = 0.0d0 use_tfromp = T single_prec_plotfiles = T use_eos_coulomb = T plot_trac = F / My question is: what is &PROBIN? where can I find more information on it?
Such an input file would be typically read using namelist formatting. Details can be found using this term. One example of use is given in this answer to a question about input. In summary, the &PROBIN says that following (up to a terminating /) is a set of pairs for variables and values. These correspond to the namelist probin. In the source file we would find a namelist statement: namelist /probin/ list, of, variables with corresponding input statement read(unit, NML=probin) where the unit unit is connected to that input file. Of course, it's entirely possible that the file is an input file processed in the "usual" way. In this case &PROBIN has no special significance. The &PROBIN is necessary to support namelist formatting, but not unique to it.
Biopython for Loop IndexError
I get "IndexError: list is out of range" when I input this code. Also, the retmax is set at 614 because that's the total number of results when I make the request. Is there a way to make the retmode equal to the number of results using a variable that changes depending on the search results? #!/usr/bin/env python from Bio import Entrez Entrez.email = "something#gmail.com" handle1 = Entrez.esearch(db = "nucleotide", term = "dengue full genome", retmax = 614) record = Entrez.read(handle1) IdNums = [int(i) for i in record['IdList']] while i >= 0 and i <= len(IdNums): handle2 = Entrez.esearch(db = "nucleotide", id = IdNums[i], type = "gb", retmode = "text") record = Entrez.read(handle2) print(record) i += 1
Rather than using a while loop, you can use a for loop... from Bio import Entrez Entrez.email = 'youremailaddress' handle1 = Entrez.esearch(db = 'nucleotide', term = 'dengue full genome', retmax = 614) record = Entrez.read(handle1) IdNums = [int(i) for i in record['IdList']] for i in IdNums: print(i) handle2 = Entrez.esearch(db = 'nucleotide', term = 'dengue full genome', id = i, rettype = 'gb', retmode = 'text') record = Entrez.read(handle2) print(record) I ran it on my computer and it seems to work. The for loop solved the out of bounds, and adding the term to handle2 solved the calling error.
Corona show text from database in newScrollView
Im trying to pull some data from SQLite database to the Corona newScollView. I managed to get data from the database in a tableView, so I thought the code should almost be the same for the newScrollView. It keeps saying the row is empty, but its not. Any help? Here is the code: function scene:create( event ) local sceneGroup = self.view local function scrollListener( event ) -- Get reference to the row group local row = event.row local options_metni = { parent = row, text = row.params.Metni, x = 0, y = 0, font = native.systemFont, fontSize = 16 } local metniObject = display.newText(options_metni) metniObject:setTextColor(0) metniObject.x = display.contentCenterX end --------------------- -- CREATE SCROLLVIEW --------------------- local scrollView = widget.newScrollView { left = 0, top = 0, width = display.contentWidth, height = display.contentHeight / 2, topPadding = 200, bottomPadding = 50, horiontalScrollDisabled = true, verticalScrollDisable = false, listener = scrollListener, } sceneGroup:insert(scrollView) --------------------- -- GET DATA FROM DB --------------------- for row in db:nrows("SELECT baslik FROM dua LIMIT 1") do if row.data == nil then print(" NO DATA FOUND ") end local rowParams = { duaID = row.dua_id, Metni = row.baslik, } end end
You need to insert an object into the scrollView, it doesn't work like the tableView. Try this where the display object is being created and the text is being set from row.baslik: for row in db:nrows("SELECT baslik FROM dua LIMIT 1") do local text = display.newText( tostring( row.baslik ), 0, 0, native.systemFont, 16 ) scrollView:insert( text ) end
Array subscript out of bouds in an IF statement
Below is a section for my code. The user inputs a value for Energy, if the value is on the array ARRDAT(1,x), then I want it to assign the related variables ARRDAT(2,x), ARRDAT(3,x), and ARRDAT(4,x). If the data is not on the array, I will interpolate (note: only values between two of my given points will be inputted). I am able to compile it with a warning warning 179 - Comparning floating point quantities for equality may give misleading results and as soon as I input any value, whether it's in the table or not I get error 11, array subscript(s) out of bounds The error occurs on the line IF (ARRDAT(1,x) == Energy) THEN I haven't been able to fix it. IMPLICIT NONE REAL :: Dose, Energy, Source, FeAtt, PbAtt, Resp, Distance, Mu, Thickness INTEGER :: x, y, upp, low CHARACTER(LEN=4) :: Material REAL, PARAMETER :: PI = 3.1415926 real, dimension(1:4,1:25) :: ARRDAT !Energy MeV ARRDAT(1,1) = 0.01 ARRDAT(1,2) = 0.015 ARRDAT(1,3) = 0.02 ARRDAT(1,4) = 0.03 ARRDAT(1,5) = 0.04 ARRDAT(1,6) = 0.05 ARRDAT(1,7) = 0.06 ARRDAT(1,8) = 0.08 ARRDAT(1,9) = 0.10 ARRDAT(1,10) = 0.15 ARRDAT(1,11) = 0.20 ARRDAT(1,12) = 0.30 ARRDAT(1,13) = 0.40 ARRDAT(1,14) = 0.50 ARRDAT(1,15) = 0.60 ARRDAT(1,16) = 0.80 ARRDAT(1,17) = 1.0 ARRDAT(1,18) = 1.5 ARRDAT(1,19) = 2.0 ARRDAT(1,20) = 3.0 ARRDAT(1,21) = 4.0 ARRDAT(1,22) = 5.0 ARRDAT(1,23) = 6.0 ARRDAT(1,24) = 8.0 ARRDAT(1,25) = 10.0 !Response Function Sv*cm2 ARRDAT(2,1) = 0.062 ARRDAT(2,2) = 0.157 ARRDAT(2,3) = 0.238 ARRDAT(2,4) = 0.329 ARRDAT(2,5) = 0.365 ARRDAT(2,6) = 0.384 ARRDAT(2,7) = 0.400 ARRDAT(2,8) = 0.451 ARRDAT(2,9) = 0.533 ARRDAT(2,10) = 0.777 ARRDAT(2,11) = 1.03 ARRDAT(2,12) = 1.56 ARRDAT(2,13) = 2.06 ARRDAT(2,14) = 2.54 ARRDAT(2,15) = 2.99 ARRDAT(2,16) = 3.83 ARRDAT(2,17) = 4.60 ARRDAT(2,18) = 6.24 ARRDAT(2,19) = 7.66 ARRDAT(2,20) = 10.2 ARRDAT(2,21) = 12.5 ARRDAT(2,22) = 14.7 ARRDAT(2,23) = 16.7 ARRDAT(2,24) = 20.8 ARRDAT(2,25) = 24.7 !mu/rho for iron cm2/g ARRDAT(3,1) = 169.4 ARRDAT(3,2) = 56.33 ARRDAT(3,3) = 25.16 ARRDAT(3,4) = 7.891 ARRDAT(3,5) = 3.450 ARRDAT(3,6) = 1.833 ARRDAT(3,7) = 1.113 ARRDAT(3,8) = 0.5391 ARRDAT(3,9) = 0.3340 ARRDAT(3,10) = 0.1786 ARRDAT(3,11) = 0.1357 ARRDAT(3,12) = 0.1051 ARRDAT(3,13) = 0.09131 ARRDAT(3,14) = 0.08241 ARRDAT(3,15) = 0.07583 ARRDAT(3,16) = 0.06631 ARRDAT(3,17) = 0.05951 ARRDAT(3,18) = 0.04863 ARRDAT(3,19) = 0.04254 ARRDAT(3,20) = 0.03616 ARRDAT(3,21) = 0.03309 ARRDAT(3,22) = 0.03144 ARRDAT(3,23) = 0.03056 ARRDAT(3,24) = 0.02991 ARRDAT(3,25) = 0.02994 !mu/rho for lead cm2/g ARRDAT(4,1) = 125.7 ARRDAT(4,2) = 108.3 ARRDAT(4,3) = 84.02 ARRDAT(4,4) = 28.94 ARRDAT(4,5) = 13.44 ARRDAT(4,6) = 7.386 ARRDAT(4,7) = 4.531 ARRDAT(4,8) = 2.112 ARRDAT(4,9) = 5.337 ARRDAT(4,10) = 1.910 ARRDAT(4,11) = 0.9359 ARRDAT(4,12) = 0.3732 ARRDAT(4,13) = 0.2148 ARRDAT(4,14) = 0.1499 ARRDAT(4,15) = 0.1167 ARRDAT(4,16) = 0.08408 ARRDAT(4,17) = 0.06803 ARRDAT(4,18) = 0.05087 ARRDAT(4,19) = 0.04530 ARRDAT(4,20) = 0.04200 ARRDAT(4,21) = 0.04178 ARRDAT(4,22) = 0.04260 ARRDAT(4,23) = 0.04382 ARRDAT(4,24) = 0.04670 ARRDAT(4,25) = 0.04969 WRITE(*,*) 'Please input the particle energy in MeV' READ(*,*) Energy x=0 DO x = 0, 25, 1 IF (ARRDAT(1,x) == Energy) THEN !if the data is already on our table ARRDAT(2,x) = Resp ARRDAT(3,x) = FeAtt ARRDAT(4,x) = PbAtt WRITE(*,*) 'CHECK 1' ELSE IF (ARRDAT(1,x) < Energy) THEN !if the data is between two points upp = x low = x - 1 Energy = ((ARRDAT(1,upp) + ARRDAT(1,low))/2) WRITE(*,*) Energy ELSE WRITE(*,*) 'Invalid Entry' END IF END DO
You declare your array to be 1-indexed with real, dimension(1:4,1:25) :: ARRDAT, but your DO loop begins with x = 0, so the first iteration of the loop looks for ARRDAT(1,0) == Energy, which is out of bounds. Start your DO loop with x = 1 and you should be fine. Side note: Fortran automatically indexes arrays beginning with 1, so you can declare your array as real, dimension(4,25) :: ARRDAT, and it will have the same effect. EDIT: As mentioned by #user5713492 in the comments, this code will still crash if the input Energy is greater than ARRDAT(1,1). You will either have to fix the lower bound of the linear interpolation or skip the interpolation entirely in the first iteration of the loop. For example: DO x = 1, 25 IF (ARRDAT(1,x) == Energy) THEN ! ... ELSE IF (ARRDAT(1,x) < Energy) THEN upp = x low = x - 1 IF (low < 1) low = 1 ! <-- make sure we don't go out of bounds on the array ! ... END IF END DO ... or ... DO x = 1, 25 IF (ARRDAT(1,x) == Energy) THEN ! ... ELSE IF (x > 1 .AND. ARRDAT(1,x) < Energy) THEN ! <-- don't interpolate for the first iteration ! ... END IF END DO Now, about that warning concerning comparison of floating point numbers for equality: please read this and try to avoid ==, >=, and <= operators when comparing reals.