two dimensional array without dupes

I am trying to create an array with two dimensions where the row/col size is determined by user input, 6,9,12,15. They array can have no duplicates in either direction, no numbers in row duped and no numbers in cols duped.

the numbers are generated randomly with the upper bound dependent on the above mentioned user input.

Example:

1, 5, 3, 4, 2, 6

3, 4, 1, 2, 6, 5

4, 6, 2, 3, 5, 1

… etc

the included code does fine on the first row but working the next row and checking the column(s) against the prior rows eludes me. Can someone please assist?

--[[Array - 2 dimensions: &nbsp; &nbsp; goal, two dimensional array of flexible size (arrayBounds). Array to have random numbers of range &nbsp; &nbsp; in 1 - nBounds. Rows require no duplicate values and the columns no duplicate values: &nbsp; &nbsp; &nbsp; 1,3,6,2,5,4 &nbsp; &nbsp; &nbsp; 3,5,2,4,6,1 &nbsp; &nbsp; &nbsp; 5,4,1,6,3,2 &nbsp; &nbsp; &nbsp; ... etc. &nbsp; &nbsp; Issue: Can get the initial row but stumped getting the column/row duplicate validation. --]] -- initial array declaration array = {} local rSeed = math.randomseed(os.time()) local mR = math.random local checkRow = {} local checkCol = {} local usedRowList = {} local usedColList = {} local arrayBounds = 6 local arrayCheckMax = 21 local cValue = 0 local cNValue = 0 local notNew = true local buildArrayRow local buildArrayCol local buildArray local seedCell seedCell = function() &nbsp;&nbsp; &nbsp; local cellVal = mR(1,6) &nbsp;&nbsp; &nbsp; return cellVal end -- zero filled , this is a test for the creation of an array buildArray = function() &nbsp; -- build initial empty&nbsp; &nbsp;&nbsp; &nbsp; for a=1, arrayBounds do &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; array[a] = {} &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; for b=1, arrayBounds do &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = 0 &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; end &nbsp;&nbsp; &nbsp; return array &nbsp;&nbsp; end ---------------------------------------------------------------------- buildArrayRow = function(currArray, a, bLimit) &nbsp; local usedSum = 0 &nbsp; local i = 0 &nbsp; local inList = true &nbsp; local rowdupes = false &nbsp; local notNew = false &nbsp; local complete = false &nbsp; local dCnt = 0 &nbsp; print("buildArrayRow: incoming -a- value is "..a.." ") &nbsp;&nbsp; &nbsp; &nbsp; for b = 1, bLimit do &nbsp; &nbsp; &nbsp;-- build row data &nbsp; &nbsp; &nbsp; notNew = true &nbsp; &nbsp; &nbsp; cValue = seedCell() &nbsp; &nbsp; &nbsp; &nbsp; -- get random cell value limited by the arrayBounds &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; usedRowList[b] = cValue &nbsp; &nbsp; &nbsp; &nbsp;-- load used number&nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: cell value "..cValue.." used list value "..usedRowList[b].." b is "..b.." &nbsp;col a is "..a.." ") &nbsp; &nbsp; &nbsp; if b == 1 then &nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = cValue &nbsp; &nbsp; &nbsp; elseif b == arrayBounds then -- check to see if this is the last cell for the row,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- sum all prior values, subtract from max and assign result &nbsp; &nbsp; &nbsp; &nbsp; -- set exit condition on result assignment &nbsp; &nbsp; &nbsp; &nbsp; local usedSum = 0 &nbsp; &nbsp; &nbsp; &nbsp; for k = 1, b - 1, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; usedSum = usedSum + usedRowList[k] &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end for &nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = arrayCheckMax - usedSum &nbsp; &nbsp; &nbsp; &nbsp; notNew = false &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: b not 1 b is "..b.." a is "..a.." ") &nbsp; &nbsp; &nbsp; &nbsp; -- &nbsp; &nbsp; &nbsp; &nbsp; -- validation of new numbers for row &nbsp; &nbsp; &nbsp; &nbsp; -- &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: start pass "..b.." ==================================================") &nbsp; &nbsp; &nbsp; &nbsp; while notNew do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- loop until new value is attained &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; complete = false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dCnt = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while not complete do &nbsp; &nbsp; -- loop until value for cell is completely validated &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for j = 1, b - 1, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- is it already used? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: in usedList process: cValue is "..cValue.." usedList value "..usedRowList[j].." index is "..j.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if usedRowList[j] == cValue then -- value is already used &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: getting next value from seedCell(); used = cval") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cValue = seedCell() &nbsp; &nbsp; &nbsp; -- get new value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: next value from seedCell() is cValue "..cValue.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; complete = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elseif usedRowList[j] ~= cValue and j \< b then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dCnt = dCnt + 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: incrementing count value dCnt "..dCnt.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if dCnt == b then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = cValue &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; usedRowList[b] = cValue &nbsp; &nbsp; &nbsp; &nbsp;-- load to used list &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; notNew = false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; complete = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end dCnt check &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end usedList check &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; -- for loop end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- completed while end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end notNew loop &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayRow: end pass "..b.." ==================================================") &nbsp; &nbsp; &nbsp; end -- end b check val &nbsp; &nbsp; end -- end b loop &nbsp;&nbsp; &nbsp; if a == 1 then &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for k = 1, a , 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for f = 1, 6, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: check array &nbsp;"..array[a][f].." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- end inner for &nbsp; &nbsp; &nbsp; &nbsp; end -- end outer for &nbsp; else &nbsp; &nbsp; &nbsp; for k = 1, a -1 , 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for f = 1, 6, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: check array &nbsp;"..array[a][f].." ") &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;--end inner for &nbsp; &nbsp; &nbsp; end -- end outer for &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; end -- end if/else &nbsp;&nbsp; &nbsp; return(currArray) &nbsp; end -- end buildArrayRow ---------------------------------------------------------------------- buildArrayCol = function(currArray) &nbsp; local usedSum = 0 &nbsp; local i = 0 &nbsp; local inList = true &nbsp; local rowdupes = false &nbsp; local notNew = false &nbsp; local complete = false &nbsp; local dCnt = 0 &nbsp; local b = 0 &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; for a = 1, arrayBounds do &nbsp; &nbsp; &nbsp; &nbsp;-- populate array &nbsp; &nbsp; b = 1 &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; notNew = true &nbsp; &nbsp; cValue = seedCell() &nbsp; &nbsp; &nbsp; &nbsp; -- get random cell value limited by the arrayBounds &nbsp;&nbsp; &nbsp; &nbsp; usedColList[a] = cValue &nbsp; &nbsp; &nbsp; &nbsp;-- load to used number&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; print("buildArrayCol: a is "..a.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; if a == 1 then &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; buildArrayRow(currArray, a, arrayBounds) &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; elseif a == arrayBounds then -- check to see if this is the last cell for the row,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- sum all prior values, subtract from max and assign result &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- set exit condition on result assignment &nbsp; &nbsp; &nbsp; local usedSum = 0 &nbsp; &nbsp; &nbsp; for k = 1, a - 1, 1 do &nbsp; &nbsp; &nbsp; &nbsp; usedSum = usedSum + usedColList[k] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end for &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = arrayCheckMax - usedSum &nbsp; &nbsp; &nbsp; notNew = false &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; print("buildArrayCol: a not 1 a is "..a.." ") &nbsp; &nbsp; &nbsp; &nbsp; -- &nbsp; &nbsp; &nbsp; &nbsp; -- validation of new numbers for row &nbsp; &nbsp; &nbsp; &nbsp; -- &nbsp; &nbsp; &nbsp; print("buildArrayCol: start a pass "..a.." ==================================================") &nbsp; &nbsp; &nbsp; while notNew do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- loop until new value is attained &nbsp; &nbsp; &nbsp; &nbsp; complete = false &nbsp; &nbsp; &nbsp; &nbsp; dCnt = 0 &nbsp; &nbsp; &nbsp; &nbsp; while not complete do &nbsp; &nbsp; -- loop until value for cell is completely validated &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for j = 1, a, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- is it already used? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: in usedList process: cValue is "..cValue.." usedColList value "..usedColList[j].." index is "..j.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if usedColList[j] == cValue then -- value is already used &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: getting next value from seedCell(); used = cval") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cValue = seedCell() &nbsp; &nbsp; &nbsp; -- get new value &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: next value from seedCell() is cValue "..cValue.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; complete = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elseif usedColList[j] ~= cValue and j \< a then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dCnt = dCnt + 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: incrementing count value dCnt "..dCnt.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if dCnt == a then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: array is &nbsp;a"..a.." b "..b.." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; array[a][b] = cValue &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; usedColList[a] = cValue &nbsp; &nbsp; &nbsp; &nbsp;-- load to used list &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buildArrayRow(array[a][b],a ,b) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; notNew = false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; complete = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end dCnt check &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp;-- end usedList check &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; -- for j loop end &nbsp; &nbsp; &nbsp; &nbsp; end -- completed while end &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: out of completed loop") &nbsp; &nbsp; &nbsp; end &nbsp;-- end notNew loop &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: end pass "..a.." ==================================================") &nbsp; &nbsp; end -- end a check val &nbsp;&nbsp; &nbsp; &nbsp; if a == 1 then &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for k = 1, a , 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for f = 1, 6, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: check array &nbsp; a = 1 "..array[a][f].." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- end inner for &nbsp; &nbsp; &nbsp; &nbsp; end -- end outer for &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; for k = 1, a -1 , 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for f = 1, 6, 1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print("buildArrayCol: check array &nbsp;a = "..a.." "..array[a][f].." ") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end -- end inner for &nbsp; &nbsp; &nbsp; &nbsp; end -- end outer for &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; end -- end if/else &nbsp; end -- end a for loop &nbsp; return currArray &nbsp;&nbsp; end &nbsp;-- end buildArrayCol ---------------------------------------------------------------------- --&nbsp; -- MAIN -- buildArray() print("MAIN: back from buildArray") &nbsp; for i, k in pairs(array) do -- validate empty array &nbsp; print("MAIN: row ",i," cells ", k[1], k[2], k[3], k[4], k[5], k[6]) &nbsp; end -- end validation empty array as test buildArrayCol(array) &nbsp; for i, k in pairs(array) do -- validate completed array &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; print("row ",i," cells ", k[1], k[2], k[3], k[4], k[5], k[6]) &nbsp; end &nbsp; &nbsp;-- end validation empty array as test -- end main

