A regular expression is a list of things to match. However, different languages have different RegEx flavors. ChatGPT uses the GoLang flavor which is the most limited, while Roblox uses a C++ version which, while not the best flavor, does support a few crucial features we need.
Every vertical bar character ( | ) defines a different target to match. So every arithmetic character gets its own target.
Next, we need to find every instances of an arithmatic character. This is done with what I call a matching group, or literally a pair of parenthesis( () ).
Now that we are matching characters, we need to find a way to match based on characters already present. Thankfully, C++ and C# both support a match group operator called “lookbehind”. It makes the parser validate characters behind the matching group instead of ahead. This is crucial, since we want to make sure to leave one arithmetic symbol, instead of matching the entire group.
Using the knowledge above, we pick an arithmetic symbol, and write a lookbehind matching group to find a matching arithmatic symbol behind it (done with (?<=...).) If a given character has a matching arithmatic symbol already present behind it, match the duplicate symbol.
Finally, we can go back to gsub, and tell it to delete the capture group with a simple replacement.
Your valid code:
local s1 = "1++++++2--+^^^3///++4^^5"
local s2 = s1:gsub("(?<=-)%1-|(?<=\+)%1\+|(?<=\*)%1\*|(?<=\/)%1\/|(?<=\^)%1\^", "%1")
print(s2) -- outputs : 1+2-+^3/+4^5
local function removeDuplicateSymbols(s: string, sym: string): string
local result = ""
for i, part in pairs(s:split(sym)) do
if part == "" then continue end
if i > 1 then result ..= sym end
result ..= part
end
return result
end
local function removeDuplicateOperations(s: string): string
local operations = {"+", "-", "*", "/", "^"}
local result = s
for _, operation in pairs(operations) do
result = removeDuplicateSymbols(result, operation)
end
return result
end
--Should print "1-2+3-4*5/6^7"
print(removeDuplicateOperations("1---2+++++3-4**5///6^^7"))