Going from number of pages P to total number of digits D is pretty easy, and unfortunately that is what most solutions have offered (with some errors or limitations).
Your problem goes the other way, you want the inverse function: the number of pages is the unknown, the total number of digits is known.
I see two possible approaches:
(1) the slow one: try P=1, calculate D, if less than the given D-value, increment P and try again. That is obviously inefficient.
(2) note how the function D(P) is piecewise linear, i.e. it grows by 1 as long as P<=9, by 2 when 10<=P<=99 by 3 when 100<=P<=999, etc.
So we will need a two-step approach: find out in which segment of the piecewise curve D
falls, then do the linear interpolation. In pseudo-code that might look like this:
int pagesFromTotalDigits(int D) {
if (D<=9) return D;
if (D<=189) return 9+(D-9)/2;
if (D<=2889) return 99+(D-189)/3;
if (D<=38889) return 999+(D-2889)/4;
etc
}
Two remarks:
(a) the above magic numbers are the P and D(P) values for consecutive P that satisfy P+1 = power of 10; they can be calculated at run-time in a loop, in fact all those if statements can be reduced to a single if statement inside a loop with increasing powers of 10.
int pagesFromTotalDigits(int D) {
int prevDbreak = 0;
int Dbreak = 9;
int pow10 = 1;
for (int exp = 1; ; exp++) {
if (D <= Dbreak) return (pow10 - 1) + (D - prevDbreak) / exp;
pow10 = 10 * pow10;
prevDbreak = Dbreak;
Dbreak = Dbreak + 9 * pow10 * (exp + 1);
}
}
(b) not all D values are valid, the code shown does not flag bad D values. A simple D(P) calculation and comparison can be added before returning the result (throw an exception when D is impossible).
ADDED: no need to calculate D(P), just check the division leaves no remainder.
ADDED2: oh my, that was overly complex; a less convoluted implementation would build up the result P, and reduce D while going along, like so:
int pagesFromTotalDigits(int D) {
if (D < 0) throw ...
int P = 0;
int threshold = 9;
int pageDigits = 1;
while (D > threshold * pageDigits) {
P += threshold;
D -= threshold * pageDigits++;
threshold *= 10;
}
if (D % pageDigits != 0) throw ...
return P + D / pageDigits;
}
:)