If you have a number like $6387$, then instead of doing $f(6387)$ you can do $f(6000) + f(300) + f(80) + f(7)$. For any $n$ in the form of $a*10^b$ where $a,b \in \mathbb{Z}$ ,
$f(n) = \begin{cases}
ab*10^{b-1} + 10^b & \text{:$b\ge1, a\gt2$} \\
ab*10^{b-1} + (n \bmod 10^b) + 1 & \text{:$b\ge1, a=2$} \\
ab*10^{b-1} & \text{:$b\ge1, a=1$} \\
1 & \text{:$b=0, a\ge2$} \\
0 & \text{:$b=0, a\lt2$} \\
\end{cases}$
For an explanation on how that equation works, take the number $6000$. If you put a $2$ in the units place (_ _ _ 2), then for all $4$ digit numbers, $6$ numbers can occupy the first spot, $10$ the second, and $10$ the third. $6*10*10 = 600$. The $2$ can also be placed in the tens and hundreds place, so make that $600*3$. Now a $2$ can also be placed in the thousands place since 2 <= 6, but there can be 10 other digits everywhere else, so it would be $10*10*10$, leaving you with $1800+1000=2800$. (That is the basic logic behind what I did).
I do not know if you are looking for a function, or just an answer. But I know the answer is $28263827$.
import java.io.File;
import java.io.PrintWriter;
public class test {
public static long count = 0;
public static void main(String[] args) {
long i = 1;
find(i);
while (i != count) {
if(i%100000==0){
System.out.println(i + ":" + count);
}
i++;
find(i);
}
System.out.println(i);
}
public static void find(long s) {
String s2 = Long.toString(s);
char[] chars = s2.toCharArray();
for (char c : chars) {
if (c == '2')
count++;
}
}
}