Counting up to a number and hitting all the numbers, but in random order?

Say I have a number “85”. I want to count out all the numbers (so no skipping any numbers), but in random order. How would one go into doing that?

    local maxNumber = 85;
    local TitleBox.Text = "";

You could create an array with values from 0 to your max number and then choose a random value from that list and remove it.

1 Like
local maxNumber = 85
local numbers = {}

for i=1, maxNumber do
	numbers[i] = i
end

for i=1, maxNumber do
	local num
	
	repeat num = math.random(1, maxNumber) until numbers[num]
	print(num)
	numbers[num] = nil
end
2 Likes

Wouldn’t this be fairly inefficient? You’re essentially looping through random indices of an array until you index an entry which has a non-nil value.

endNum = 85
numbers = {}

for i = 1, endNum do
	table.insert(numbers, i)
end

for i = 1, endNum do
	local num = math.random(1, #numbers)
	print(num)
	table.remove(numbers, table.find(numbers, num))
end

This saves a lot on unnecessary operations.

1 Like

You can go even further by ditching table.find.

endNum = 9
numbers = {}

for i = 1, endNum do
	table.insert(numbers, i)
end

for i = 1, endNum do
	local num = table.remove(numbers, math.random(1, #numbers))
	print(num)
end
endNum = 9
numbers = {}

for i = 1, endNum do
	table.insert(numbers, i)
end

for i = 1, endNum do
	print(table.remove(numbers, math.random(1, #numbers)))
end
1 Like

You can go even further by recognizing that table.remove becomes more inefficient as the maximum number / upper bound of the problem increases. We can instead assign the chosen index via math.random in the range [currentIndex, maxVal] with the value associated with the index of the current iteration in the for loop. This ensures that in the next iteration, we choose between a range of indices [currentIndex+1, maxVal], excluding already chosen numbers:

local maxVal = 100000 -- change upper bound here

local arr = table.create(maxVal, 0) -- preallocated array

for i = 1, maxVal do
	arr[i] = i -- populate array with the desired numbers
end

for currentIndex = 1, maxVal do
	local chosenIndex = math.random(currentIndex, maxVal) 
	
	local num = arr[chosenIndex] -- your number
	print(num)
	
	arr[chosenIndex] = arr[currentIndex]
end

This is just an extra optimization, and for small values this isn’t too impactful.

1 Like