How to get all possible variants of 1 word?

I want to get all possible variants of 1 word.
Example:
Word = “Hello”
Fillers = {“#”, “$”}
Varient 1: “#ello”,
Varient 2: “#$llo”,
Varient 3: “h$llo”,

Here is my current attempt:

local word = "Hello"
local keywords = {
	#
	"$",
}
local variants = {}

for i=1, word:len() do
	for _,v in pairs(keywords) do
		local newString = word
		newString = string.sub(word, 1, i) .. v .. string.sub(word, i+1)
		table.insert(variants, newString)
	end
end

print(table.concat(variants, " "))

It works but I want to get something like this too #el$o

1 Like

One thing you should note is that there are a lot of combinations. It can get quite big: hello = (x+1)^n combinations
Imagine x + 1 being the number of keywords, plus 1 for the default state of a letter, and n being the length of the string.

If you had 2 keywords, and a word with 5 letters, that would be 3^5, which is 243.

Sorry, I’m pressed for time so I can’t give you any code rn. What the end goal should be is to get every possible combination of every character, with every possible combination of every other character.

A quick idea would be to loop through each keyword, loop through each character, set that character to the keyword (or default), then somehow change every other character to every other keyword, all in the context of that single keyword and character.

I can’t tell exactly what you’re looking for since you haven’t adequately described the rules of your character replacement. My interpretation is a program that counts up in base N, where N is the number of “keywords” plus 1, from 0 to (N^word length) - 1, and each 0 in the number represents an un-changed character and each non-0 represents the corresponding keyword.

local function variants(word, filler)
	if #filler == 0 then return {word} end
	local counter = {}
	for i = 1, #word do counter[i] = 0 end
	local words = {word}
	for i = 1, (#filler+1)^#word-1 do
		counter[1] = counter[1] + 1
		for j = 1, #counter-1 do
			if counter[j] == #filler+1 then
				counter[j], counter[j+1] = 0, counter[j+1] + 1
			else
				break
			end
		end
		local index = 0
		words[#words+1] = word:gsub(".", function(c)
			index = index + 1
			return filler[counter[index]] or c
		end)
	end
	return words
end

local words = variants("hello", {"#","$"})
for k, v in pairs(words) do print(k, v) end

edit: here’s a much shorter recursive function

local function variants(word, filler)
	if #word == 1 then return {word, unpack(filler)} end
	local combinations = variants(word:sub(2), filler)
	local words = {}
	for i = 1, #combinations do
		for j = 0, #filler do
			words[#words+1] = (filler[j] or word:sub(1, 1))..combinations[i]
		end
	end
	return words
end
3 Likes