Count repetitions of integers C ++, Array

2

Good morning, the exercise says the following

"Design an algorithm that accepts a natural number n and counts the number of times each digit is repeated within it"

I know I have not posted my code, but I do not know where to start, that is, if I put more than several digits in each array I do not know how to count each digit, but rather the problem I have to separate the value of the array in digits.

Yes I tried to solve it using pencil and paper. I have developed the following algorithm:

1.- Write the figures from 0 to 9 from top to bottom.
2.- Write the number to process from left to right. Put your finger on the number on the left.
3.- Add a stick to the vertical figure that corresponds to the figure where the finger is.
4.- Move your finger one figure to the right.
5.- If the finger is on a figure go to step 3.
6.- Problem solved, the sticks indicate how many times each figure appears.

Here is a drawing with my algorithm in action:

This question is an improved copy of one that once made Skydez and that was deleted.

    
asked by Jose Antonio Dura Olmos 30.06.2017 в 22:46
source

3 answers

3

They ask you to process a number entered by keyboard ... in this case you can assume that you are only going to enter a number and this allows us to take shortcuts: What if instead of reading the data as a number and then separate its digits do not read the character number to character? With this new approach, simpler algorithms remain.

You can choose to use a fixed-size array. The number of elements coincides with the range of values to be controlled. The idea is to accumulate in this array the number of occurrences of each number. In this case the range of values is 10 (numbers from 0 to 9).

The idea is to read digit by digit and add one in the position corresponding to that digit:

#include <iostream>

int main()
{
  int contador[10] = {0};

  char c;
  while( std::cin >> c && c != '\n' )
    contador[c-'0']++;

  for ( int i=0; i<10; ++i )
    std::cout << "La cifra " << i << " aparece " << contador[i] << " veces.\n";
}

Of course, if the code supports the C ++ 11 standard or higher, you can use the class array to be able to use iterators and not have to remember the range of values:

#include <iostream>
#include <array>

int main()
{
  std::array<int,10> contador = {0};

  char c;
  while( std::cin >> c && c != '\n' )
    contador[c-'0']++;

  for ( size_t i=0; i<contador.size(); ++i )
    std::cout << "La cifra " << i << " aparece " << contador[i] << " veces.\n";
}    

If the range of values is wider, it might make sense to use a map. The advantage of using a map is that if a significant part of the range is not used, the memory savings can be considerable.

Note in the following example how the digits that are not in the number do not appear in the result:

#include <iostream>
#include <map>

int main()
{
  std::map<char,int> contador;

  char c;
  while( std::cin >> c && c != '\n' )
    contador[c]++;

  for ( auto& pair : contador )
    std::cout << "La cifra " << pair.first << " aparece " << pair.second << " veces.\n";
}

Another advantage of this solution is that we save the conversion char->int .

Of course you could also show the digits without occurrences ... in return the code would get very slightly complicated:

#include <iostream>
#include <map>

int main()
{
  std::map<char,int> contador;

  char c;
  while( std::cin >> c && c != '\n' )
    contador[c]++;

  for ( char c = '0'; c <= '9'; ++c )
    std::cout << "La cifra " << c << " aparece " << contador[c] << " veces.\n";
}

An improvement to these last two solutions would be to use std::unordered_map . This container would give better response times if the range of values to be mapped was high (several thousand). It is not the case so I see no need to extend the answer further. I just wanted to record the existence of this third solution.

    
answered by 02.07.2017 / 04:32
source
5

First a program that reads a natural number and prints it on the screen:

#include <iostream>

int main() {
    unsigned int n;  // Variable de números no negativos
    std::cin >> n;   // Lee un número de teclado y lo almacena en n.
    std::cout << n;  // Imprime el número dentro de la variable n
    std::cout << std::endl; // Imprime salto de línea
    return 0;
}

With that you already know how to read a keyboard number.

Now a program that prints one by one the numbers of a natural number. From the most significant to the least significant.
The last number of a number is always the rest of dividing that number by 10. This operation in C ++ is called a module and is done by the operator % .
Once we print that number we are left with the superiors dividing by 10.

#include <iostream>