A multi-dimensional array can be represented in two ways:
 

  1. A flat table where positions are calculated from row-col.  OK for 2-dimensional array, but a challenge for higher dimension arrays.
     

  2. A table of tables (…)
     
    For example (using technique 2) we can make a two-dimensional array as follows

    – 4 column x 3 row --> row-major array (rows are tables) local cols = 4 local rows = 3 – Create and initialize entries to 0 local myArray = {} for row = 1, rows do local curRow = {} myArray[row] = curRow for col = 1, cols do curRow[col] = 0 end end

With these functions we can get and set the cells in the array

local function get( array, row, col ) return array[row][col] end local function set( array, row, col, value) array[row][col] = value return array[row][col] end local function dump( array ) local rows = #array local cols = #array[1] for row = 1, rows do local curRow = "" for col = 1, cols do curRow = string.format("%s %3d", curRow, array[row][col] ) end print( curRow ) end end 

Now test it:

dump( myArray ) --[[prints something like this to console: 13:24:03.069 0 0 0 0 13:24:03.069 0 0 0 0 13:24:03.069 0 0 0 0 --]]

Now set the ‘identify matrix’ and dump it:

-- Set the identity matrix set( myArray, 1, 1, 1 ) set( myArray, 1, 4, 1 ) set( myArray, 2, 2, 1 ) set( myArray, 3, 3, 1 ) dump( myArray ) --[[prints something like this to the console: 13:25:53.071 1 0 0 1 13:25:53.071 0 1 0 0 13:25:53.071 0 0 1 0 --]]

