Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test for all possibilities in a string

I am trying to test (compare against another value in memory) for all possible combinations in a string but wanted to know what the best way is to do it.

My input string is 0246, the trick is that each number can be one of 2 options, for instance:

[0,1][2,3][4,5][6,7]

I want to be able to flip through all possible combinations, it's kind of like cracking a safe but that is not the purpose of this, I promise!

I was thinking of doing a foreach loop to switch through each option but my loops would be nested and I know performance will take a hit, since Linq is like the new black, can this be done using that?

UPDATE*

I want the result to return in order from low to high as my original string that I am comparing against could be 0001 but doesn't make sense to randomly jump around.

I also want to keep track of how many times I had to generate a different variation of this and note that down as it will be used at a later time.

like image 812
nGX Avatar asked Mar 11 '26 18:03

nGX


2 Answers

Do you mean this:

var allCombinations = from a in new[] { "0", "1", }
                      from b in new[] { "2", "3", }
                      from c in new[] { "4", "5", }
                      from d in new[] { "6", "7", }
                      select a + b + c + d;

Or more fancily:

var allCombinations = from a in "01"
                      from b in "23"
                      from c in "45"
                      from d in "67"
                      select string.Concat(a, b, c, d);

In the latter (fancy) version a, b, c and d are char variables, and string.Concat(a, b, c, d) could also be written a.ToString() + b + c + d.

like image 196
Jeppe Stig Nielsen Avatar answered Mar 13 '26 08:03

Jeppe Stig Nielsen


Here's an approach that works for any number of inputs (after parsing your format into int[][]), using Aggregate and Join:

var data = new[]
{
    new[] { 0, 1 },
    new[] { 2, 3 },
    new[] { 4, 5 },
    new[] { 6, 7 },
};
var nums = data.Aggregate(new[] { "" }.AsEnumerable(),
        (agg, arr) => agg.Join(arr, x => 1, x => 1, (i, j) => i.ToString() + j));

Outputs:

0246 
0247 
0256 
0257 
0346 
0347 
0356 
0357 
1246 
1247 
1256 
1257 
1346 
1347 
1356 
1357 

It uses LINQ, so it's probably not the fastest thing ever (still < 1 ms for me with this data), and something smells about how I'm using Join with fixed join values, so it's probably not the best thing ever, but hey - it works.

I'm assuming you actually need all the values listed out. If all you're really trying to do is see if the value matches something that looks like a valid passcode, a regex like Dmitry's solution is probably the way to go.

like image 33
Tim S. Avatar answered Mar 13 '26 08:03

Tim S.