简单的练习和困难的解决方案 C++

easy exercise with difficult solution C++

所以,首先,这个 SEEMS 就像您第一次开始学习编程时在学校接受的练习之一。 Weeeeell 事实证明不止于此。

主要练习相当简单,任何人都可以解决:

编辑:我掌握了原始(翻译)声明:

为一个非递归函数编写两个实现,该函数有一个参数(n = 最多 9 位的自然数),return通过将 n 的第一个数字重新定位到末尾得到的数字的数量。例如,如果 n 为 4273,则函数应 return 2734。 C1) 你可以使用循环。 C2) 不允许使用循环。

好的,首先很简单。

    long function(long n)
    {
        long newNumber = 0, p = 1;

        while(n>9)
        {
            newNumber = n%10 * p + newNumber;
            n = n/10;
            p = p*10;
        }

        return newNumber*10+n;
    }

现在不使用任何循环来做同样的事情。 no while, for, do while, 等等。你不知道这个数字有多长,可能是3位数,我可能是9。而且整个工作必须由一个函数单独完成。

现在,当然,一个简单的解决方案也是一个可怕的解决方案是编写类似

的内容
    if(n<100)
        return n%10*10+n/10;
    else
        if(n<1000)
            return n%100*10+n/100;
        else
            if...
    ...
    ...
    ...

但这不是最理想的代码段。还有其他干净的方法吗?到目前为止,我问过的人都不知道任何其他方式。

还有一件事。这应该是初学者可以解决的(我在帮助我的一个伙伴解决他的一个练习时遇到了这个问题)所以使用一些奇特的库以某种方式帮助初学者永远不会知道不应该是一个有效的解决方案(但是我很好奇所有的想法)。

此外,我知道您可以使用以下公式计算一个数字的位数:

|日志(n)| + 1 = ln(n) / ln(10) + 1 可以在 C++ 中使用如下:

    long function(long n)
    {
            int k; // number of digits of n

            k = (int) (ln(n) / ln(10)) + 1; // applying the formula
            long p = pow(10, k-1);
            return n%p * 10 + n/p;
    }

但我不记得我在高中时曾被教导过 C++ 中的 ln 函数,他们也没有。那么...还有其他适合初学者的方法吗?

约束列表:

编辑:所以与此同时我被告知提出这个问题的解决方案是使用对数的解决方案......这很奇怪,因为他们的学生从未在 C++ 中使用过它。我的猜测是他们搞砸了声明,这就是他们的 "salvation excuse".

使用recursion。这是一些未经测试的代码:

long f(long n, long base) 
{
    if(n <= 9)
        return n;    // last 'iteration'
    else
        return (base * (n % 10)) + f(n / 10, 10 * base);
}

....
f(1234, 10);

编辑 1:更改为不使用循环。 编辑 2:此解决方案不再满足 OP 设置的要求。但是,我会在这里留下我的答案,以供未来遇到此问题的读者使用,他们可能会在他们的解决方案中使用字符串。

#include <iostream>
#include <string>

int main() {
    long testNum = 0;
    long newNum;
    std::cout << "Enter a number: ";
    std::cin >> testNum;

    std::string stringFromLong;

    stringFromLong = std::to_string(testNum);
    char tempChar = stringFromLong[0];

    std::string newString = stringFromLong.substr(1, stringFromLong.length() - 1) + tempChar;

    newNum = std::stol(newString);
    std::cout << newNum << std::endl;
    return 0;
}

这将接收一个数字并将其转换为字符串。它们会将字符串的第一个字符保存在临时变量中。一个新字符串由我们的原始字符串(从第二个字符开始到最后一个字符)加上我们放在末尾的临时字符组成。然后它使用 std::stol() 将我们的字符串转换为长整数以供输出。

如果你被允许使用字符串,你就可以做这样的事情。它使用字符串基本上将数字视为向量,使这项任务变得微不足道。

但是,就目前而言,这是不允许的(从问题的编辑 #3 开始,我在编写和测试此解决方案时没有看到)。但是,我会 post 在这里,以防将来有人被引导到这个问题,并且不限于不使用字符串。

#include <string>
#include <cstdlib>

long firstDigitToEnd(long n) {
    bool neg = (n < 0);                  // Preserve signed-ness.
    if (neg) { n = labs(n); }            // Obtain absolute value, for convenience.

    std::string num = std::to_string(n); // Convert number to string.

    char first = num[0];                 // Obtain first digit.
    num.erase(0, 1);                     // Erase first digit, shift rest forwards.
    num.push_back(first);                // Append first digit to end.

    // And we're done.  Convert string back to number, restore signed-ness.
    return (neg ? -(std::stol(num)) : std::stol(num));
}

// -----

// Testing code.

#include <iostream>
#include <limits>

void readCin(long& l);

int main() {
    long n = 0;

    do {
        if (n) {
            std::cout << "Result: " << firstDigitToEnd(n) << std::endl;
        }

        std::cout << "Input number, or 0 to exit: ";
        readCin(n);
    } while (n);

    std::cout << "...And we're gone." << std::endl;
}

// Read a number, or clear the buffer if non-number is entered.
void readCin(long& l) {
    using std::cin;

    cin >> l;
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    if (cin.fail()) {
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        l = 0;
    }
}

查看实际效果 here

这是一种使用 std::log10 和 std::pow 的解决方案(需要 #include <cmath>)。

long func(long in) {
    long base = std::pow(10, (int)std::log10(in));
    long left_most_num = in / base;
    long body = in - left_most_num * base;
    return body * 10 + left_most_num;
}

由于我们在编译时知道 INT_MAX 的约束,即使丑陋也是微不足道的。

if(x > 999999999)
   ndigits =  9;
else if(x > 99999999)
   ndigits = 8;

等; 然后你可以使用 ndigits 和乘法。对 10 的相关幂进行除法和取模以获得您想要的结果。

但是,如果 x 是无界的,那么在不使用某种形式的循环的情况下,本质上无法知道它的大小。