Technically this is a jagged array or “array of array”.  A true two-dimensional array would be array[row,col] not array[row][col].

I’m not sure if Lua supports true multi-dimensional arrays?

Ok, roaming gamer. Where you are setting the identity marix, can that be substituted by the random number process?

Lua does not support true two-dimensional arrays. You have to use a table of tables or a computed offset in a single table.

Rob

ok I will revisit the code and approach it from a table of tables process.

based on Ed’s code to initialise with a random number (in this case between 1 and 10) just use

set( myArray, 1, 1,&nbsp;math.random(1,10)&nbsp;)

A multi-dimensional array can be represented in two ways:
 

  1. A flat table where positions are calculated from row-col.  OK for 2-dimensional array, but a challenge for higher dimension arrays.
     

  2. A table of tables (…)
     
    For example (using technique 2) we can make a two-dimensional array as follows

    – 4 column x 3 row --> row-major array (rows are tables) local cols = 4 local rows = 3 – Create and initialize entries to 0 local myArray = {} for row = 1, rows do local curRow = {} myArray[row] = curRow for col = 1, cols do curRow[col] = 0 end end

With these functions we can get and set the cells in the array

local function get( array, row, col ) return array[row][col] end local function set( array, row, col, value) array[row][col] = value return array[row][col] end local function dump( array ) local rows = #array local cols = #array[1] for row = 1, rows do local curRow = "" for col = 1, cols do curRow = string.format("%s %3d", curRow, array[row][col] ) end print( curRow ) end end 

Now test it:

dump( myArray ) --[[prints something like this to console: 13:24:03.069 0 0 0 0 13:24:03.069 0 0 0 0 13:24:03.069 0 0 0 0 --]]

Now set the ‘identify matrix’ and dump it:

-- Set the identity matrix set( myArray, 1, 1, 1 ) set( myArray, 1, 4, 1 ) set( myArray, 2, 2, 1 ) set( myArray, 3, 3, 1 ) dump( myArray ) --[[prints something like this to the console: 13:25:53.071 1 0 0 1 13:25:53.071 0 1 0 0 13:25:53.071 0 0 1 0 --]]

Technically this is a jagged array or “array of array”.  A true two-dimensional array would be array[row,col] not array[row][col].

I’m not sure if Lua supports true multi-dimensional arrays?

Ok, roaming gamer. Where you are setting the identity marix, can that be substituted by the random number process?

Lua does not support true two-dimensional arrays. You have to use a table of tables or a computed offset in a single table.

Rob

ok I will revisit the code and approach it from a table of tables process.

based on Ed’s code to initialise with a random number (in this case between 1 and 10) just use

set( myArray, 1, 1,&nbsp;math.random(1,10)&nbsp;)