Mixing Up Numbers

Hey,

This might seem like a really basic question with a simple answer. I have looked everywhere for this and I feel dumb.

How would I convert an ordered number into a mixed number? For example: “1234” turns into “2431”

It probably is really something simple that I haven’t looked at :joy::joy::roll_eyes::roll_eyes:

math.random I guess but maybe it is :scream:

Convert the number to a string, randomly recreate a string using the characters given, and coerce it back to a number.

If that’s a bit confusing, I could write a version of the function? It’s not too complicated.

If that’s ok with you? That would be a massive help :slight_smile: :slight_smile:

-- Prime the pseudo-random number generator with a unique enough seed.
math.randomseed(os.time());

-- Take an array-like table and shuffle it.
local function shuffleArray(array)
	local shuffledArray = {};
	for _, element in ipairs(array) do
		local position = math.random(1, #shuffledArray + 1);
		table.insert(shuffledArray, position, element);
	end
	return shuffledArray;
end

-- Convert a string to an array-like table where every element is a single
-- character.
local function stringToCharacterArray(str)
	local characters = {};
	
	for character in str:gmatch(".") do
		table.insert(characters, character);
	end
	
	return characters;
end

-- Scramble an integer, converting it to a number where every character in
-- the original number is in a random position.
local function scrambleInteger(integer)
	local numberAsString = tostring(integer);
	local characters = stringToCharacterArray(numberAsString);
	local shuffledCharacters = shuffleArray(characters);
	local shuffledNumberAsString = table.concat(shuffledCharacters, "");
	local shuffledNumber = tonumber(shuffledNumberAsString);
	return shuffledNumber;
end

-- Run a few tests
print(scrambleInteger(1234))
print(scrambleInteger(1234))
print(scrambleInteger(1234))
print(scrambleInteger(1234))
print(scrambleInteger(1234))

When just running this script in an empty baseplate, the tests worked! Here was the output:

1432
3421
2314
2143
4132

Hope this helps!

1 Like

Thank you!!

30char30char30char

This seems pretty complicated for such a simple thing. While your solution works fine, I’m sure, here’s a quicker and (in my opinion) cleaner version contained in one function for anyone curious:

local function shuffleNumber(int)
	local digits = {}
	for letter in tostring(int):gmatch(".") do
		table.insert(digits, math.random(#digits + 1), letter)
	end
	return tonumber(table.concat(digits, ""))
end

Basically, you can just randomly pick where to insert rather than inserting each letter and then shuffling the list.

3 Likes

It certainly is a less verbose function! I like it a lot.

I tend to make snippets like this though, where I’m unsure of the developer’s familiarity with certain semantics, to make code as verbose as possible such that even if they don’t understand the fine-grained details (like what gmatch does, et cetera), they can understand the gist.

I’m also used to languages like Ruby, Swift, or ECMAScript where the standard library typically has this functionality in it as opposed to the lightweight library we have with Lua, so I broke it up in a more-than-needed modular way.

1 Like