2
\$\begingroup\$

Left limit, right limit and the digit to be counted is entered. This code works only for whole numbers i. e. from 0 to n. This code returns the number of occurence of the digit n in the given range. Please review this code and suggest improvements.

#include <iostream>

int count_n(int l, int r, int n)
{
    if (r <= l)
    {
        std::cerr << "Right limit must greater then left limit\n";
        return 0;
    }

    if (l < 0)
    {
        std::cerr << "Only positive integers\n";
        return 0;
    }

    int count = 0;
    for (int i = l; i <= r; ++i)
    {
        int i_copy = i;
        while (i_copy != 0)
        {
            if (i_copy % 10  == n)
            {
                count++;
            }
            i_copy = i_copy / 10;
        }
    }
    return count;
}

int main()
{
    int left_limit, right_limit, num;
    std::cout << "Enter left limit, right limit and the number(Only positive numbers)\n";
    std::cin >> left_limit >> right_limit >> num;

    int result = count_n(left_limit, right_limit, num);
    std::cout << result << "\n";
}

Output:

Enter left limit, right limit and the number(Only for positive numbers)
1 20 0
2
\$\endgroup\$
  • \$\begingroup\$ There is a much better algorithm. See this answer for some hints as to how to derive it. \$\endgroup\$ – Edward Oct 27 '19 at 18:09
3
\$\begingroup\$

In addition to this, you should specify validation for n ( digit ). Also, it may be better to group validations into separate function.

void check_input(int min_left, int max_right, int digit) {
  if (max_right <= min_left)
    throw std::invalid_argument("right is <= left, expected right > left");
  if (min_left < 0)
    throw std::invalid_argument("left < 0, expected left > 0");
  if (digit <= 0)
    throw std::invalid_argument("digit <= 0");
    //throw std::invalid_argument("number <= 0");  
  if (digit > 9)
    throw std::invalid_argument("digit > 9");

  ////number:
  //if (digit > max_right)
  //  throw std::invalid_argument("number > right limit");
}

int count_digit_entries(int min_left, int max_right, int digit) {
//...
}

int main() {
  int left_limit, right_limit, num;
  std::cout << "Enter left limit, right limit and the number(Only positive numbers)\n";
  std::cin >> left_limit >> right_limit >> num;

  check_input(left_limit, right_limit, num);

  int result = count_digit_entries(left_limit, right_limit, num);

  std::cout << "\nTotal: " << result << "\n";
}

You may want to find not only digits but a whole numbers.

//...


#define DEBUG
#ifdef  DEBUG
#define debug(x) x
#else 
#define debug(x)
#endif


int count_digit_entries(int min_left, int max_right, int search_number) {
  int count = 0;

  int mod = 10;
  while(search_number / mod > 0) mod = mod * 10; // 279 -> 1000

  for (int current_number = min_left, right = max_right; current_number < right; ++current_number) {
    int copied_current_number = current_number; // 542793

    while (copied_current_number >= search_number) {
        // 542793 - 279 % 1000    >0 
        // 54279 - 279 % 1000     =0

      if ( ( (copied_current_number - search_number) % mod ) == 0 ) { 
        debug(std::cout << current_number << " ");
        ++count;
      };
      copied_current_number = copied_current_number / 10; 
      // 542793 -> 54279

    };
  };

  return count;
};

Output:

Enter left limit, right limit and the number(Only positive numbers)
0 1000 25
25 125 225 250 251 252 253 254 255 256 257 258 259 325 425 525 625 725 825 925 
Total: 20
\$\endgroup\$
1
\$\begingroup\$

1. Error handling

Since 0 could also be a valid result for the input (e.g. 6 10 5), I'd prefer to indicate invalid input via exceptions rather than the return value:

int count_n(int l, int r, int n) {
    if (r <= l) {
        throw std::invalid_argument("Right limit must greater then left limit");
    }

    if (l < 0) {
        throw std::invalid_argument("Only positive integers");
    }

    // ...
}

Thus the caller of the function can distinguish invalid input parameters from valid results by putting the call of count_n() into a try / catch block.

2. Function and parameter naming

Naming the function count_n() and the parameter for the digit to count n is a bit unclear.
You should rather use the signature

 int count_digit(int min_left, int max_right, int digit);

to make the intend of that function clearer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.