Рубрики
Без рубрики

Современная проблема Cpp на мобильных телефонах с большим количеством номеров

Привет! Я Ксавье Жувено, и вот шестая часть длинной серии, посвященной современным вызовам C++. I… С тегами android, cpp, java, challenge.

Привет! Я Ксавье Жувено, и вот шестая часть длинной серии о Современный вызов C++ . В этой статье я собираюсь объяснить, как я решил шестую проблему на C++ и как я интегрировал решение в проект Android.

Цель этой шестой задачи проста. Мы должны, чтобы печатались все все обильные числа и их обилие, вплоть до предела, введенного пользователем. Решение будет вычислено на C++, а интерфейс для получения пользовательского ввода и отображения результата будет обрабатываться с помощью Android Studio Framework.

Я призываю вас прочитать предыдущую часть этой серии , так как мы собираемся продолжить нашу программу, созданную в ней.

Что такое обильное число?

Избыточное число – это число, для которого сумма его собственных делителей больше, чем само число. Величина, на которую сумма превышает число, и есть изобилие.

Например, число 12 может быть разделен на 1 , 2 , 3 , 4 , 6 и сам по себе. Таким образом, его собственные делители являются 1 , 2 , 3 , 4 , 6 , и если вы их суммируете, то получаете 1+2+3+4+6 который больше, чем 12.So 12 – это обильное число с обилием 16-12 .

Решение на C++

Прежде всего, мы должны быть в состоянии решить проблему с помощью C++.Для этого мы собираемся реализовать 3 функции. 🙂

Первый из них позволяет нам получить сумму всех делителей числа.

static constexpr unsigned int getSumOfDivisors(unsigned int number)
{
    unsigned int sumOfDivisors{0};
    for(auto i = 1; i < number; ++i)
    {
        if(number % i == 0)
        {
            sumOfDivisors += i;
        }
    }
    return sumOfDivisors;
}

Вторая функция позволяет нам узнать, является ли число избыточным числом, и получить изобилие, если это избыточное число. Эта функция вернет std::optional , который будет содержать значение изобилия, или std::nullptr , если ввод не является избыточным числом.

std::optional getAbundance(unsigned int number)
{
    const auto sum = getSumOfDivisors(number);
    if(number < sum)
    {
        return {static_cast(sum - number)};
    }
    return std::nullopt;
}

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

std::vector getAllAbundantNumbersUpTo(unsigned int upperLimit)
{
    std::vector results;
    for(auto i = 1; i <= upperLimit; ++i)
    {
        auto potentialAbundantNumber = i;
        auto abundance = getAbundance(i);
        if(abundance.has_value())
        {
            results.emplace_back(std::make_pair(std::move(potentialAbundantNumber), std::move(*abundance)));
        }
    }
        return results;
}

С помощью этих трех функций мы можем решить проблему без каких-либо проблем 😉

Пользовательский интерфейс на Android Studio

Пользовательский интерфейс для этой проблемы похож на интерфейс предыдущей проблемы . Поэтому я не буду вдаваться в подробности, но я призываю вас заглянуть в мой пост в блоге об этом . 😉

Но даже если интерфейс проблемы похож на две предыдущие проблемы, я хочу поговорить с вами о пользовательском интерфейсе, который мне пришлось создать. Действительно, теперь, когда в нашем приложении решены 6 проблем, необходимость много раз нажимать на кнопку “Далее”, чтобы перейти к последней проблеме, занимает много времени и будет увеличиваться каждый раз, когда мы добавляем новое решение проблемы.

Чтобы избежать этого, мы создали пользовательский интерфейс, похожий на меню, в котором вы можете нажать на проблему, к которой хотите перейти. Для этого мы создали новый пользовательский интерфейс с 6 кнопками, открывающими один проблемный интерфейс.

Вот методы, которые я использовал:

void addButton(@IdRes int id, String text)
{
    RelativeLayout ll = findViewById(R.id.buttons);

    RelativeLayout.LayoutParams newParams = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);

    Button b = new Button(this);
    b.setId(id);
    b.setText(text);
    b.setOnClickListener(this);

    newParams.addRule (RelativeLayout.ALIGN_LEFT);
    b.setLayoutParams(newParams);
    ll.addView(b);
}

