How to calculate the odds of finding "20" at least three times in a sha256 string? For example, what are the odds of this happening:

Can this even be calculated?
If we assume that the output of a SHA-256 hash is roughly random, this is ultimately just a combinatorics problem.  That is:

Given a random string of 64 hexadecimal digits, what is the probability that the sequence &quot;20&quot; appears 3 or more times.

We can think of this as having three set items, the three &quot;20&quot;s, and then 58 other hexadecimal characters distributed around them.  That gives us four spots to put the rest of the numbers:
$$ X_1\ |\ 20\ |\ X_2\ |\ 20\ |\ X_3\ |\ 20\ |\ X_4 $$
Where $X_n$ is a string of hexadecimal digits with size ranging 0 to 58, with $\sum_{i=1}^n len(X_i) = 58$ and &quot;|&quot; denoting concatenation.
After seeing kodlu's answers I figured I would include a more complete answer.
The above ultimately led me down the path of counting all possible 58-hexadecimal-digit strings and then counting the ways we can &quot;insert&quot; the 20's throughout it.  The number of random strings is $16^{58}$.  We can insert 20's at the beginning or after any of the digits, and there are 3 inserts required.  Since we want to allow repetitions (sections without any digits between the 20's) we want ${58 + 3 - 1 \choose 3} = {60 \choose 3}$ (see combinations with repetition).  Dividing that by the total number of SHA-256 hashes, we get:
$$ \frac{16^{58} \cdot {60 \choose 3}}{2^{256}} \approx 0.00203967 \approx ~0.204\% $$
Just to see if this made sense, I ran a quick test using bash to see how this panned out:
#!/bin/bash

function next() {
    head -c 32 /dev/urandom | xxd -p -c 64
}

total=100000

count=0
i=0
while [[ $i -lt $total ]]; do
    next | grep -q &quot;20.*20.*20&quot; &amp;&amp; let count=&quot;$count+1"
    let i="$i+1&quot;
done

echo &quot;$count / $total&quot;

I ran this a few times and got:
$$175 / 100000 = 0.175 \%$$
$$200 / 100000 = 0.200 \%$$
$$187 / 100000 = 0.187 \%$$
So this seems about right.

A couple notes on the properties of this.  As kodlu mentioned, since &quot;20&quot; is not symmetrical, we don't have to worry about things like &quot;FFF&quot; potentially counting as two instances of &quot;FF&quot; if that's what we were looking for.  However, if we don't want to count that as two, my approach should still work, even if we were using a symmetric target string like &quot;FF&quot; or &quot;00&quot;.
Also, since we are looking for &quot;at least&quot; 3 occurrences of &quot;20&quot; in the string, we don't have care about whether any of $X_1, ..., X_4$ contain a 20, those are just extra.  In fact, this is exactly why this approach works.  That said, we may end up double counting in cases where our variant placements of 20s don't really change the ultimate string.  For example, if the 58-digit string is &quot;202020202020...&quot; there are many places we could insert our three &quot;20's&quot; without actually changing the resulting string.  Accounting for that could prove tricky, and I'm not sure how to do so at the moment, but given the extremely large number of cases we're looking at I'm inclined to think this is probably relatively small.  Although it's not hard to come up with other examples, so caution is good.  Regardless, this type of thing is exactly why I wanted to include a more empirical approach (i.e. brute-force counting with code).
On that note, I decided to run another, longer test (with 1,000,000 values) to see if it might be closer to my updated probability than my original one.  Or at least further confirm that we're in the right ballpark.  I got:
$$ 1797 / 1000000 = 0.001797 = 0.1797 \% $$
So, for what it's worth, it seems like the answer is at least &quot;somewhere between 0.17% and 0.20%.&quot;