Click here to Skip to main content
15,887,812 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I am stuck in a problem where the user inputs the total number of digits used in numbering the pages and the program gives the total number of pages in the book.

(i.e. a book of 10 pages needs 11 digits to number because the numbers 1-9 are written with one digit and the number 10 is written with two digits; and an 11 pages book requires 13 digits, and so on ...).

What I have tried:

C++
#include <stdio.h>

int main() {
    int n, pages = 9;
    scanf("%d", &n);

    if (n <= 9) {
        printf("%d",n);
    }
    else if (n % 2 == 0) {
        printf("Invalid input");
    }
    else {
        while (n < 9) {
            pages++;
            n -= 2;
        }
    }
    return 0;
}
Posted
Updated 14-Feb-22 10:49am
v2
Comments
Maciej Los 14-Feb-22 5:42am    
The answer is pretty obvious...

10 pages = (10-1) + 2bits = 11 bits
11 pages = (11-1) + 2 bits = 12 bits
and so on.

So, the algorithm is:
var noOfPages = (noOfbitsProvidedByUser -1) + 2 bit.

In order to represent the integer n, you need (int)log10(n)+1 digits in order to represent n.
So a brute force approach would be
C
#include <stdio.h>
#include <math.h>

int main()
{
  int pages = 11;

  int digits = 0;
  for (int page = 1; page <= pages; ++page)
  {
    digits += (int)log10(page)+1;
  }
  printf("digits = %d\n", digits);

  return 0;
}


You may implement a more refined algorithm starting from the following example:
say pages = 1250.
For pages 1000 to 1250 you need 4*(1250-1000+1)
digits.
For pages 1 to 999 you need (9 + 90*2 + 900*3) digits.

By generalization
  digits(pages) = (L + 1) * (pages - P + 1) + 9 * (1 + 20 + .. + P / 10 * L);
where
  L = (int)log10(pages);
  P = pow(10,L);
 
Share this answer
 
Comments
Patrice T 14-Feb-22 9:26am    
+5
CPallini 14-Feb-22 9:59am    
Thank you.
Luc Pattyn 14-Feb-22 16:49pm    
unfortunately that is not what was asked for, you provided the inverse function!
CPallini 15-Feb-22 2:05am    
Well, inverting it is left as exercise. :-)
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:

pseudo
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.

pseudo
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:

pseudo
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;
}


:)
 
Share this answer
 
v6
Comments
CPallini 15-Feb-22 2:13am    
5.
While we are more than willing to help those that are stuck, that doesn't mean that we are here to do it all for you! We can't do all the work, you are either getting paid for this, or it's part of your grades and it wouldn't be at all fair for us to do it all for you.

So we need you to do the work, and we will help you when you get stuck. That doesn't mean we will give you a step by step solution you can hand in!
Start by explaining where you are at the moment, and what the next step in the process is. Then tell us what you have tried to get that next step working, and what happened when you did.

Start by thinking about how you would do it manually: would you think about each page number and how many digits it needs, adding that to a sum each time, or would you break the pages numbers into "groups": single character numbers, double character numbers, triple character numbers, and so on? One way could take weeks, and the other minutes ...
I know how I'd do it manually, and probably so do you! So think about how you would automate that.

If you are having problems getting started at all, then this may help: How to Write Code to Solve a Problem, A Beginner's Guide[^]
 
Share this answer
 
C++
#include <stdio.h>

int main() {
    int n, pages = 9;
    scanf("%d", &n);

    if (n <= 9) {
        printf("%d",n);
    }
    else if (n % 2 == 0) {
        printf("Invalid input");
    }
    else {
        while (n < 9) { // here it should be (n > 9)
            pages++;
            n -= 2;
        }
        // Here you forgot to print the answer
    }
    return 0;
}


Your code do not behave the way you expect, or you don't understand why !

There is an almost universal solution: Run your code on debugger step by step, inspect variables.
The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't know what your code is supposed to do, it don't find bugs, it just help you to by showing you what is going on. When the code don't do what is expected, you are close to a bug.
To see what your code is doing: Just set a breakpoint and see your code performing, the debugger allow you to execute lines 1 by 1 and to inspect variables as it execute.

Debugger - Wikipedia, the free encyclopedia[^]

Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]
Basic Debugging with Visual Studio 2010 - YouTube[^]

1.11 — Debugging your program (stepping and breakpoints) | Learn C++[^]

The debugger is here to only show you what your code is doing and your task is to compare with what it should do.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900