void addButton(@IdRes int id, String text, @IdRes int idOfLeftElement)
{
    RelativeLayout ll = findViewById(R.id.buttons);

    RelativeLayout.LayoutParams newParams = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);

    Button b = new Button(this);
    b.setId(id);
    b.setText(text);
    b.setOnClickListener(this);

    newParams.addRule (RelativeLayout.RIGHT_OF, idOfLeftElement);
    b.setLayoutParams(newParams);
    ll.addView(b);
}

void addButtonBelow(@IdRes int id, String text, @IdRes int idOfElementOnTop)
{
    RelativeLayout ll = findViewById(R.id.buttons);

    RelativeLayout.LayoutParams newParams = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);

    Button b = new Button(this);
    b.setId(id);
    b.setText(text);
    b.setOnClickListener(this);

    newParams.addRule (RelativeLayout.BELOW, idOfElementOnTop);
    b.setLayoutParams(newParams);
    ll.addView(b);
}

void addButtonBelow(@IdRes int id, String text, @IdRes int idOfLeftElement, @IdRes int idOfElementOnTop)
{
    RelativeLayout ll = findViewById(R.id.buttons);

    RelativeLayout.LayoutParams newParams = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);

    Button b = new Button(this);
    b.setId(id);
    b.setText(text);
    b.setOnClickListener(this);

    newParams.addRule (RelativeLayout.RIGHT_OF, idOfLeftElement);
    newParams.addRule (RelativeLayout.BELOW, idOfElementOnTop);
    b.setLayoutParams(newParams);
    ll.addView(b);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    addButton(R.id.menu_button_1, "1");
    addButton(R.id.menu_button_2, "2", R.id.menu_button_1);
    addButton(R.id.menu_button_3, "3", R.id.menu_button_2);
    addButton(R.id.menu_button_4, "4", R.id.menu_button_3);
    addButtonBelow(R.id.menu_button_5, "5", R.id.menu_button_1);
    addButtonBelow(R.id.menu_button_6, "6", R.id.menu_button_5, R.id.menu_button_2);
}

public void onClick(View v) {
    switch (v.getId())
    {
        case R.id.menu_button_1:
            startActivity(new Intent(this, Problem_1.class));
            break;
        case R.id.menu_button_2:
            startActivity(new Intent(this, Problem_2.class));
            break;
        case R.id.menu_button_3:
            startActivity(new Intent(this, Problem_3.class));
            break;
        case R.id.menu_button_4:
            startActivity(new Intent(this, Problem_4.class));
            break;
        case R.id.menu_button_5:
            startActivity(new Intent(this, Problem_5.class));
            break;
        case R.id.menu_button_6:
            startActivity(new Intent(this, Problem_6.class));
            break;
        default:
            new AssertionError("Unknown menu button.");
            break;
    }
}

Не волнуйтесь, я собираюсь объяснить этот код. 😉

Прежде всего, кнопка добавить и добавить кнопку ниже методы создайте кнопку в пользовательском интерфейсе с правильным текстом и в правильном положении, используя RelativeLayout , размещенный в пользовательском интерфейсе в определении xml пользовательского интерфейса.

Затем у нас есть метод onCreate , который вызывает ранее определенные методы для добавления кнопок с правильными параметрами.

И, наконец, метод onClick вызывается при нажатии на кнопку и открывает нужное действие в зависимости от нажатой кнопки. Это подразумевает, что класс реализует class View.OnClickListener . 😉

И таким образом, мы получаем меню, позволяющее нам перейти непосредственно к нужной нам проблеме.

Использование собственного кода C++

Привязка пользовательского интерфейса к коду C++ очень похожа на предыдущую проблему.

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_themoderncppchallenge_Problem_16_AbundantNumbersUpTo(JNIEnv *env, jobject thiz,
                                                                      jint user_input) {
    const auto& result = getAllAbundantNumbersUpTo(user_input);
    std::string text;
    for(const auto& abundance : result) {
        text += '(' + std::to_string(abundance.first) + ", " + std::to_string(abundance.second) + "), ";
    }
    // Removes the last ", "
    text.pop_back();
    text.pop_back();
    return env->NewStringUTF(text.c_str());
}

Мы начинаем с получения результатов из ранее определенной функции и преобразуем эти данные в string перед отправкой их вызывающей стороне.

Вывод

Вот так ! Теперь у нас есть приложение, которое может решить первые шесть задач Современный вызов C++ .

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

Спасибо всем вам за чтение этой статьи, И до моей следующей статьи желаю вам прекрасного дня 😉

Интересные ссылки

Оригинал: “https://dev.to/10xlearner/the-modern-cpp-challenge-on-mobile-abundant-numbers-30a1”