Help With My Random String

I’m trying to get a random string of numbers and letters and want the string to have a length of 7 characters, so basically a license plate.

Here is my extremely flawed code… as you can see with my code there will never be a number in between two letters and vice versa. I would really appreciate some help with this!

My code
[lua]
function RandomLicensePlate()
IntTable = {}
CharTable = {}

local alphabet = "abcdefghijklmnopqrstuvwxyz"

local numint = math.random(1,6)
local numchar = (7 - numint)

for i = 1, numint do
	int = math.random(1,9)
		
	table.insert(IntTable, int)
end

for i = 1 , numchar do
	char = string.GetChar(alphabet, math.random(1,26))
		
	table.insert(CharTable, char)
end
	
table.Add(IntTable, CharTable)

local license = table.concat(IntTable)
	
print(license)

end
[/lua]

Make it a table instead.


local allowedChars = {
"a",
"b",
"y",
"z",
"1",
"9",
}

char = table.Random(allowdChars)

What’s your problem exactly, do you simply want numbers to be mixed with letters? Because if so, you can simply add numerical digits to your alphabet, like this:

[lua]function RandomLicensePlate()
local alphabet = “abcdefghijklmnopqrstuvwxyz0123456789”

local CharTable = {}
local numchar = 7

for i = 1, numchar do
	local char = string.GetChar(alphabet, math.random(1, #alphabet))
		
	table.insert(CharTable, char)
end

local license = table.concat(IntTable)
	
print(license)

end[/lua]

#alphabet gives you the length of the alphabet string.

However, since there are more letters than numbers, letters will have a higher chance to apear, so if you want letters and numbers to appear at the same frequency, you can do this instead:

[lua]
function RandomLicensePlate()

local alphabet = "abcdefghijklmnopqrstuvwxyz"

local CharTable = {}
local numchar = 7

for i = 1, numchar do
	local char
	if math.random() < 0.5 then
		char = string.GetChar(alphabet, math.random(1,26))
	else
		char = tostring(math.random(0, 9))
	end
		
	table.insert(CharTable, char)
end

local license = table.concat(IntTable)
	
print(license)

end
[/lua]

math.random() with no parameters returns a floating point value between 0 and 1, so using this code, you’ll have a 50% chance to get a letter and a 50% chance to get a number.

Thanks a lot Kilburn, I went with your second solution.

You’re doing it wrong.

It’s simpler to do this :

[lua]
local function RandomString( len )

str = "";

for i = 0, len do 

	str = str .. string.char( math.random(97,122) );

end

return str;

end
[/lua]

[editline]26th June 2013[/editline]

Number range is from 48 to 57, lowercase is from 97 to 122 uppercase is from 65 to 90.

I think ‘wrong’ is the wrong word. Yeah, your way is more compact but if he doesn’t understand it it isn’t beneficial to use it in a project.

This is indeed more compact but I didn’t want to confuse him any further with concepts he might not understand. Plus, I remember reading somewhere that building a table and then calling table.concat is actually a lot faster than doing a lot of string concatenations, since the latter creates a copy of the string every time you perform a concatenation.

I tried oubliette’s method but with concatenating the random number and letter in one string.

[lua]
function RandomLicensePlate()

local numchar = 7
local str = ""

for i = 1, numchar do 
	str = str ..GetNextChar()
end

return str

end

function GetNextChar()
if math.random() > .5 then
return string.char(math.random(65,90))
else
return math.random(0,9)
end
end
[/lua]

It works, but I’m not sure it that’s the appropriate way to make it work

At the same time you were promoting what he was doing, which wasn’t the best.

Someone had to point out there was a more efficient method.

Also you’re right there, but only by a bit :



concat avg : 0.00013802081070025
".." op avg : 0.00024359414877836


That was the time it took to concatenate 32^2 letters, averaged 1000 times.

Yeah my bad, “wrong” was the wrong word.

Do this :

[lua]
function genPlate( size )

local str = "";

for i = 0, size do 

	local range = ( math.random() > 0.5  and {65, 90} or {48, 57} );
	str = str .. string.char( math.random( range[ 1 ], range[ 2 ] ) );

end

return str;

end
[/lua]

Output :

http://puu.sh/3oUX4.jpg

It’s 75% faster, I wouldn’t call that “a bit”. :v: But at this scale it’s true that it doesn’t really matter, I almost never use table.concat myself.

This however seems a bit forced. You could at least explain to him how this works, especially the “A and B or C” part. Either way this looks quite inefficient to me since you’re creating one new table for each character.
Also there are going to be size+1 characters since you’re starting from 0. This is Lua, not C. Get rid of the semicolons as well while you’re at it, they have absolutely no reason to be there.

If I really wanted to make the shortest and most optimized function ever to perform this task, I’d do something like this:

[lua]local LicensePlateRanges = {{65, 90}, {48, 57}}
local LicensePlateResult = {}

function RandomLicensePlate()
for i=1, 7 do
LicensePlateResult* = string.char(math.random(unpack(LicensePlateRanges[math.random(2)])))
end

return table.concat(LicensePlateResult)

end[/lua]

Tables are allocated only once outside the function, so the only memory allocation done inside of it is for the returned string. Since the generated license plates are always going to be 7 characters long, there is no need to recreate the LicensePlateResult table ever. You also proved that table.concat is faster.

Either way Gaming_Unlim, just go with whichever solution you prefer. At this scale, you shouldn’t really worry about performance (if you had to write something that required optimal performance you wouldn’t even be coding in Lua in the first place).
Just a few notes though, try to avoid using functions from the table library which start with an uppercase letter, like table.Add. Those were written in Lua and aren’t really part of the original table library, therefore they are usually quite unoptimized. Only use them when absolutely necessary.

Also if you were wondering, “(A and B) or C” is a little trick known by a few Lua programmers which exploits the way the “and” and “or” operators work. It’s basically a selection which results in B if A is true, and C otherwise. A similar trick you might encounter as well is “A or B”, which results in A if A is neither nil nor false, and B otherwise. I tend to avoid using the first one though, mostly because of how confusing it looks and because it doesn’t really have any advantage.

I actually was wondering what that was when I saw that, thank you for the explanation. Also thanks to everyone who posted…I got more than enough information from this thread.