Problem Statement:
Given an equation “x=y”, for example, “111=12”, you need to add pluses
inside x to make the equation correct. In our example “111=12”, we can
add one plus “11+1=12” and the equation becomes correct. You need to
find the minimum number of pluses to add to x to make the equation
correct. If there is no answer print -1.
Note that the value of y won’t exceed 5000. The numbers in the
corrected equation may contain arbitrary amounts of leading zeros.
Input Format The first line contains a string, A as described in the
problem statement.
Constraints 1 <= len(A) <= 10^3
I tried the recursive approach. Which is for every character in the 'x', I have two options I can include the plus sign next to the current digit or move to the next digit (by including the current digit with the next digit) I checked all the combinations and found the minimum pluses. As you know, this is exponential in complexity. I'm not able to apply dynamic programming for this problem as I can't think of the states for the dynamic programming.
I know this problem can be solved by dynamic programming. But, I don't know how to identify the state and the transition.
The first thing that comes to mind is to have a table
int f[N+1][M+1];
where N = len(x) and M = y. Then f[i][j] would record the solution to the sub-problem substr(x,0,i)=j; i.e. how many pluses are needed to get the sum j from the first i digits of x. The table can be incrementally updated through the recurrence relation:
f[i][j] = minimum over 0 <= k < i of (f[k][j - atoi(substr(x,k,i))] + 1)
Configurations that aren't obtainable or out-of-bounds should be understood as having f[i][j] == +infinity rather than -1.
The size of the table will be O(N*M) and the running time is O(N² M).
I'll leave the implementation details and the starting condition for you to complete.
Backtracking along with DP (Memoization) helped me to pass all the cases
here is my code. It passed all the cases in the given time limit
all_ans = {}
def min_pulses(A, target):
if (A, target) in all_ans:
return all_ans[(A, target)]
if len(A) == 0:
if target != 0:
return -1
else:
return 0
while len(A) > 0 and A[0] == '0':
A = A[1:]
if len(A) == 0 and target == 0:
return 1
if target < 0:
return -1
i = 1
ans = float('inf')# initializing ans to infinite number so that min can be update
while i <= 5 and i <=len(A):
curr_num = A[:i]
curr_ans = min_pulses(A[i:], target - int(curr_num))
if curr_ans >= 0:
ans = min(1 + curr_ans, ans)
i += 1
if ans == float('inf'):
ans = -1
all_ans[(A,target)] = ans
return ans
equation = input().split('=')
A = equation[0]
target = int(equation[1])
groups = min_pulses(A, target)
if groups < 0:
print(-1)
else:
print(groups - 1)
//import java.io.*;
import java.util.*;
//import java.lang.Math;
class NewClass15{
public static int minimum_pluses(String S)
{
StringBuilder s = new StringBuilder();
int target=0;
for(int i=0;i<S.length();i++) //distinguishing left and right strings respectively
{
if(S.charAt(i)=='=')
{
target=Integer.parseInt(S.substring(i+1,S.length()));
break;
}
s.append(S.charAt(i));
}
dp = new int[1000][5001][6];
int temp = dfs(s.toString(),0,0,target);
if(temp>=max)
return -1;
else
return temp;
}
static int dp[][][];
private static int dfs(String s,int len,int ind,int target)
{
if(target<0||len>5) return max;
if(ind==s.length())
{
int x=0;
if(len!=0)
x=Integer.parseInt(s.substring(ind-len,ind));
target-=x;
if(target==0) return 0;
return max;
}
if(dp[ind][target][len]!=0)
{
System.out.println("1 dfs("+ind+","+target+","+len+")");
return dp[ind][target][len]-1;
}
//add
long ans=max;
if(s.charAt(ind)=='0' && len==0)
{
System.out.println("2 dfs("+0+","+(ind+1)+","+target+")");
ans=Math.min(ans,dfs(s,0,ind+1,target));
return (int)(ans);
}
System.out.println("3 dfs("+(len+1)+","+(ind+1)+","+target+")");
ans=Math.min(ans,dfs(s,len+1,ind+1,target));
//add +
if(len!=0)
{
int x=Integer.parseInt(s.substring(ind-len,ind));
int j=ind;
while(j<s.length() && s.charAt(j)=='0') j++;
if(j!=s.length()) j=j+1;
System.out.println("4 dfs("+(1)+","+(j)+","+(target-x)+")");
ans=Math.min(ans,1+dfs(s,1,j,target-x));
}
System.out.println("final dfs("+ind+","+target+","+len+")");
dp[ind][target][len]=(int)(ans+1);
return (int)(ans);
}
static int max=10000;
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String A;
A=scan.next();
int result;
result = minimum_pluses(A);
System.out.print(result);
}
}
This is the answer in java if it is of some help. I have not written the code though.
Can you provide me with some testcases for the given Minimum Pluses Question?
Thank you.
"""2nd one Answer"""
def permute(s):
result = [[s]]
for i in range(1, len(s)):
first = [s[:i]]
rest = s[i:]
for p in permute(rest):
result.append(first + p)
return [[int(j) for j in i] for i in result]
def problem(s):
x,y=s.split("=")
data=permute(x)
newdata=[]
for i in range(1,len(x)+1,1):
for j in data:
if i==len(j):
newdata.append(j)
for i in newdata:
if sum(i)==int(y):
print("str 1",i)
return
print("str -1")
def check_constraint(s):
if (not (1<=len(s)<=10^3)):
print(-1)
elif (s.split("=")[0]==s.split("=")[1]):
print(1)
elif (not (len(s.split("=")[0])>=len(s.split("=")[1]))):
print(-1)
else:
problem(s)
A=input()
check_constraint(A)
I need to have an algorithm for generating regex which will be checking whether number is i in specific range. In general I have following requirements:
I need to use regex
Regex need to generated based on given numbers (min and max)
Need to check only for float numbers
Numbers migh be positive as well as negative
Possible float formats: +X.YYY, +X.YY, +X.Y, -X.YYY, -X.YY, -X.Y
X represents any number of digitts, while Y represent exactly one digit. At least one decimal is needed. So 1 should be 1.0, 0 should be 0.0 and so on.
Min and max will always have the same format. So you can have min = +2.22, max = +3.45 and check for +1.541 but you cant have min = +2.223, max = +3.45 and check for +1.541
Below you can find examples of ranges:
from +1.0 to +20.0
from -1.0 to +20.0
from -20.0 to -10.0
from +1.01 to +2.12
I am not very familiar with regex and to be hoenst I dont even know where should I start. Will appreciate any suggestions!
MY IDEA
The idea I have is to create subranges. So say I want to check for range 7.5 - 222.1. Then I believe that I should create subranges and check for them. For example:
7.5 - 7.9
8.0 - 9.9
10.0 - 99.9
100.0 - 222.0
222.0 - 222.1
Regular expression are not really suited for testing whether a number is within some range; they can get quite long.
Below a solution written in a runnable JavaScript snippet. You can enter the range and test value in the input boxes and both the produced regex and validation result for the test value are displayed.
The following assumptions/rules apply:
When the range is invalid (e.g. minimum number is greater than maximum), then the regex will be _^ which will make all test values fail.
Test values must have the same number of decimal digits as the minimum/maximum values.
When the minimum and maximum have a different number of decimal digits, the greater of the two applies
+ is not allowed; non-negative numbers should not have a sign
-0.0 is not allowed; zero should not have a sign
.9 is not allowed; there should be at least one digit before the decimal point
The rules for the minimum/maximum values are less strict.
minimum and maximum do not need to have the same number of integer digits. For example, a range from -33.08 to 12328.84 will work fine.
// Some helper constants/functions for producing regex
const reDot = "\\.";
function reRange(low, high) {
return high-low === 9 ? "\\d" : low<high ? "[" + low + "-" + high + "]" : low;
}
function reRepeat(what, min, max=min) {
return !max ? ""
: what + (max > 1 ? "{" + min + (min < max ? "," + max : "") + "}" : min ? "" : "?");
}
function reOr(list) {
return list.length > 1 ? "(" + list.join("|") + ")" : list[0];
}
function reAnchor(what) {
return "^" + what + "$";
}
// Main function:
function rangeRegex(min, max) {
if (!(+min <= +max)) return "_^"; // All strings should fail this regex
const decimals = Math.max( (min+".").split(".")[1].length, (max+".").split(".")[1].length );
// Take care of negative ranges:
if (+min < 0 && +max < 0) return reAnchor("-" + positiveRange(-max, -min));
if (+min < 0) return reAnchor(reOr(["-(?=.*[1-9])" + positiveRange(0, -min), positiveRange(0, max)]));
return reAnchor(positiveRange(min, max));
function positiveRange(min, max) {
// Format the two input numbers with equal number of decimals and remove decimal point
const minParts = (Math.abs(min)+".").split(".");
const maxParts = (Math.abs(max)+".").split(".");
min = minParts[0] + minParts[1].padEnd(decimals, "0");
max = maxParts[0] + maxParts[1].padEnd(decimals, "0");
// Build regex parts
const parts = [];
if (min.length < max.length && !/^1?0*$/.test(min)) {
parts.push(fixedLengthRange(min, "9".repeat(min.length)));
min = "1" + "0".repeat(min.length);
}
if (min.length < max.length && !/^9+$/.test(max)) {
parts.push(fixedLengthRange("1" + "0".repeat(max.length-1), max));
max = "9".repeat(max.length-1);
}
if (/^1?0*$/.test(min) && /^9+$/.test(max)) {
parts.push(
reRange(min[0], 9)
+ reRepeat(reRange(0, 9), min.length-decimals-1, max.length-decimals-1)
+ (decimals ? reDot + reRepeat(reRange(0, 9), decimals) : "")
);
} else {
parts.push(fixedLengthRange(min, max));
}
return reOr(parts);
}
function fixedLengthRange(min, max) {
const len = max.length;
if (!len) return "";
const pre = len === decimals ? reDot : "";
let low = +min[0];
let high = +max[0];
if (low === high) return pre + min[0] + fixedLengthRange(min.slice(1), max.slice(1));
const parts = [];
if (+min.slice(1)) {
parts.push(min[0] + fixedLengthRange(min.slice(1), "9".repeat(len-1)));
low++;
}
if (max.slice(1) < "9".repeat(max.length-1)) {
parts.push(max[0] + fixedLengthRange("0".repeat(len-1), max.slice(1)));
high--;
}
if (low <= high) {
parts.push(reRange(low, high) +
(len <= decimals || !decimals ? reRepeat(reRange(0, 9), len-1)
: reRepeat(reRange(0, 9), len-1-decimals) + reDot + reRepeat(reRange(0, 9), decimals)));
}
return pre + reOr(parts);
}
}
// I/O handling for this snippet
const inputMin = document.querySelector("#min");
const inputMax = document.querySelector("#max");
const inputVal = document.querySelector("#val");
const outputRegex = document.querySelector("#regex");
const outputValid = document.querySelector("#valid");
document.oninput = function() {
const regex = rangeRegex(inputMin.value, inputMax.value);
outputRegex.textContent = regex;
outputValid.textContent = new RegExp(regex).test(inputVal.value) ? "OK" : "Not OK";
}
<label>Min: <input id="min"></label>
<label>Max: <input id="max"></label>
<hr>
<div>Regex: <span id="regex"></span></div>
<label>Test: <input id="val"></label>
<div>Valid: <span id="valid"></span></div>
I am making a program for nth Fibonacci number. I made the following program using recursion and memoization.
The main problem is that the value of n can go up to 10000 which means that the Fibonacci number of 10000 would be more than 2000 digit long.
With a little bit of googling, I found that i could use arrays and store every digit of the solution in an element of the array but I am still not able to figure out how to implement this approach with my program.
#include<iostream>
using namespace std;
long long int memo[101000];
long long int n;
long long int fib(long long int n)
{
if(n==1 || n==2)
return 1;
if(memo[n]!=0)
return memo[n];
return memo[n] = fib(n-1) + fib(n-2);
}
int main()
{
cin>>n;
long long int ans = fib(n);
cout<<ans;
}
How do I implement that approach or if there is another method that can be used to achieve such large values?
One thing that I think should be pointed out is there's other ways to implement fib that are much easier for something like C++ to compute
consider the following pseudo code
function fib (n) {
let a = 0, b = 1, _;
while (n > 0) {
_ = a;
a = b;
b = b + _;
n = n - 1;
}
return a;
}
This doesn't require memoisation and you don't have to be concerned about blowing up your stack with too many recursive calls. Recursion is a really powerful looping construct but it's one of those fubu things that's best left to langs like Lisp, Scheme, Kotlin, Lua (and a few others) that support it so elegantly.
That's not to say tail call elimination is impossible in C++, but unless you're doing something to optimise/compile for it explicitly, I'm doubtful that whatever compiler you're using would support it by default.
As for computing the exceptionally large numbers, you'll have to either get creative doing adding The Hard Way or rely upon an arbitrary precision arithmetic library like GMP. I'm sure there's other libs for this too.
Adding The Hard Way™
Remember how you used to add big numbers when you were a little tater tot, fresh off the aluminum foil?
5-year-old math
1259601512351095520986368
+ 50695640938240596831104
---------------------------
?
Well you gotta add each column, right to left. And when a column overflows into the double digits, remember to carry that 1 over to the next column.
... <-001
1259601512351095520986368
+ 50695640938240596831104
---------------------------
... <-472
The 10,000th fibonacci number is thousands of digits long, so there's no way that's going to fit in any integer C++ provides out of the box. So without relying upon a library, you could use a string or an array of single-digit numbers. To output the final number, you'll have to convert it to a string tho.
(woflram alpha: fibonacci 10000)
Doing it this way, you'll perform a couple million single-digit additions; it might take a while, but it should be a breeze for any modern computer to handle. Time to get to work !
Here's an example in of a Bignum module in JavaScript
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s, Number) .reverse ()
, toString: (b) =>
b .reverse () .join ("")
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
We can verify that the Wolfram Alpha answer above is correct
const { fromInt, toString, add } =
Bignum
const bigfib = (n = 0) =>
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n > 0) {
_ = a
a = b
b = add (b, _)
n = n - 1
}
return toString (a)
}
bigfib (10000)
// "336447 ... 366875"
Expand the program below to run it in your browser
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s) .reverse ()
, toString: (b) =>
b .reverse () .join ("")
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
const { fromInt, toString, add } =
Bignum
const bigfib = (n = 0) =>
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n > 0) {
_ = a
a = b
b = add (b, _)
n = n - 1
}
return toString (a)
}
console.log (bigfib (10000))
Try not to use recursion for a simple problem like fibonacci. And if you'll only use it once, don't use an array to store all results. An array of 2 elements containing the 2 previous fibonacci numbers will be enough. In each step, you then only have to sum up those 2 numbers. How can you save 2 consecutive fibonacci numbers? Well, you know that when you have 2 consecutive integers one is even and one is odd. So you can use that property to know where to get/place a fibonacci number: for fib(i), if i is even (i%2 is 0) place it in the first element of the array (index 0), else (i%2 is then 1) place it in the second element(index 1). Why can you just place it there? Well when you're calculating fib(i), the value that is on the place fib(i) should go is fib(i-2) (because (i-2)%2 is the same as i%2). But you won't need fib(i-2) any more: fib(i+1) only needs fib(i-1)(that's still in the array) and fib(i)(that just got inserted in the array).
So you could replace the recursion calls with a for loop like this:
int fibonacci(int n){
if( n <= 0){
return 0;
}
int previous[] = {0, 1}; // start with fib(0) and fib(1)
for(int i = 2; i <= n; ++i){
// modulo can be implemented with bit operations(much faster): i % 2 = i & 1
previous[i&1] += previous[(i-1)&1]; //shorter way to say: previous[i&1] = previous[i&1] + previous[(i-1)&1]
}
//Result is in previous[n&1]
return previous[n&1];
}
Recursion is actually discommanded while programming because of the time(function calls) and ressources(stack) it consumes. So each time you use recursion, try to replace it with a loop and a stack with simple pop/push operations if needed to save the "current position" (in c++ one can use a vector). In the case of the fibonacci, the stack isn't even needed but if you are iterating over a tree datastructure for example you'll need a stack (depends on the implementation though). As I was looking for my solution, I saw #naomik provided a solution with the while loop. That one is fine too, but I prefer the array with the modulo operation (a bit shorter).
Now concerning the problem of the size long long int has, it can be solved by using external libraries that implement operations for big numbers (like the GMP library or Boost.multiprecision). But you could also create your own version of a BigInteger-like class from Java and implement the basic operations like the one I have. I've only implemented the addition in my example (try to implement the others they are quite similar).
The main idea is simple, a BigInt represents a big decimal number by cutting its little endian representation into pieces (I'll explain why little endian at the end). The length of those pieces depends on the base you choose. If you want to work with decimal representations, it will only work if your base is a power of 10: if you choose 10 as base each piece will represent one digit, if you choose 100 (= 10^2) as base each piece will represent two consecutive digits starting from the end(see little endian), if you choose 1000 as base (10^3) each piece will represent three consecutive digits, ... and so on. Let's say that you have base 100, 12765 will then be [65, 27, 1], 1789 will be [89, 17], 505 will be [5, 5] (= [05,5]), ... with base 1000: 12765 would be [765, 12], 1789 would be [789, 1], 505 would be [505]. It's not the most efficient, but it is the most intuitive (I think ...)
The addition is then a bit like the addition on paper we learned at school:
begin with the lowest piece of the BigInt
add it with the corresponding piece of the other one
the lowest piece of that sum(= the sum modulus the base) becomes the corresponding piece of the final result
the "bigger" pieces of that sum will be added ("carried") to the sum of the following pieces
go to step 2 with next piece
if no piece left, add the carry and the remaining bigger pieces of the other BigInt (if it has pieces left)
For example:
9542 + 1097855 = [42, 95] + [55, 78, 09, 1]
lowest piece = 42 and 55 --> 42 + 55 = 97 = [97]
---> lowest piece of result = 97 (no carry, carry = 0)
2nd piece = 95 and 78 --> (95+78) + 0 = 173 = [73, 1]
---> 2nd piece of final result = 73
---> remaining: [1] = 1 = carry (will be added to sum of following pieces)
no piece left in first `BigInt`!
--> add carry ( [1] ) and remaining pieces from second `BigInt`( [9, 1] ) to final result
--> first additional piece: 9 + 1 = 10 = [10] (no carry)
--> second additional piece: 1 + 0 = 1 = [1] (no carry)
==> 9542 + 1 097 855 = [42, 95] + [55, 78, 09, 1] = [97, 73, 10, 1] = 1 107 397
Here is a demo where I used the class above to calculate the fibonacci of 10000 (result is too big to copy here)
Good luck!
PS: Why little endian? For the ease of the implementation: it allows to use push_back when adding digits and iteration while implementing the operations will start from the first piece instead of the last piece in the array.
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'