Finding a Specific Digit of a Number - c++

I'm trying to find the nth digit of an integer of an arbitrary length. I was going to convert the integer to a string and use the character at index n...
char Digit = itoa(Number).at(n);
...But then I realized the itoa function isn't standard. Is there any other way to do this?

(number/intPower(10, n))%10
just define the function intPower.

You can also use the % operator and / for integer division in a loop. (Given integer n >= 0, n % 10 gives the units digit, and n / 10 chops off the units digit.)

number = 123456789
n = 5
tmp1 = (int)(number / 10^n); // tmp1 = 12345
tmp2 = ((int)(tmp1/10))*10; // tmp2 = 12340
digit = tmp1 - tmp2; // digit = 5

You can use ostringstream to convert to a text string, but
a function along the lines of:
char nthDigit(unsigned v, int n)
{
while ( n > 0 ) {
v /= 10;
-- n;
}
return "0123456789"[v % 10];
}
should do the trick with a lot less complications. (For
starters, it handles the case where n is greater than the number
of digits correctly.)
--
James Kanze

Itoa is in stdlib.h.
You can also use an alternative itoa:
Alternative to itoa() for converting integer to string C++?
or
ANSI C, integer to string without variadic functions

It is also possible to avoid conversion to string by means of the function log10, int cmath, which returns the 10th-base logarithm of a number (roughly its length if it were a string):
unsigned int getIntLength(int x)
{
if ( x == 0 )
return 1;
else return std::log10( std::abs( x ) ) +1;
}
char getCharFromInt(int n, int x)
{
char toret = 0;
x = std::abs( x );
n = getIntLength( x ) - n -1;
for(; n >= 0; --n) {
toret = x % 10;
x /= 10;
}
return '0' + toret;
}
I have tested it, and works perfectly well (negative numbers are a special case). Also, it must be taken into account that, in order to find tthe nth element, you have to "walk" backwards in the loop, subtracting from the total int length.
Hope this helps.

A direct answer is:
char Digit = 48 + ((int)(Number/pow(10,N)) % 10 );
You should include the <math> library

const char digit = '0' + number.at(n);
Assuming number.at(n) returns a decimal digit in the range 0...9, that is.

A more general approach:
template<int base>
int nth_digit(int value, int digit)
{
return (value / (int)pow((double)base, digit)) % base;
}
Just lets you do the same thing for different base numbers (e.g. 16, 32, 64, etc.).

An alternative to itoa is the std::to_string method. So, you could simply do:
char digit = to_string(number)[index]

Related

How can I use logarithms to get the opposite of power?

