将[N]下的所有幸运数字添加到向量的算法?

时间:2015-11-12 16:22:35

标签: c++ algorithm loops

幸运数字被定义为正整数,其十进制表示仅包含幸运数字4和7.例如,数字47,744,4是幸运的,5,17,467不是。

现在,假设我想将给定整数[N]下的所有Lucky Number添加到向量中,而不使用递归。为简单起见,设N = 1000。

我提出了一种方法,只需检查[N]下所有数字的每个数字,分别为1位数字,2位数字等制作单独的数字。

for(int number=0;number<10;number++) {if(((number%10==4)||(number%10==7))) {lucky.push_back(number);}} //1 Digit Lucky Numbers
for(int number=10;number<100;number++) {if(((number%10==4)||(number%10==7))&&(((number/10)%10==7)||((number/10)%10==4))) {lucky.push_back(number);}} //2 Digit Lucky Numbers
for(int number=100;number<1000;number++) {if(((number%10==4)||(number%10==7))&&(((number/10)%10==7)||((number/10)%10==4))&&(((number/100)%10==7)||((number/100)%10==4))) {lucky.push_back(number);}} //3 Digit Lucky Numbers
for(int number=1000;number<10000;number++) {if(((number%10==4)||(number%10==7))&&(((number/10)%10==7)||((number/10)%10==4))&&(((number/100)%10==7)||((number/100)%10==4))&&(((number/1000)%10==7)||((number/1000)%10==4))) {lucky.push_back(number);}} //4 Digit Lucky Numbers

我当时认为这可以大致转换成这些内容,但我无法想出具体要做的事情。

for(number;number<10*itr_counter;number++)
    {
    if(((number%10*itr_counter==4)||(number%10*itr_counter==7))) {lucky.push_back(number);}
    itr_counter*=10;
    }

我基本上想要通过取模10并检查数字是4还是7来检查所有1位数的每个数字。 类似地,对于由X个数字组成的数字,我采用模数并将数字除以10,100,依此类推以检查4或7。

这是解决上述问题的好方法吗?此外,有人可以帮我优化第一块代码,使其更小更高效吗?第二段代码的某些方面可行。

7 个答案:

答案 0 :(得分:1)

// Use a D bit number as a proxy for a D digit number
// Then use L=2^D as a proxy for D in a loop through required values of D
// Notice D is only implied, we don't need to actually store it.
for (unsigned L=2; ; L*=2)
{
   // Loop through all D bit numbers (which happen to be all numbers less than L
   for (unsigned N=0; N<L; ++N)
   {
      // Convert that D bit number into a D digit number
      unsigned long long X = 0;
      // Loop through the bits of N converting to digits
      for ( unsigned B=L; (B>>=1)>0; )
      {
         X = X * 10 + 4;
         if ( B & N ) X += 3;  // change the 4 to a 7.
      }
      if ( X > MAX_NUMBER )
         return;  // break out of two levels of loop
      lucky.push_back( X );
   }
}

对于这么简单的任务来说,这看起来过于棘手。但是如果MAX_NUMBER非常大,那么这种方法比测试数字是否幸运还要好得多。

还要注意这个方法在代码流程中的一个尴尬点(在两个循环级别内)完成(检测完成)。在严肃的编程中,这种事情很常见。我在这种情况下的压倒性优先选择是将整个嵌套循环放入一个函数中,这样我就可以使用函数中的return作为break两级循环的简单方法。使用return可能会严重影响结构化编程狂热分子。您可以通过将done标志混合到每个循环的控件中来完成相同的流控制。这种方法让我感到冒犯,因为return冒犯了结构化编程狂热者。

关于两个棘手循环的更多细节:

从概念上讲,我们有D并且我们希望它从1开始并计数直到我们点击返回指令并且我们想要计算L=1<<D意味着其唯一设置位在位置D的数字。但是我们跳过完全D并直接计算L.

然后我们希望最里面的循环有一个位数E,并在概念上倒计数D下面的位位置:

for (E=D-1; E>=0; --E)

我们希望同样计算B=1<<E作为唯一设置位在位置E的数字。但是我们再次没有D而且我们不需要E,我们可以计算B直接

答案 1 :(得分:0)

也许您可以制作散点图图并使用Gradient descendant算法和machine learning来估算您的值?

答案 2 :(得分:0)

考虑到您没有扫描列表以查找集合中的幸运数字,而是生成包含0到N之间包含这些数字的所有可能数字组合的列表;使用简单的函数简单地生成所有幸运数字不是更有效吗?

答案 3 :(得分:0)

由于您没有解析确认数字是幸运数字的列表,因此您最好使用函数构建幸运数字的列表/向量。

解决这个问题的一种方法是将二进制数从0计算到你想要的给定数字。对于n=1000 0b111 = 7,然后将每个0替换为4,每个1替换为7.即0b101 = 747。然后,您可以轻松总结生成的矢量。

关于将其验证为幸运数字的迭代方法,我将在pseduocode中创建类似以下的函数:

while number > 0:
   lastDigit = number % 10
   if lastDigit != 4 and lastDigit != 7
       return false
   number = number / 10

return true

答案 4 :(得分:0)

