5

I have a recursive function, and within the function a random element from an array is selected, but no matter what I do I keep getting the same seed.

static Random rand = new Random();
public String spintaxParser(String s)
    {
        if (s.Contains('{'))
        {
            int closingBracePosition = s.IndexOf('}');
            int openingBracePosition = closingBracePosition;

            while (!s[openingBracePosition].Equals('{'))
                openingBracePosition--;

            String spintaxBlock = s.Substring(openingBracePosition, closingBracePosition - openingBracePosition + 1);

            String[] items = spintaxBlock.Substring(1, spintaxBlock.Length - 2).Split('|');


            s = s.Replace(spintaxBlock, items[rand.Next(items.Length)]);

            return spintaxParser(s);
        }
        else
        {
            return s;
        }
    }

What's the best way to handle Random in a recursive function?

Sian Jakey Ellis
  • 435
  • 1
  • 4
  • 13
  • Did you try searching for an answer to this? There are so many question on the topic of using Random - for instance, http://stackoverflow.com/questions/4855756/random-number-generation-same-number-returned (which itself refers to other related questions). – AAT Nov 04 '11 at 14:23
  • We'll need some source code to really be able to help. – Corey Ogburn Nov 04 '11 at 14:24
  • What exactly do you mean by "I keep getting the same seed"? Could you provide an example of input, expected output and actual output? – LukeH Nov 04 '11 at 14:29
  • 2
    IMO with your current code it's impossible to get same seed except items count is equal or smaller than 1. – Saeed Amiri Nov 04 '11 at 14:30

4 Answers4

3

Declare a single (static) instance of the Random object outside the scope of your recursive function, then invoke the instance from inside your recursive function.

The default constructor of Random will automatically seed it with the current timestamp, so you're getting the same values over and over because you're constantly creating a new instance of the Random object.

Edit: Also, you could try this, although it's definitely not ideal. I would prefer a single Random instance or a static seed over this method.

Random r = new Random( Guid.NewGuid().GetHashCode() );
Brandon Moretz
  • 7,512
  • 3
  • 33
  • 43
  • would it be possible to create a new instance of the Random class inside the recursive function and pass in a timestamp? – Sian Jakey Ellis Nov 04 '11 at 14:28
  • @SianJakeyEllis you could create a global (static) seed and reuse it in the constructor when creating your random objects. However, that's probably a bit less than ideal efficiency wise. – Brandon Moretz Nov 04 '11 at 14:30
2

It would help if you posted code. But in the absence of that, I will use my psychic powers and guess that you are using a pattern like this

void MyRecursiveFunction() {
  var index=new Random().Next(...);
  ...
}

If true, the fix is to change your code so that it does "new Random()" just once and passes it around (or stores it in some appropriate instance variable) rather than constructing a new one every time.

Corey Kosak
  • 2,615
  • 17
  • 13
1

Pass the Random as a parameter to the recursive function and use the passed instance to get the next value from it each time.

public void Recurse(object param, Random rand)
{

  ...
  var val = rand.Next();
  //use the value ... 
  Recurse(obj, rand);
}

Recurse(arg, new Random());

Obviously, the recursion will bottom out in some way but this demonstrates the principle.

Steve Rowbotham
  • 2,868
  • 17
  • 18
0

I suggest that you include the random object in the recursive function itself. This test should prove that you wont always get the same int.

[Test]
    public void TestSpintaxRandom()
    {
        spintaxParser("{|||{|||{|||{|||{|||{|||{|||{|||}}}}}}}}", new Random());
    }

    public String spintaxParser(String s, Random r)
    {
        if (s.Contains('{'))
        {
            var closingBracePosition = s.IndexOf('}');
            var openingBracePosition = closingBracePosition;

            while (!s[openingBracePosition].Equals('{'))
                openingBracePosition--;

            var spintaxBlock = s.Substring(openingBracePosition, closingBracePosition - openingBracePosition + 1);
            var items = spintaxBlock.Substring(1, spintaxBlock.Length - 2).Split('|');

            var next = r.Next(items.Length);
            Console.WriteLine(next);
            s = s.Replace(spintaxBlock, items[next]);

            return spintaxParser(s, r);
        }

        return s;
    }
Ioannis Karadimas
  • 7,746
  • 3
  • 35
  • 45