Gradient RegEx Fractal Index and length Error

Boleeman

New member
Joined
Jan 15, 2025
Messages
1
Programming Experience
10+
Hi All.

I have converted a Gradient RegEx Fractal code from Java to CSharp in which you type in a RegEx string like 1*2*0 and it creates a fancy gradient pattern, saved to a png file. It used a nuget package called Fare which implements dk.briks.automation.

The Java version was originally here:
GitHub - SSODelta/GradientRegexImages: Creating pretty images from regular expressions using edit distance
and the Fare nuget for CSharp is here:

The
Fare did not have implemented GetStrings, but in the Java version of dk briks automation it was there.

In Java version:

Java GetString Implementation:
private static void getStrings(State s, Set<String> strings, StringBuilder path, int length) {
if (length == 0) {
if (s.accept)
strings.add(path.toString());
} else
for (Transition t : s.transitions)
for (int n = t.min; n <= t.max; n++) {
path.append((char)n);
getStrings(t.to, strings, path, length - 1);
path.deleteCharAt(path.length() - 1);
}
} 
 
and also 

public static Set<String> getStrings(Automaton a, int length) {
HashSet<String> strings = new HashSet<String>();
if (a.isSingleton && a.singleton.length() == length)
strings.add(a.singleton);
else if (length >= 0)
getStrings(a.initial, strings, new StringBuilder(), length);
return strings;


I tried to make a C# version of GetStrings that matches the Java code but I get the error message "Index and length must refer to a location within the string".
Googling suggested:
The error occurs in C# when you are trying to perform an operation (like accessing or removing characters) on a string or StringBuilder and the provided index and/or length is out of bounds for the current string or string-like object, but I still cannot find where that error is (getting really frustrated). Any help or hints would be greatly appreciated. I would really like to get it working in CSharp. At present the program compiles to an exe and is run in the console with say a test RegEx string 1*2*0 but I get the error message "Index and length must refer to a location within the string".

CSHarp GetString:
public static HashSet<string> GetStrings(Automaton automaton, int length)
{
    HashSet<string> strings = new HashSet<string>();
    if (automaton.IsSingleton && automaton.Singleton.Length == length)
        strings.Add(automaton.Singleton);
    else if (length >= 0)
        GetStrings(automaton.Initial, strings, new StringBuilder(), length);
    return strings;
}

private static void GetStrings(State s, HashSet<string> strings, StringBuilder path, int length)
{
    if (length == 0)
    {
        if (s.Accept)
            strings.Add(path.ToString());
    }
    else
    {
        foreach (Transition t in s.Transitions)
        {
            for (int n = t.Min; n <= t.Max; n++)
            {
                path.Append((char)n);
                GetStrings(t.To, strings, path, length - 1);
                
                // Only remove the last character if the path is not empty
                if (path.Length > 0)
                    path.Remove(path.Length - 1, 1);
            }
        }
    }
}


The problem might be too hard to solve, but I thought I would ask for help.
 

Attachments

  • Gradient RegEx updated.zip
    283.1 KB · Views: 1
  • testimage from Java.png
    testimage from Java.png
    35.4 KB · Views: 1
This is what happens when you do Pokemon exception handling:
C#:
try
{
   :
}
catch (FormatException)
{
    :
}
catch (IOException)
{
    :
}
catch (Exception ex)    // <--- Pokemon exception handling
{
    :
}
You should only catch the exceptions that you are expecting to happen and know how to handle. Doing a catch-all exception handler just sets you up for future instability. Yes, your code might not have crashed, but do you know if all your objects are still in a good state?

Granted, you do have it at the top level because you wanted to crash gracefully, but beware that someone else may just copy and paste the code and not realize what is going on.

Anyway, if you set Visual Studio to stop for all CLR exceptions:
1736949718607.png


You'll see that it stops at:
RegexToPoint:
public static Point RegexToPoint(string regex)
{

    //If it's the last letter, then we're at base case
    if (regex.Length == 1)
    {
        char c = regex[0];
        switch (c)
        {
            case '0':
                return new Point(0, 1);
            case '1':
                return new Point(0, 0);
            case '2':
                return new Point(1, 0);
            default:
                return new Point(1, 1);
        }
    }


    //Get the next location
    Point p = RegexToPoint(regex.Substring(regex.Length - 1, regex.Length));

    //Get what this point *would* have been
    Point q = RegexToPoint(regex.Substring(0, regex.Length - 1));
    Point k = new Point(q.X * 2 + p.X, q.Y * 2 + p.Y);
    return k;
}

You are asking for a substring of regex that is regex.Length characters long, but starting at the last character. Obviously, that would go beyond the string.
 
Last edited:
Not related to your problem, but you should only create a singleton Random object instance and use that one instead of doing something like:
C#:
private static int RandomColor()
{
    Random random = new Random();
    return random.Next(COLORS.Length);
}

The Random object in C# is initialized with the current time as the seed. The time resolution is typically much bigger than the speed of most code that runs in a tight loop. So you'll end up with essentially the same random values within a small timeframe.
 
Ah! I see. Looks like an error in porting the Java code to C#. In C#, the String.Substring() method takes a starting index and length. In Java, the string.substring() takes a starting index and an exclusive ending index.
 
Back
Top Bottom