I have a software test failing from time to time, due to the fact that the string 123 appears when generating a string with SecureRandom.hex(32) (Ruby), which gives a 64 symbols string.
This includes (A-F) and (0-9), so 16 symbols possible.
I have played a little, and I noticed that it can roughly happens 1500 times over 100,000 calls to the function, so around 1.5%.
What would be the formula to have the exact probability of this test failing?
As a developer, I had to share a little bit of code: JS Fiddle.
Edit: Answer's WolframAlpha link
54392126209570846953192790832763093471349103670511891931049735583247364107/
3618502788666131106986593281521497120414687020801267626233049500247285301248
≈0.0150317
≈1.50317%
An exact answer, via Inclusion Exclusion Principle:
Let $A_i =$ the set of 64-long strings where "123" appears starting at the $i$th position ($1 \le i \le 62$). E.g. if "123" appears at both the 2nd and 40th positions in string $x$, then $x \in A_2$ and $x \in A_{40}$, i.e. $x \in A_2 \cap A_{40} $.
Then $S = \bigcup_i A_i=$ the set of strings where "123" appears at least once, and your desired probability is $|S|/16^{64}$.
The Inclusion Exclusion Principle gives:
$$|S| = |\bigcup A_i| = \sum_i |A_i| - \sum_{i<j} |A_i \cap A_j| + \sum_{i<j<k} |A_i \cap A_j \cap A_k| - \dots $$
Obviously $|A_i| = 16^{61}$ as the other 61 positions can be anything. So the first term is $\sum_i |A_i| = 62 \cdot 16^{61}$.
Now two occurrences of "123" cannot overlap (unlike e.g. if you're looking for "111" in which case they CAN overlap). So if $j - i < 3$, then $|A_i \cap A_j| = 0$. For the non-trivial case of $j - i \ge 3$, the other $64 - 3 - 3 = 58$ positions can be filled with anything, so $|A_i \cap A_j| = 16^{58}$.
Meanwhile, how many $(i, j)$ pairs are there s.t. $j - i \ge 3$? Imagine "merging" each "123" into a new character "!", so the final string length is now $64-2-2 = 60$ instead and there are two "!" characters. The number of ways to do this is simply ${60 \choose 2}$. Thus the 2nd term is:
$$ \sum_{i<j} |A_i \cap A_j| = {60 \choose 2} 16^{58}$$
The $m$th term is similar and we have:
$$ \sum_{i_1 < i_2 < \cdots < i_m} |A_{i_1} \cap A_{i_2} \cap \cdots \cap A_{i_m}| = {64 - 2m \choose m} 16^{64 - 3m} $$
So the final result is:
$$ |S| = \sum_{m=1}^{21} (-1)^{m+1} {64 - 2m \choose m} 16^{64 - 3m} $$