Thread Tools Display Modes
06-10-14, 08:09 AM   #1
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Non wow-addon LUA help

I'm unsure if you are willing to help out as this isn't related to addon authorship, but I do trust this community's expertise when it comes to Lua coding. I am attempting to trial a large database of samples we have and the only language I kind of know is Lua.

We have 50,000 samples on 521 96 well plates. 520 of these 96 well plates are full. They are set up in 12 column, 8 row format. The 521st plate has 10 columns and 8 rows. I need to randomly select 400 of these samples, format them like so (123:A:10) with leading 0's on the first number for excel formatting. Lastly (and the place I'm having difficulty with) is ensuring there are no duplicates. I could just run the code until I don't get duplicates, but I would prefer not to as I'd have to submit my code to the journal publishing the results.

Lua Code:
  1. local plate, row, column, printout
  2.  
  3. local rntl = {} --row number to letter table
  4. local dct = {}  --duplicate check table
  5.  
  6. rntl[1] = 'A'
  7. rntl[2] = 'B'
  8. rntl[3] = 'C'
  9. rntl[4] = 'D'
  10. rntl[5] = 'E'
  11. rntl[6] = 'F'
  12. rntl[7] = 'G'
  13. rntl[8] = 'H'
  14.  
  15. local samplechoice = function(plate, column, row, rntl, dct, i)
  16.     plate = math.random(1,521)  --50,000 samples divided on 520, 96 well plates, with 1 plate only having 80 samples
  17.         if plate == 521 then    --Check to see if randomly got the one plate with only 80 samples
  18.             column = math.random(1,10)
  19.         else
  20.             column = math.random(1,12)
  21.         end
  22.        
  23.         if plate < 10 then      --Format to add double 0's for excel sorting purposes
  24.             plate = '00'..plate
  25.         elseif plate < 100 then --Format to add single 0's for excel sorting purposes
  26.             plate = '0'..plate
  27.         end
  28.        
  29.     row = math.random(1,8)
  30.     dct[i] = plate..':'..rntl[row]..':'..column     --format eg. 234:D:8
  31. end
  32.  
  33. for i = 1,400 do
  34.     samplechoice(plate, column, row, rntl, dct, i)
  35.         for j = 1, i-1 do                               --Second for loop that starts with dct[1] and goes until just before the current iteration checking for string matches
  36.             if dct[i] == dct[j] then                    --if it finds a string match, it needs to reiterate until it doesnt
  37.                 samplechoice(plate, column, row, rntl, dct, i)
  38.             end
  39.         end
  40.     print(dct[i])
  41. end

If this is deemed inappropriate for this forum, I understand.

I think my issue lies with my function definition and call.
  Reply With Quote
06-10-14, 09:11 AM   #2
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
I would do something like this. Don't know if it works. It's dry coded and I can't test it right now. :/

Lua Code:
  1. local samples = {}
  2.  
  3. local rntl = {} --row number to letter table
  4. rntl[1] = 'A'
  5. rntl[2] = 'B'
  6. rntl[3] = 'C'
  7. rntl[4] = 'D'
  8. rntl[5] = 'E'
  9. rntl[6] = 'F'
  10. rntl[7] = 'G'
  11. rntl[8] = 'H'
  12.  
  13.  
  14. local tPlate
  15. local tColumn
  16. local tRow 
  17.  
  18. while table.getn(samples) < 400 do
  19.     tPlate = math.random(1,521)
  20.     if plate == 521 then
  21.         tColumn = math.random(1, 10)
  22.         tRow = math.random(1, 8)
  23.     else
  24.         tColumn = math.random(1, 12)
  25.         tRow = math.random(1, 8)
  26.     end
  27.     if not samples(tPlate..":"..tColumn..":"..rntl[tRow]) then
  28.         sample(tPlate..":"..tColumn..":"..rntl[tRow]) = true
  29.     end
  30. end
  31.  
  32. for i, v in pairs(samples) do
  33.     print(i)
  34. end

Last edited by Duugu : 06-10-14 at 09:16 AM.
  Reply With Quote
06-10-14, 09:17 AM   #3
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Rather than separately pick random plates, columns, and rows, I'd just pick random samples (1-50,000) and then figure out the correct plate/column/row data for the selected sample:

Code:
local NUM_TRIALS = 400

local MAX_SAMPLES = 50000
local SAMPLES_PER_PLATE = 96
local COLUMNS_PER_ROW = 12

local samples = {}
local letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

-- Get random samples:
repeat
	local n = math.random(1, MAX_SAMPLES)
	if not samples[n] then
		samples[n] = true

		-- You should definitely double-check this math, as I'd be shocked if it's correct.
		local plate = math.ceil(n / SAMPLES_PER_PLATE)
		local row = math.ceil((n % SAMPLES_PER_PLATE) / COLUMNS_PER_ROW)
		local col = (n % SAMPLES_PER_PLATE) - (row * COLUMNS_PER_ROW)
		col = string.sub(letters, col, col)

		local text = string.format("%03f:%s:%s", plate, col, row)
		table.insert(samples, text)
	end
until #samples == NUM_TRIALS

-- Remove k/v pairs used for duplicate checking:
for k, v in pairs(samples) do
	if v == true then
		samples[k] = nil
	end
end

-- Do whatever with your list of samples here.
Definitely double-check the math where indicated. I just woke up, haven't had breakfast or coffee, and math isn't my strong suit anyway. The principle should be sound though.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
06-10-14, 09:41 AM   #4
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Not tested but:
Code:
local format, random = string.format, math.random
local index, samples, used = 1, { }, { }
while(index <= 400) do
	local plate = random(1, 521)
	local sample = format("%03u:%c:%u", plate, 64 + random(1, 8), random(1, plate ~= 521 and 12 or 10))
	if not used[sample] then
		index, samples[index], used[sample] = index + 1, sample, true
	end
end
  Reply With Quote
06-10-14, 10:27 AM   #5
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
I appreciate all of your responses. I was able to get all three to work to my needs.

As a learning opportunity, taking my base code, what did I do wrong with the function declaration/calls?

Additionally, are all of you ok with me submitting one of the following scripts to the journal publishing the paper? (they will not publish it, but I'm certain they would review it.)
  Reply With Quote
06-10-14, 11:05 AM   #6
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
I fixed my own mistake, it had to do with the for j = 1, i-1

simply changing it to j = 2, i-1 fixed it
  Reply With Quote
06-10-14, 11:07 AM   #7
Duugu
Premium Member
 
Duugu's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 851
Post

Originally Posted by sirann View Post
As a learning opportunity, taking my base code, what did I do wrong with the function declaration/calls?
The first thing that catches my eyes is that you're passing plate, column, row, rntl, and dct with your function call. That's not necessary as they are all global variables to you environment.
Code:
local samplechoice = function(i)
and
Code:
samplechoice(i)
would do the job.
And plate, row, and column are not even used outside of your function. So you could move
Code:
local plate, row, column
to your function.
Code:
local samplechoice = function(plate, column, row, rntl, dct, i)
   local plate, row, column
   plate = math.random(1,521) 
       if plate == 521 then    --Check to see if randomly got the one plate with only 80 samples
The second thing that comes to my mind is that your solution isn't a true recursive approach. You're just doing a second try if the first result is already in the list. What if the second result is in the list too?

Originally Posted by sirann View Post
Additionally, are all of you ok with me submitting one of the following scripts to the journal publishing the paper? (they will not publish it, but I'm certain they would review it.)
Sure
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Non wow-addon LUA help


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off