#include <iostream>
#include <vector>

bool is_lucky(int check_num)
{
while(check_num!=0)
    {
    if((check_num%10!=4)&&(check_num%10!=7))
        {
        return false;
        }
    check_num/=10;
    }
return true;
}

int main()
{
std::vector <long long> lucky;
for(int in_num=1;in_num<1000;in_num++)
    {
    if(is_lucky(in_num))
        {
        lucky.push_back(in_num);
        }
    }
}

我终于能够使这个is_lucky函数仍然不是执行任务的最有效方法,但似乎是完成任务的最短方式。

答案 5 :(得分:0)

类似于Sieve of Eratosthenes的解决方案可行,但它远非聪明。

考虑将每个值放在一个有序向量中:第n个元素将由前面的一个元素加上一个最终的&#39; 4&#39;组成。 o&#39; 7&#39;。记住这一点,你可以生成数字,而不是检查它们。

这是

的想法
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

#define MAX_NUMBER 1000

int main()
{
    std::vector<int> lucky_numbers(0);

    if (lucky_numbers.size () == 0)
    {
        if (4 < MAX_NUMBER)
            lucky_numbers.push_back (4);
        if (7 < MAX_NUMBER)
            lucky_numbers.push_back (7);
    }

    bool exit = false;

    while (!exit)
    {
        int size = lucky_numbers.size ();

        for (int i = 0 ; i < size ; i++)
        {
            int new_lucky_number = lucky_numbers[i] * 10 + 4;
            if (new_lucky_number < MAX_NUMBER &&
                std::find(lucky_numbers.begin(), lucky_numbers.end(), new_lucky_number) == lucky_numbers.end() )
            {
                lucky_numbers.push_back (new_lucky_number);
            }
            else if (new_lucky_number >= MAX_NUMBER)
            {
                exit = true;
                break;
            }

            new_lucky_number = lucky_numbers[i] * 10 + 7;
            if (new_lucky_number < MAX_NUMBER &&
                std::find(lucky_numbers.begin(), lucky_numbers.end(), new_lucky_number) == lucky_numbers.end() )
            {
                lucky_numbers.push_back (new_lucky_number);
            }
            else if (new_lucky_number >= MAX_NUMBER)
            {
                exit = true;
                break;
            }
        }
    }

    int size = lucky_numbers.size ();

    for (int i = 0 ; i < size ; i++)
        std::cout << lucky_numbers[i] << std::endl;
}

根据您的问题的条件,您可以优化使用std :: find并使其更快。

<强>更新

讨论解决方案后,这里是增强版。检查是内联的,但避免找到重新启动。

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

#define MAX_NUMBER 1000

int main()
{
    std::vector<int> lucky_numbers(0);
    std::vector<int>::iterator it;

    if (lucky_numbers.size () == 0)
    {
        if (4 < MAX_NUMBER)
            lucky_numbers.push_back (4);
        if (7 < MAX_NUMBER)
            lucky_numbers.push_back (7);
    }

    for (int i = 0 ; ; i++)
    {
        int new_lucky_number = lucky_numbers[i] * 10 + 4;

        if (new_lucky_number < MAX_NUMBER)
            lucky_numbers.push_back (new_lucky_number);
        else
            break;

        new_lucky_number = lucky_numbers[i] * 10 + 7;

        if (new_lucky_number < MAX_NUMBER)
            lucky_numbers.push_back (new_lucky_number);
        else
            break;
    }

    for (int i = 0 ; i < lucky_numbers.size () ; i++)
        std::cout << lucky_numbers[i] << std::endl;
}

答案 6 :(得分:0)

这个答案取决于Ottavio Campana的答案,但展示了良好的软件工程原理,它将工作的每个不同元素和设计决策的每个元素保存在代码中的一个位置(请参阅我的评论在那个早先的回答中):

// Anywhere a type is a design decision, rather than an obvious choice, use a typedef
typedef unsigned long long number;
typedef std::vector<number> container;

// A function is usually the best way to centralize work.
// If the parameter passing cost exceeds the work, use an inline function
// and rely on the optimizer to sort it out
inline bool push_number(container& c, number n, number m)
{
   if (n>m) return false;
   c.push_back(n);
   return true;
}

...

number n=0;
unsigned i=0;
container c;
while ( push_number(c,n+4,MAX_NUMBER) && push_number(c,n+7, MAX_NUMBER) )
{
   n = 10 * c[i++];
}

请注意,与max相比的>操作在代码中显示为 ONCE 。 4和7各自在代码中显示 ONCE 。乘以10会在代码中出现 ONCE

当你遇到更复杂的问题时,组织这些事情的额外努力每次出现都会成为草率编程和真实软件工程之间的最大区别。

如果MAX_NUMBER来自#define或任何全局位置,那么将它传递两次比在函数内直接使用它更有意义。但我反对#define这样的事情并且几乎同样反对全局变量。所以我不想在假设最大数量是全局可见的情况下进行编码。通过它并不好,但它并不是很糟糕。在一个真实的项目中,当你发现自己过度传递像cMAX_NUMBER这样的东西时,这暗示了工作应该由具有这些东西作为成员变量的类的成员函数来完成。