Sara Millan
Sara Millan

Reputation: 33

How can I find numbers with repeating digits in a vector?

Given a range of numbers between a and b, I need to find all numbers that have repeating digits. They don't have to be consecutive repeating digits- for example 121 would count as one of these numbers. I already coded the input of the vector list itself - I just don't know how to analyze the digits of each individual item in that vector.

#include <iostream>
#include <vector>
using namespace std;

int main(){
    //variables
    int a, b, i = 0; // a & b inputs, i for iterating

    //entering number range
    cout << "Enter the first number" << endl;
    cin >> a;
    cout << "Enter the second number" << endl;
    cin >> b;


    //making a vector to contain numbers between a and b
    vector<int> listofnums((b-a)+1); 
    int initialvalue = a;
    while (i <= (b-a)) {  
        listofnums[i] = initialvalue;                                 
        initialvalue++; 
        i++;
    }

    //printing the completed vector
    for ( const auto &item : listofnums ){
        std::cout << item << ' ';
    }

    std::cout << '\n';

    //analyzing the digits of each item in the vector
    //code for finding repeating digits here

    return 0;
}

Upvotes: 0

Views: 554

Answers (3)

A M
A M

Reputation: 15267

There are one million solutions. Everybody can do, what he wants

The standard approach in C++ for these types of problem is to use a std::map as a counter. A std::map has an index operator. The index operator returns a reference to a value, if the key isexisting. If the key is not existing, it will create a new entry and then return a reference to the default initialized value.

We then increment the reference.

Before that, we convert the integer to a string and then work on the chararcters(digits). Counting is then as easy as:

for (const char& digit : numberAsString) counter[digit]++;

We put all the operations into a function and can then use this in C++ algorithms.

Please see:

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>

bool check(const int& i) {
    // Convert int to string
    std::string numberAsString{ std::to_string(i) };

    // We will use a map as counter
    std::map<char, size_t> counter{};

    // Count the digits
    for (const char& digit : numberAsString) counter[digit]++;

    // Search for a digit count > 1
    bool result{};
    for (const auto& [digit, count] : counter)  if (count > 1) { result = true; break; };

    return result;
}


using namespace std;

int main() {
    //variables
    int a, b, i = 0; // a & b inputs, i for iterating

    //entering number range
    cout << "Enter the first number" << endl;
    cin >> a;
    cout << "Enter the second number" << endl;
    cin >> b;


    //making a vector to contain numbers between a and b
    vector<int> listofnums((b - a) + 1);
    int initialvalue = a;
    while (i <= (b - a)) {
        listofnums[i] = initialvalue;
        initialvalue++;
        i++;
    }

    //printing the completed vector
    for (const auto& item : listofnums) {
        std::cout << item << ' ';
    }

    cout << '\n';

    //analyzing the digits of each item in the vector
    //code for finding repeating digits here

    // Example 1
    // print out all values in the vector having this property
    cout << "\n\n Result:\n";
    copy_if(listofnums.begin(), listofnums.end(), ostream_iterator<int>(cout,"\n"), check);

    // Example 2
    // copy all thos values to a new vector
    vector<int> result;
    copy_if(listofnums.begin(), listofnums.end(), back_inserter(result), check);

    return 0;
}

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

Here you are.

#include <iostream>
#include <bitset>
#include <tuple>
#include <vector>
#include <algorithm>

bool duplicated_digits( int value )
{
    const int Base = 10;
    std::bitset<Base> b;

    bool is_duplicate = false;

    do
    {
        int digit = value % Base;

        if ( digit < 0 ) digit = -digit;

        b.flip( digit );
        is_duplicate = not b.test( digit );
    } while ( not is_duplicate && ( value /= Base ) != 0 );

    return is_duplicate;
}

int main()
{
    int a = 0, b = 0; 

    std::cout << "Enter the first number: ";
    std::cin >> a;
    std::cout << "Enter the second number: ";
    std::cin >> b;

    std::tie( a, b ) = std::minmax( { a, b } );

    std::vector<int> v; 

    int current_value = a;
    do
    {
        if ( duplicated_digits( current_value ) ) v.push_back( current_value );
    } while ( current_value++ != b );

    if ( not v.empty() )
    {
        std::cout << "There are the following numbers with duplicated digits "
                     "in the range [ "
                  << a << ", " << b << " ]\n";                   
        for ( const auto &item : v )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    }
    else
    {
        std::cout << "There are no numbers with duplicated digits in the range [ "
                  << a << ", " << b << " ]\n";                   
    }

    return 0;
}

The program output might look for example the following way

Enter the first number: 50
Enter the second number: -50
There are the following numbers with duplicated digits in the range [ -50, 50 ]
-44 -33 -22 -11 11 22 33 44 

Or another example of possible program output

Enter the first number: -100
Enter the second number: -130
There are the following numbers with duplicated digits in the range [ -130, -100 ]
-122 -121 -119 -118 -117 -116 -115 -114 -113 -112 -111 -110 -101 -100 

Upvotes: 1

Adrian Mole
Adrian Mole

Reputation: 51835

You can get the value of the lowest (least significant) digit of a decimal number by taking the remainder after dividing it by 10; in C++ this is readily accomplished using the modulo operator (%). Thus, given a integer variable, a, with a value of 123, the statement int b = a % 10; will assign 3 to b.

Now, by running a loop in which we sequentially divide the 'test' number by 10 (until it reaches zero), we can get the values for each digit. If we keep an array of bool values, setting each one to true when we find a given digit, we can quickly detect a repeated digit.

Thus, this function will do the job:

bool HasRepeatDigit(int x)
{
    bool hasDigit[10] = {false, false, false, false, false, false, false, false, false, false};
    while (x > 0) {
        int digit = x % 10;
        if (hasDigit[digit]) return true; // We already have this digit!
        hasDigit[digit] = true; // Flag the digit we just found
        x /= 10; // Divide by 10, to move onto the next digit
    }
    return false; // If we get here, there is no repeat digit!
}

You can then call this function on each of your 'test' numbers in a second loop, adding those numbers that have repeated digits to a new vector:

vector<int> withRepeats;
for (auto i : listofnums) { // Tests "i" for every element in listofnums
    if (HasRepeatDigit(i)) withRepeats.push_back(i); // Append this to the new vector
}

Feel free to ask for further explanation and/or clarification.

As an aside, you can reduce the code that fills your listofnums vector using the std::iota function (defined in the <numeric> header):

#include <numeric>
//...
std::iota(begin(listofnums), end(listofnums), a);

Upvotes: 1

Related Questions