title: Algorithm to find Lucky Numbers
body: <p>I came across this question.A number is called lucky if the sum of its digits, as well as the sum of the squares of its digits is a prime number. How many numbers between A and B are lucky? 1 &lt;= A &lt;= B &lt;= 10<sup>18</sup>. I tried this.<br><br></p>
  
  <ul>
  <li>First I generated all possible primes between 1 and the number that could be resulted by summing the squares (81 *18 = 1458).<br><br></li>
  <li>I read in A and B  find out maximum number that could be generated by summing the digits If B is a 2 digit number ( the max number is 18 generated by 99).<br><br></li>
  <li>For each prime number between  1 an max number. I applied integer partition algorithm.<br><br></li>
  <li>For each possible partition I checked whether their sum of squares of their digits form prime. If so the possible permutations of that partition are generated and if they lie with in range they are lucky numbers.<br></li>
  </ul>
  
  <hr>
  
  <p>This is the implementation:</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  #include&lt;malloc.h&gt;
  #include&lt;math.h&gt;
  #include &lt;stdlib.h&gt;
  #include&lt;string.h&gt;
  long long luckynumbers;
  int primelist[1500];
  
  int checklucky(long long possible,long long a,long long b){
      int prime =0;
      while(possible&gt;0){
              prime+=pow((possible%10),(float)2);
              possible/=10;
      }
          if(primelist[prime]) return 1;
          else return 0;
  }
  long long getmax(int numdigits){
          if(numdigits == 0) return 1; 
          long long maxnum =10;
               while(numdigits&gt;1){
                          maxnum = maxnum *10;
                          numdigits-=1;
               }
           return maxnum; 
  
  }
  void permuteandcheck(char *topermute,int d,long long a,long long b,int digits){
      if(d == strlen(topermute)){
              long long possible=atoll(topermute);
              if(possible &gt;= getmax(strlen(topermute)-1)){  // to skip the case of getting already read numbers like 21 and 021(permuted-210
  
                  if(possible &gt;= a &amp;&amp; possible &lt;= b){
  
                      luckynumbers++;
                  }
              }
      }
      else{
          char lastswap ='\0';
          int i;
          char temp;
          for(i=d;i&lt;strlen(topermute);i++){
              if(lastswap == topermute[i])
                  continue;
              else
                  lastswap = topermute[i];
              temp = topermute[d];
              topermute[d] = topermute[i];
              topermute[i] = temp;
  
              permuteandcheck(topermute,d+1,a,b,digits);
  
              temp = topermute[d];
              topermute[d] = topermute[i];
              topermute[i] = temp;
          }
  
      }
  
  }
  
  
  void findlucky(long long possible,long long a,long long b,int digits){
      int i =0;
      if(checklucky(possible,a,b)){
          char topermute[18];
          sprintf(topermute,"%lld",possible);
          permuteandcheck(topermute,0,a,b,digits);
      }
  }
  
  
  void  partitiongenerator(int k,int n,int numdigits,long long  possible,long long a,long long b,int digits){
      if(k &gt; n || numdigits &gt; digits-1 || k &gt; 9) return;
      if(k == n){
  
          possible+=(k*getmax(numdigits));
  
          findlucky(possible,a,b,digits);
          return;
      }
      partitiongenerator(k,n-k,numdigits+1,(possible + k*getmax(numdigits)),a,b,digits);
      partitiongenerator(k+1,n,numdigits,possible,a,b,digits);
  
  }
  
  
  void calcluckynumbers(long long a,long long b){
      int i;
      int numdigits = 0;
      long long temp = b;
      while(temp &gt; 0){
          numdigits++;
          temp/=10;
      }
  
      long long maxnum =getmax(numdigits)-1;
      int maxprime=0,minprime =0;
      temp = maxnum;
      while(temp&gt;0){
          maxprime+=(temp%10);
          temp/=10;
      }
      int start = 2;
      for(;start &lt;= maxprime ;start++){
              if(primelist[start]) {
                  partitiongenerator(0,start,0,0,a,b,numdigits);
              }
      }   
  
  }   
  void generateprime(){
      int i = 0;
      for(i=0;i&lt;1500;i++)
          primelist[i] = 1;
      primelist[0] = 0;
      primelist[1] = 0;
      int candidate = 2;
      int topCandidate = 1499;
      int thisFactor = 2;
      while(thisFactor * thisFactor &lt;= topCandidate){
          int  mark = thisFactor + thisFactor;
          while(mark &lt;= topCandidate){
              *(primelist + mark) = 0;
              mark += thisFactor;
          }
          thisFactor++;
          while(thisFactor &lt;= topCandidate &amp;&amp; *(primelist+thisFactor) == 0) thisFactor++;
      }
  
  }
  int main(){
          char input[100];
          int cases=0,casedone=0;
      long long a,b;
      generateprime();
          fscanf(stdin,"%d",&amp;cases);
          while(casedone &lt; cases){
          luckynumbers = 0;
                  fscanf(stdin,"%lld %lld",&amp;a,&amp;b);
          int i =0;
                 calcluckynumbers(a,b);
                  casedone++;
          }
  
  }
  </code></pre>
  
  <hr>
  
  <p>The algorithm is too slow. I think the answer can be found based on the property of numbers.Kindly share your thoughts. Thank you.</p>