I was never good at maths in school and I realized that I actually need the opposite of pow(base, exponent) functions which powers some number by some factor like 2 ^ 4 = 16
Searching for answers I found that logarithm log() should be the opposite of power.
Now, I've found that to write e.g. "log 2 of 32" would in code look like log(32) / log(2)... but how do you translate this following problem into logarithm?
I'm going to write a quick C program to print index table where all alphabetical characters are going to be printed assigned to each index starting from 0 to 26 ^ DIGITS.
Assuming DIGITS are set to 1, table will only be of size 26 (the length of alphabet from A to Z) in format index[0] = A, index[1] = B, ... ... index[25] = Z.
The count of DIGITS gives 26 ^ DIGITS combinations.
Now, I have this code already written:
#include <stdio.h>
#include <ctype.h>
#include <math.h>
unsigned int letterToIndex(char c);
char indexToLetter(unsigned int index);
int main(void)
{
printf("Printing Index table:\n\n");
const int DIGITS = 2;
const int ALPHABSIZE = 26;
int currentIdx = 0; // current index
const int endIndex = pow(ALPHABSIZE, DIGITS);
// this should be
//double bit5 = log(32) / log(2);
//printf("log(32) / log(2) AKA bit^5 should be: %f", bit5);
while (currentIdx < endIndex)
{
printf("index[%i] = ", currentIdx);
/*for (int i = 0; i < DIGITS; ++i)
{
//float logarithm = log( (currentIdx / ALPHABSIZE) % ALPHABSIZE ) / log(DIGITS);
float logarithm = log( currentIdx % ALPHABSIZE ) / log(DIGITS);
printf("%c", indexToLetter( (int) logarithm ));
}*/
// letter
//unsigned int idxLetter = letterToIndex(i) * ALPHABSIZE + letterToIndex(i+1);
///////////////////////////////////////////////////////////////////////////////
// I have an obvious pattern here vv
// here I print only 2 digits hard-coded
// prints the 1st digit
printf("%c", indexToLetter( (currentIdx / ALPHABSIZE) % ALPHABSIZE ));
// prints the 2nd digit
printf("%c", indexToLetter( currentIdx % ALPHABSIZE ));
// obvious pattern ^^
//////////////////////////////////////////////////////////////////////////////
printf("\n");
currentIdx++;
}
// if DIGITS are only 1 sized:
// index[0] = A
// index[1] = B
// index[2] = C
// index[3] = D
// index[4] = E
// ... ... ...
// index[25] = Z
// DIGITS having size of 2:
// index[0] = AA
// index[25] = AZ
// index[26] = BA = index[ 1 * 26 + 0 ] = index[26]
// index[30] = BE = index[ 1 * 26 + 4 ] = index[30]
// ... ... ...
// index[107] = ED = index[ 4 * 26 + 3 ] = index[107]
return 0;
}
// maps the ASCII range from 'A' = 0 to 'Z' = 25
unsigned int letterToIndex(char c)
{
return toupper(c) - 'A';
}
// get any letter from 0 to 25: from 'A' to 'Z'
char indexToLetter(unsigned int index)
{
return toupper(index + 65);
}
I've commented out the for loop inside the main (inside the while block), and this time hardcoded to printf currentIdx's first digit and then its second digit at each iteration in the while loop.
But it strikes me like it's asking for a logarithm... How can I automate this in the for loop? Instead of having two printf lines, I'm pretty much convinced these two lines:
printf("%c", indexToLetter( (currentIdx / ALPHABSIZE) % ALPHABSIZE ));
printf("%c", indexToLetter( currentIdx % ALPHABSIZE ));
could be put into one line with the right (maybe logarithm?) solution. If it was DIGITS size 1, only the 2nd line would apply. DIGITS of size 3 requires opposite of power to 3. It's clearly power to DIGITS.
But what to make out of this pattern in a loop? Let's say const int DIGITS (that's currently set to 2) could be changed to be higher. How to make it dynamic so that it'll combine the alphabet for every digit?
You can start with pow(ALPHABSIZE, DIGITS - 1) and use integer division to get each place value/table index. On each loop you successively reduce by a factor of ALPHABSIZE down to 1. This lets you output left to right.
Logarithms are not necessary to compute here. To compute an integer logarithm you could nevertheless just count the number of passes through a while/for loop in the same fashion.

Problem with Reversing Large Integers On Leetcode?