int main() {
    unsigned int n = 19383;  // Variable de números no negativos con un valor
    do {
        int resto = n %10; // La última cifra
        std::cout << resto << std::endl; // La imprimimos con salto de línea
        n = n / 10; // Esto es una división entera
    } while ( n>0 ); // Cuando el número se queda a 0 es que ya no hay más cifras.
    return 0;
}

With that you already know how to divide a number into figures.
You only need to count how many times each figure appears.

You can use an array of ten elements to count each of the ten figures.

int cuentaCifra[0];

Which you should initialize to 0.

for ( int i=0; i<10; ++i )
  cuentaCifra[i] = 0;

And you can print such that:

for ( int i=0; i<10; ++i )
  std::cout << "La cifra " << i << " aparece " << cuentaCifra[i] << " veces." << std::endl;

If you find the figure n and want to post it you must add one to cuentaCifra[n] :

++cuentaCifra[n]

Put together everything you've learned before in an appropriate way and you'll have the solution to your exercise.

    
answered by 30.06.2017 в 22:46
3

You do not need any characteristic of C ++, so I will limit myself to C (by the way, I differentiate my response from the previous ones, contributing something new).

To be able to read a keyboard number, we will use scanf() . This function allows a number taken from the keyboard to be saved in an integer variable, such as: int num; scanf( "%d", &num ) . It is important to remember to put an ampersand in front of the variable, as it will be modified within scanf() . The opposite of scanf() is printf() , which allows you to display a value per console. Both functions accept a string of characters to know the format of the value to be displayed or to be requested by keyboard, as the first parameter. %d represents an integer number, equivalent to type int .

To save the results, we need a data structure that allows us to store the result of the count for each number. We will need to be able to ask: for 5 ?, and to return us: 1 time (or whatever they are). You also need to be able to say: "increase the count by 1 to 5." That is, we need to be able to associate an integer value (the count) with another integer value (a digit from 0 to 9). In C ++ it is possible to use a map<> , but in the specific case of associating an integer value with another integer value, we can use a simple vector, a primitive array. If we create: int digitos[10] , then we have 10 integer values to save the character count: one in position 0, another in position 1 ... so, the position in the vector (the index) represents the digits, while the value of the position, the count. Of course, we will have to initialize each position of the vector to zero before using it.

Finally, we need to be able to access each number of the number that the user has entered by keyboard. One way to do this is to convert the number to a character string, and then access each position and post it. But this implies reserving memory, when we can do the same with simple calculations: suppose we have the number 482. If we divide the number by 10, we have 48. The rest will be 2. If we divide 48 by 10, the result is 4, while the rest is 8. If we divide the number again by 10, the result is 0, the rest is 4. With the remains of the divisions, we have "walked" each number of the number, though, in the opposite direction, although for count the appearances of each figure that does not matter. The only thing to keep in mind is that the number must be positive, so it will be necessary to call abs() .

Of course, to do all this it is necessary to use loops, which allow repeating the execution of a body of instructions several times. for() is used when you previously know the number of times that body of instructions will have to execute. while() is used when the number of times to repeat that code is not known, so it is accompanied by a condition, and the body of instructions will be executed while the condition is met (return true ).

void cuenta_ocurrencias_digitos(int n, int digitos[])
{
    // Inicializa
    for(int i = 0; i < 10; ++i) {
        digitos[ i ] = 0;
    }

    // Cuenta las ocurrencias
    n = abs( n );
    while( n > 0 ) {
        digitos[ n % 10 ] += 1;
        n /= 10;
    }
}

The previous function initializes the vector digitos , and then decomposes the number in figures, increasing by one the position in the vector for each of them.

It's all left to show the results. The only relevant results are the counting of figures when said counting is greater than zero, as seen in the following function.

void muestra_resultado(int n, int digitos[])
{
    printf( "\nPara: %d\n", n );
    for(int i = 0; i < 10; ++i) {
        if ( digitos[ i ] > 0 ) {
            printf( "%d aparece %d veces.\n", i, digitos[ i ] );
        }
    }
    printf( "\n" );
}

I hope all this helps you. You have the full code in IDEOne .

    
answered by 02.07.2017 в 12:35