Разминка для мозгов: проверить наличие двух одинаковых цифр в числе

Сегодня в разделе «Готовые решения» обнаружил програму на Паскале для проверки наличия двух одинаковых цифр в числе.

Задача:

Напишите программу, которая определяет, верно ли, что введённое число содержит по крайней мере две одинаковых цифры, возможно, не стоящие рядом (как, например, 212).

Входные данные
Входная строка содержит одно натуральное число.

Выходные данные
Программа должна вывести слово «YES», если в числе есть две одинаковые цифры, и слово «NO», если такой пары цифр нет.

Если решение перевести с Pascal на C++, оно выглядит так:

#include <iostream>

using namespace std;

int main() {
    int a, b, c, s;

    cout << "Number: ";
    cin >> c;

    do {
        a = c % 10;
        c = c / 10;
        s = c;
        while (s > 0) {
            b = s % 10;
            s = s / 10;
            if (a == b) {
                cout << "yes" << endl;
                a = 77;
                break;
            }
        }
        if (a == 77)
            break;
    } while (c != 0);
    if (a != 77)
        cout << "no" << endl;

    system("pause");
    return 0;
}

Программа работает правильно. Но есть некоторые «шероховатости» как в плане эффективности, так и в плане стиля.

Задание:

Придумайте другой, желательно более оптимальный, алгоритм решения этой задачи и напишите программу.

Примечания. (1) Задание несложное, для новичков. (2) Считаем, что всегда вводится корректное число: положительное целое в пределах типа int (со знаком). (3) При написании программы постарайтесь придерживаться хорошего стиля программирования.

Cranium, так там используется чтение из файла, подшаманьте с библиотекой fstream. С чтением программа становится сложнее )

if (a != 77)
   cout << "no" << endl;

Новички могут не догнать
15:47
Попробую собрать на коленке

что-то вроде:

#include <iostream>
#include <iomanip>
#include <cstring>

bool eq(int num_)
{
    bool arr[10]={false};
    int num = abs(num_);
    while( num != 0 ){
        int d = num%10;
        if( arr[d] ){
            return true;
        }
        arr[d] = true;        
        num /= 10;
    }
    return false;
}



int main()
{
    std::cout << std::boolalpha << eq(123) << std::endl;
}

Ahmasoft, очепятку в строке поправил.

На счёт «там используется чтение из файла, подшаманьте с библиотекой fstream» — не понял. Чтение из файла ни «там», ни «здесь» не используется. К тому же эта задачка на соображалку, а не на знание работы с вводом-выводом.

«Новички могут не догнать» — а вот здесь как раз пускай догоняют. Не такой уж и крутой финт.

«Новички могут не догнать» — а вот здесь как раз пускай догоняют.

Пусть лучше так не делают.
Когда одна переменная используется
для хреновой тучи целей, хочется удавить.
В том коде не хватает только

a = 0;
return a;

Да и вывод раскидан хрен пойми как.
В общем, код сам по себе выглядит не ахти.

Croessmah, не думал, что позиционируешь себя новичком ;-)

Есть, работает.

Ещё варианты?..

Croessmah,

Пусть лучше так не делают.
...
В общем, код сам по себе выглядит не ахти.

Я в задании поэтому и сделал приписку о хорошем стиле программирования.

не думал, что позиционируешь себя новичком

Ну так если я новичок,
что тут скрывать то уж? :D

#include<iostream>
#include<string>

int main()
{
    bool flag = false;
    int a;
    std::cin >> a;
    for (int i = 0; i < 10; i++)
    {
        int count = 0, a1 = a;
        while (a1>0)
        {
            if (a1 % 10 == i) count++;
            if (count > 1)
            {
                flag = true;
                break;
            }
            a1 = (a1 - (a1 % 10)) / 10;
        }
    }
    if (flag) std::cout << "YES"; 
    else std::cout << "NO";
    system("pause");
    return 0;
}

Никита, код рабочий. #include <string> — лишнее.

По эффективности хуже, чем исходный вариант программы: количество выполнения тела внутреннего цикла while в самом плохом случае равно N * 10. Где N — количество цифр в числе.

Для исходной программы это количество равно N / 2 * (N - N % 2).

Для варианта Croessmah количество выполений тела цикла равно N.

Ещё варианты будут?

Для варианта Croessmah количество выполений тела цикла равно N.
Ещё варианты будут?

такой же, только без массива:

bool eq(int num_)
{
    int mask = 0;
    int num = abs(num_);
    while( num != 0 ){
        unsigned int d = num%10;
        unsigned int n_mask = (1 << d);
        if( n_mask & mask ){
            return true;
        }
        mask |= n_mask;
        num /= 10;
    }
    return false;
}

М-да... не густо. Своей пассивностью удивили, в первую очередь, новички. В комментах к урокам регулярно появляются пожелания увидеть «упражнения», «домашние задания» и пр. Вот вам упражнение. Есть где и покодить и мозгами пошевелить.

В заключение приведу свой вариант решения. Он очень похож на вариант от Croessmah, но без массива. В качестве флагов используются биты целой переменной.

#include <iostream>

using namespace std;

bool dubdigit(int num) {
    int digit;
    int flags = 0;
    int mask;
    while (num > 0) {
        digit = num % 10;
        num /= 10;
        mask = 1 << digit;
        if ((flags & mask) != 0) {
            return true;
        }
        flags |= mask;
    }
    return false;
}

int main() {
    int number;

    cout << "Nubmer: ";
    cin >> number;

    if (dubdigit(number))
        cout << "YES";
    else
        cout << "NO";
    cout << endl;
    system("pause");
    return 0;
}

А вообще разминка для мозгов кому-то интересна? Или можно не париться?

UPD. Пока писал сообщение, Croessmah залил свой второй вариант решения, совпадающий с моим.

А вообще разминка для мозгов кому-то интересна?

Ресурс не популярный, так что посетителей тоже не много.
Постоянных — вообще единицы.
Соответственно интересно это,
в крайнем случае, нескольким лицам.

Или можно не париться?

Думаю, можно не париться.
Хотя если вам интересно, то можно всё :)

Пока писал сообщение, Croessmah залил свой второй вариант решения, совпадающий с моим

Ну, это достаточно популярное решение данной задачи,
так что не думаю, что это можно назвать моим или Вашим решением.

Можно париться, пожалуйста. Вы занимаетесь очень полезным делом, по крайней мере, для людей вроде меня. Не всем по..., не верьте.
Постараюсь вскоре предложить свой вариант. Хотя не уверен, что моя идея намного лучше популярного решения.
Спасибо вам!

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.