I was working on this problem from Leetcode where it has this requirement of reversing numbers whilst staying within the +/-2^31 range. I checked out other solutions made for this problem, and from there created my own solution to it. It worked successfully for numbers ranging from 10 to less than 99,999,999. Going more than that(when trying to submit the code to move to the next question) would throw an error saying:
"Line 17: Char 23: runtime error: signed integer overflow: 445600005 * 10 cannot be represented in type 'int' (solution.cpp)"
This was the input given when trying to submit the code: 1534236469
My code
class Solution {
public:
int reverse(int x) {
int flag = 0;
int rev = 0;
if (x >= pow(2, 31)) {
return 0;
} else {
if (x < 0) {
flag = 1;
x = abs(x);
}
while(x > 0) {
rev = rev * 10 + x % 10;
x /= 10;
}
if (flag == 1) {
rev = rev*(-1);
}
return rev;
}
}
};
As you can see from my code, I added an if statement that would basically return 0 if the number was greater than 2^31. Unfortunately, this was wrong.
Can anyone explain how this can be fixed? Thank you in advance.
Problem statement asks to return 0 if reversed number does not belong to integer range :
If reversing x causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0.
In your code you checked if input fits in integer range but their arises a corner case when the integer has 10 digits and last digit is >2 (and for some cases 2).
Lets consider the input 1534236469: 1534236469 < 2^31 - 1
so program executes as expected now lets trace last few steps of program execution : rev = 964632435 and x = 1 problem arises when following statement is executed :
rev = rev * 10 + x % 10;
Now, even though input can be represented as integer rev * 10 i.e. 9646324350 is greater than integer range and correct value that should be returned is zero
Fix ?
1. Lets consider 10 digit case independently
Even though this can be done, it gives rise to unnecessary complications when last digit is 2
2. Make rev a long integer
This works perfectly and is also accepted, but sadly this is not expected when solving this problem as statement explicitly asks to not use 64-bit integers
Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
3. Checking before multyplying by 10 ?
This works as expected. Before multyplying rev by 10 check if it is >= (pow(2,31)/10)
while(x > 0) {
if (rev >= pow(2, 31)/10 )
return 0;
rev = rev * 10 + x % 10;
x /= 10;
}
I hope this solves your doubt !! Comment if you find something wrong as this is my first answer.
Note : The following if statement is unnecessary as input is always a 32-bit integer
Given a signed 32-bit integer x
if (x >= pow(2, 31)) {
return 0;
}
Edit : As most of the comments pointed it out, instead of pow(2,31), use INT_MAX macro as it suffices here.
public static int reverse(int x) {
boolean isNegative = false;
if (x < 0) {
isNegative = true;
x = -x;
}
long reverse = 0;
while (x > 0) {
reverse = reverse * 10 + x % 10;
x=x/10;
}
if (reverse > Integer.MAX_VALUE) {
return 0;
}
return (int) (isNegative ? -reverse : reverse);
}

I need to get a random number in the range from a to b with n decimal places

I need a function that returns me a random number with n decimal places
Example:
int aleatorio(int li, int ls)
{
return rand()%(ls+1-li)+li;
}
What i want is:
float new_random(int start, int final, int number_decimals)
{
return // What should I write here?
}
if I would call this function 5 times like this::
new_random(0, 5, 4);
The exit would be:
0.2344
3.4356
2.8435
4.2435
I do not want to use this, because I need numbers of 4 exact decimal places since I will not use them to print, but you will have others:
cout << setprecision(4) << 4.24359675967 << endl; //I do not want this
I need numbers of 4 exact decimal places
Then you cannot use finite precision binary floating point (i.e. float, double or long double) because those types cannot exactly represent all of the values with 4 decimal places.
A solution is to use arbitrary precision floating point, and another is to use fixed point. C++ standard doesn't provide arbitrary precision types nor fixed point types. Another approach is to give up the requirement of exactly representing those values and accept the almost exact values that are achievable with limited precision.
Try this for a Java solution. Multiply the start and finish by 1000, generating ints between the range and then divide the resultant number by 1000 as a double.
int start = 20;
int finish = 30;
int count = 10;
Random r = new Random();
r.ints(start * 1000, finish * 1000).filter(n -> n % 10 != 0)
.limit(count).mapToDouble(n -> n / 1000.)
.forEach(System.out::println);
prints something like this.
21.186
26.983
25.345
20.764
27.911
21.139
24.679
27.722
29.443
28.675
Or as a method supplying the starting number, ending number and precision.
for (int i = 0; i < 10; i++) {
System.out.println(newRandom(start,finish,4));
}
static Random r = new Random();
public static Double newRandom(int start, int finish, int precision) {
int f = (int)Math.pow(10,precision);
return r.ints(start * f, finish * f).filter(n -> n % 10 != 0)
.limit(1).mapToDouble(n -> n / (double)f).findFirst().getAsDouble();
}
Prints something like this.
28.4444
25.0259
29.5611
25.6445
25.4977
28.5124
28.9709
23.4835
27.9766
23.9438
You can generate an integer number N between start and final * 10^number_decimals and then return N / 10^number_decimals
Eg. start = 0, final = 5, number_decimals = 4 ==> N in [0 - 50000] ==> N/10000 in [0.0000 - 5.0000]
float new_random(int start, int final, int number_decimals) {
return aleatorio(start, final*pow10(number_decimals))/number_decimals;
}
You can define pow10 as:
int pow10(int p) {
if (p == 0) return 1;
else return 10 * pow10(p-1);
}

How do I get the number of a specific place in an int in C++?

So I have an int that counts upwards.
Let's say we're up to 65,000 already.
I need to get the number in the thousandth place (the 5), to be assigned to another int.
I found the following snippet which is pretty easy but not quite what I need.
You can use % operator for any number of integers you want to
separate. For example 888881%10 will give you 1 and 888881%100 will
give you 81...
Thanks!
You probably need this.
int AtPos(int number, int pos)
{
return ((number > 0 ? number : -number) / (int)pow(10, pos)) % 10;
}
If this is that you are looking for, arguments validity check should be added.
EDIT.
I just noticed, you need to assign different number in specified position. So you need this improvement:
int& SetValueAtPos(int& number, int pos, int newValue)
{
int power = (int)pow(10, pos);
number -= AtPos(number, pos) * power;
number += power * newValue;
return number;
}
Additionally you can merge those functions and cache value of pow(10, pos) so it would be more optimal.
Try something like this
int a =65432;
int b = ((a%10000)-(a%1000))/1000;
here (a%10000) = 5432
and (a%1000) = 432
so (a%10000)-(a%1000) will be 5000
and finally 5000/1000 = 5
or directly you can use
int b = (a%10000)/1000;
What #Matt suggested in comment is:
int num1 = 65000;
int num2 = num%10000; //num2 is 5000
num2 = num2/1000;
Output: 5

how to generate Narcissistic numbers faster?

The “Narcissistic numbers”, are n digit numbers where the sum of all the nth power of their digits is equal to the number.
So, 153 is a narcissistic number because 1^3 + 5^3 + 3^3 = 153.
Now given N, find all Narcissistic numbers that are N digit length ?
My Approach : was to iterate over all numbers doing sum of powers of digits
and check if its the same number or not, and I per calculated the powers.
but that's not good enough, so is there any faster way ?!
Update:
In nature there is just 88 narcissistic numbers, and the largest is 39 digits long,
But I just need the numbers with length 12 or less.
My Code :
long long int powers[11][12];
// powers[x][y] is x^y. and its already calculated
bool isNarcissistic(long long int x,int n){
long long int r = x;
long long int sum = 0;
for(int i=0; i<n ; ++i){
sum += powers[x%10][n];
if(sum > r)
return false;
x /= 10;
}
return (sum == r);
}
void find(int n,vector<long long int> &vv){
long long int start = powers[10][n-1];
long long int end = powers[10][n];
for(long long int i=start ; i<end ; ++i){
if(isNarcissistic(i,n))
vv.push_back(i);
}
}
Since there are only 88 narcisstic numbers in total, you can just store them in a look up table and iterate over it: http://mathworld.wolfram.com/NarcissisticNumber.html
Start from the other end. Iterate over the set of all nondecreasing sequences of d digits, compute the sum of the d-th powers, and check whether that produces (after sorting) the sequence you started with.
Since there are
9×10^(d-1)
d-digit numbers, but only
(10+d-1) `choose` d
nondecreasing sequences of d digits, that reduces the search space by a factor close to d!.
The code below implements the idea of #Daniel Fischer. It duplicates the table referenced at Mathworld and then prints a few more 11-digit numbers and verifies that there are none with 12 digits as stated here.
It would actually be simplier and probably a little faster to generate all possible histograms of non-increasing digit strings rather than the strings themselves. By a histogram I mean a table indexed 0-9 of frequencies of the respective digit. These can be compared directly without sorting. But the code below runs in < 1 sec, so I'm not going to implement the histogram idea.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DIGITS 12
// pwr[d][n] is d^n
long long pwr[10][MAX_DIGITS + 1];
// Digits and final index of number being considered.
int digits[MAX_DIGITS];
int m;
// Fill pwr.
void fill_tbls(void)
{
for (int d = 0; d < 10; d++) {
pwr[d][0] = 1;
for (int p = 1; p <= MAX_DIGITS; p++)
pwr[d][p] = pwr[d][p-1] * d;
}
}
// qsort comparison for integers descending
int cmp_ints_desc(const void *vpa, const void *vpb)
{
const int *pa = vpa, *pb = vpb;
return *pb - *pa;
}
// Test current number and print if narcissistic.
void test(void)
{
long long sum = 0;
for (int i = 0; i <= m; i++)
sum += pwr[digits[i]][m + 1];
int sum_digits[MAX_DIGITS * 2];
int n = 0;
for (long long s = sum; s; s /= 10)
sum_digits[n++] = s % 10;
if (n == m + 1) {
qsort(sum_digits, n, sizeof(int), cmp_ints_desc);
if (memcmp(sum_digits, digits, n * sizeof(int)) == 0)
printf("%lld\n", sum);
}
}
// Recursive generator of non-increasing digit strings.
// Calls test when a string is complete.
void gen(int i, int min, int max)
{
if (i > m)
test();
else {
for (int d = min; d <= max; d++) {
digits[i] = d;
gen(i + 1, 0, d);
}
}
}
// Fill tables and generate.
int main(void)
{
fill_tbls();
for (m = 0; m < MAX_DIGITS; m++)
gen(0, 1, 9);
return 0;
}
I wrote a program in Lua which found all the narcissistic numbers in 30829.642 seconds. The basis of the program is a recursive digit-value count array generator function which calls a checking function when it's generated the digit-value count for all the digit-values. Each nested loop iterates:
FROM i=
The larger of 0 and the solution to a+x*d^o+(s-x)*(d-1)^o >= 10^(o-1) for x
where
- 'a' is the accumulative sum of powers of digits so far,
- 'd' is the current digit-value (0-9 for base 10),
- 'o' is the total number of digits (which the sum of the digit-value count array must add up to),
- 's' represents the remaining slots available until the array adds to 'o'
UP TO i<=
The smaller of 's' and the solution to a+x*d^o < 10^o for x with the same variables.
This ensures that the numbers checked will ALWAYS have the same number of digits as 'o', and therefore be more likely to be narcissistic while avoiding unnecessary computation.
In the loop, it does the recursive call for which it decrements the digit-value 'd' adds the current digit-value's contribution (a=a+i*d^o) and takes the i digit-slots used up away from 's'.
The gist of what I wrote is:
local function search(o,d,s,a,...) --Original number of digits, digit-value, remaining digits, accumulative sum, number of each digit-value in descending order (such as 5 nines)
if d>0 then
local d0,d1=d^o,(d-1)^o
local dd=d0-d1
--a+x*d^o+(s-x)*(d-1)^o >= 10^(o-1) , a+x*d^o < 10^o
for i=max(0,floor((10^(o-1)-s*d1-a)/dd)),min(s,ceil((10^o-a)/dd)-1) do
search(o,d-1,s-i,a+i*d0,i,...) --The digit counts are passed down as extra arguments.
end
else
--Check, with the count of zeroes set to 's', if the sum 'a' has the same count of each digit-value as the list specifies, and if so, add it to a list of narcissists.
end
end
local digits=1 --Skip the trivial single digit narcissistic numbers.
while #found<89 do
digits=digits+1
search(digits,9,digits,0)
end
EDIT: I forgot to mention that my program finds 89 narcissistic numbers! These are what it finds:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315, 24678050, 24678051, 88593477, 146511208, 472335975, 534494836, 912985153, 4679307774, 32164049650, 32164049651, 40028394225, 42678290603, 44708635679, 49388550606, 82693916578, 94204591914, 28116440335967, 4338281769391370, 4338281769391371, 21897142587612075, 35641594208964132, 35875699062250035, 1517841543307505039, 3289582984443187032, 4498128791164624869, 4929273885928088826, 63105425988599693916, 128468643043731391252,449177399146038697307, 21887696841122916288858, 27879694893054074471405, 27907865009977052567814, 28361281321319229463398, 35452590104031691935943, 174088005938065293023722, 188451485447897896036875, 239313664430041569350093, 1550475334214501539088894, 1553242162893771850669378, 3706907995955475988644380, 3706907995955475988644381, 4422095118095899619457938, 121204998563613372405438066, 121270696006801314328439376, 128851796696487777842012787, 174650464499531377631639254, 177265453171792792366489765, 14607640612971980372614873089, 19008174136254279995012734740, 19008174136254279995012734741, 23866716435523975980390369295, 1145037275765491025924292050346, 1927890457142960697580636236639, 2309092682616190307509695338915, 17333509997782249308725103962772, 186709961001538790100634132976990, 186709961001538790100634132976991, 1122763285329372541592822900204593, 12639369517103790328947807201478392, 12679937780272278566303885594196922, 1219167219625434121569735803609966019, 12815792078366059955099770545296129367, 115132219018763992565095597973971522400, 115132219018763992565095597973971522401
For posterity ;-) This is most similar to #Krakow10's approach, generating bags of digits recursively, starting with 9, then 8, then 7 ... to 0.
It's Python3 code and finds all base-10 solutions with 1 through 61 digits (the first "obviously impossible" width) in less than 10 minutes (on my box). It's by far the fastest code I've ever heard of for this problem. What's the trick? No trick - just tedium ;-) As we go along, the partial sum so far yields a world of constraints on feasible continuations. The code just pays attention to those, and so is able to cut off vast masses of searches early.
Note: this doesn't find 0. I don't care. While all the references say there are 88 solutions, their tables all have 89 entries. Some eager editor must have added "0" later, and then everyone else mindlessly copied it ;-)
EDIT New version is over twice as fast, by exploiting some partial-sum constraints earlier in the search - now finishes in a little over 4 minutes on my box.
def nar(width):
from decimal import Decimal as D
import decimal
decimal.getcontext().prec = width + 10
if width * 9**width < 10**(width - 1):
raise ValueError("impossible at %d" % width)
pows = [D(i) ** width for i in range(10)]
mintotal, maxtotal = D(10)**(width - 1), D(10)**width - 1
def extend(d, todo, total):
# assert d > 0
powd = pows[d]
d1 = d-1
powd1 = pows[d1]
L = total + powd1 * todo # largest possible taking no d's
dL = powd - powd1 # the change to L when i goes up 1
for i in range(todo + 1):
if i:
total += powd
todo -= 1
L += dL
digitcount[d] += 1
if total > maxtotal:
break
if L < mintotal:
continue
if total < mintotal or L > maxtotal:
yield from extend(d1, todo, total)
continue
# assert mintotal <= total <= L <= maxtotal
t1 = total.as_tuple().digits
t2 = L.as_tuple().digits
# assert len(t1) == len(t2) == width
# Every possible continuation has sum between total and
# L, and has a full-width sum. So if total and L have
# some identical leading digits, a solution must include
# all such leading digits. Count them.
c = [0] * 10
for a, b in zip(t1, t2):
if a == b:
c[a] += 1
else:
break
else: # the tuples are identical
# assert d == 1 or todo == 0
# assert total == L
# This is the only sum we can get - no point to
# recursing. It's a solution iff each digit has been
# picked exactly as many times as it appears in the
# sum.
# If todo is 0, we've picked all the digits.
# Else todo > 0, and d must be 1: all remaining
# digits must be 0.
digitcount[0] += todo
# assert sum(c) == sum(digitcount) == width
if digitcount == c:
yield total
digitcount[0] -= todo
continue
# The tuples aren't identical, but may have leading digits
# in common. If, e.g., "9892" is a common prefix, then to
# get a solution we must pick at least one 8, at least two
# 9s, and at least one 2.
if any(digitcount[j] < c[j] for j in range(d, 10)):
# we're done picking digits >= d, but don't have
# enough of them
continue
# for digits < d, force as many as we need for the prefix
newtodo, newtotal = todo, total
added = []
for j in range(d):
need = c[j] - digitcount[j]
# assert need >= 0
if need:
newtodo -= need
added.append((j, need))
if newtodo < 0:
continue
for j, need in added:
newtotal += pows[j] * need
digitcount[j] += need
yield from extend(d1, newtodo, newtotal)
for j, need in added:
digitcount[j] -= need
digitcount[d] -= i
digitcount = [0] * 10
yield from extend(9, width, D(0))
assert all(i == 0 for i in digitcount)
if __name__ == "__main__":
from datetime import datetime
start_t = datetime.now()
width = total = 0
while True:
this_t = datetime.now()
width += 1
print("\nwidth", width)
for t in nar(width):
print(" ", t)
total += 1
end_t = datetime.now()
print(end_t - this_t, end_t - start_t, total)
I think the idea is to generate similar numbers. For example, 61 is similar to 16 as you are just summing
6^n +1^n
so
6^n+1^n=1^n+6^n
In this way you can reduce significant amount of numbers. For example in 3 digits scenario,
121==112==211,
you get the point. You need to generate those numbers first.
And you need to generate those numbers without actually iterating from 0-n.
Python version is:
def generate_power_list(power):
return [i**power for i in range(0,10)]
def find_narcissistic_numbers_naive(min_length, max_length):
for number_length in range(min_length, max_length):
power_dict = generate_power_dictionary(number_length)
max_number = 10 ** number_length
number = 10** (number_length -1)
while number < max_number:
value = 0
for digit in str(number):
value += power_dict[digit]
if value == number:
logging.debug('narcissistic %s ' % number)
number += 1
Recursive solution:
In this solution each recursion handles a single digit of the array of digits being used, and tries all appropriate combinations of that digit
def execute_recursive(digits, number_length):
index = len(digits)
if digits:
number = digits[-1]
else:
number = 0
results = []
digits.append(number)
if len(digits) < number_length:
while number < 10:
results += execute_recursive(digits[:], number_length)
number += 1
digits[index] = number
else:
while number < 10:
digit_value = sum_digits(digits)
if check_numbers_match_group(digit_value, digits):
results.append(digit_value)
logging.debug(digit_value)
number += 1
digits[index] = number
return results
def find_narcissistic_numbers(min_length, max_length):
for number_length in range(min_length, max_length):
digits = []
t_start = time.clock()
results = execute_recursive(digits, number_length)
print 'duration: %s for number length: %s' %(time.clock() - t_start, number_length)
Narcissistic number check
In the base version, when checking that a number matched the digits, we iterated through each digit type, to ensure that there were the same number of each type. In this version we have added the optimisation of checking the digit length is correct before doing the full check.
I expected that this would have more of an effect on small number lengths, because as number length increases, there will tend to be more numbers in the middle of the distribution. This was somewhat upheld by the results:
n=16: 11.5% improvement
n=19: 9.8% improvement
def check_numbers_match_group(number, digits):
number_search = str(number)
# new in v1.3
if len(number_search) != len(digits):
return False
for digit in digit_list:
if number_search.count(digit[0]) != digits.count(digit[1]):
return False
return True
I think you could use Multinomial theorem for some optimisation of cheacking if it is Narcissistic number.
you can calculate (a+b+c+..)^n- sum of non n-th powers values
for example for n=2 you should compare x and (a+b)^2-2*a*b where a and b is digits of number x
'''We can use Nar() function to calculate the Narcissitic Number.'''
import math
def Nar(num):
sum=0
n=len(str(num))
while n>0:
temp=num%10
sum=sum+math.pow(temp,n)
num=num/10
return sum
x=input()
y=Nar(x)
if x==y:
print x,' is a Narcissistic number'
else:
print x,' is not a Narcissistic number'