Kickstart 2022 interesting numbers - c++

The question is to find the number of interesting numbers lying between two numbers. By the interesting number, they mean that the product of its digits is divisible by the sum of its digits.
For example: 459 => product = 4 * 5 * 9 = 180, and sum = 4 + 5 + 9 = 18; 180 % 18 == 0, hence it is an interesting number.
My solution for this problem is having run time error and time complexity of O(n2).
#include<iostream>
using namespace std;
int main(){
int x,y,p=1,s=0,count=0,r;
cout<<"enter two numbers"<<endl;
cin>>x>>y;
for(int i=x;i<=y;i++)
{
r=0;
while(i>1)
{
r=i%10;
s+=r;
p*=r;
i/=10;
}
if(p%s==0)
{
count++;
}
}
cout<<"count of interesting numbers are"<<count<<endl;
return 0;
}

If s is zero then if(p%s==0) will produce a divide by zero error.
Inside your for loop you modify the value of i to 0 or 1, this will mean the for loop never completes and will continuously check 1 and 2.
You also don't reinitialise p and s for each iteration of the for loop so will produce the wrong answer anyway. In general limit the scope of variables to where they are actually needed as this helps to avoid this type of bug.
Something like this should fix these problems:
#include <iostream>
int main()
{
std::cout << "enter two numbers\n";
int begin;
int end;
std::cin >> begin >> end;
int count = 0;
for (int number = begin; number <= end; number++) {
int sum = 0;
int product = 1;
int value = number;
while (value != 0) {
int digit = value % 10;
sum += digit;
product *= digit;
value /= 10;
}
if (sum != 0 && product % sum == 0) {
count++;
}
}
std::cout << "count of interesting numbers are " << count << "\n";
return 0;
}
I'd guess the contest is trying to get you to do something more efficient than this, for example after calculating the sum and product for 1234 to find the sum for 1235 you just need to add one and for the product you can divide by 4 then multiply by 5.

Related

Find One to N is Prime optimization

So I was inspired by a recent Youtube video from the Numberphile Channel. This one to be exact. Cut to around the 5 minute mark for the exact question or example that I am referring to.
TLDR; A number is created with all the digits corresponding to 1 to N. Example: 1 to 10 is the number 12,345,678,910. Find out if this number is prime. According to the video, N has been checked up to 1,000,000.
From the code below, I have taken the liberty of starting this process at 1,000,000 and only going to 10,000,000. I'm hoping to increase this to a larger number later.
So my question or the assistance that I need is optimization for this problem. I'm sure each number will still take very long to check but even a minimal percentage of optimization would go a long way.
Edit 1: Optimize which division numbers are used. Ideally this divisionNumber would only be prime numbers.
Here is the code:
#include <iostream>
#include <chrono>
#include <ctime>
namespace
{
int myPow(int x, int p)
{
if (p == 0) return 1;
if (p == 1) return x;
if (p == 2) return x * x;
int tmp = myPow(x, p / 2);
if (p % 2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
int getNumDigits(unsigned int num)
{
int count = 0;
while (num != 0)
{
num /= 10;
++count;
}
return count;
}
unsigned int getDigit(unsigned int num, int position)
{
int digit = num % myPow(10, getNumDigits(num) - (position - 1));
return digit / myPow(10, getNumDigits(num) - position);
}
unsigned int getTotalDigits(int num)
{
unsigned int total = 0;
for (int i = 1; i <= num; i++)
total += getNumDigits(i);
return total;
}
// Returns the 'index'th digit of number created from 1 to num
int getIndexDigit(int num, int index)
{
if (index <= 9)
return index;
for (int i = 10; i <= num; i++)
{
if (getTotalDigits(i) >= index)
return getDigit(i, getNumDigits(i) - (getTotalDigits(i) - index));
}
}
// Can this be optimized?
int floorSqrt(int x)
{
if (x == 0 || x == 1)
return x;
int i = 1, result = 1;
while (result <= x)
{
i++;
result = i * i;
}
return i - 1;
}
void PrintTime(double num, int i)
{
constexpr double SECONDS_IN_HOUR = 3600;
constexpr double SECONDS_IN_MINUTE = 60;
double totalSeconds = num;
int hours = totalSeconds / SECONDS_IN_HOUR;
int minutes = (totalSeconds - (hours * SECONDS_IN_HOUR)) / SECONDS_IN_MINUTE;
int seconds = totalSeconds - (hours * SECONDS_IN_HOUR) - (minutes * SECONDS_IN_MINUTE);
std::cout << "Elapsed time for " << i << ": " << hours << "h, " << minutes << "m, " << seconds << "s\n";
}
}
int main()
{
constexpr unsigned int MAX_NUM_CHECK = 10000000;
for (int i = 1000000; i <= MAX_NUM_CHECK; i++)
{
auto start = std::chrono::system_clock::now();
int digitIndex = 1;
// Simplifying this to move to the next i in the loop early:
// if i % 2 then the last digit is a 0, 2, 4, 6, or 8 and is therefore divisible by 2
// if i % 5 then the last digit is 0 or 5 and is therefore divisible by 5
if (i % 2 == 0 || i % 5 == 0)
{
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
continue;
}
bool isPrime = true;
int divisionNumber = 3;
int floorNum = floorSqrt(i);
while (divisionNumber <= floorNum && isPrime)
{
if (divisionNumber % 5 == 0)
{
divisionNumber += 2;
continue;
}
int number = 0;
int totalDigits = getTotalDigits(i);
// This section does the division necessary to iterate through each digit of the 1 to N number
// Example: Think of dividing 124 into 123456 on paper and how you would iterate through that process
while (digitIndex <= totalDigits)
{
number *= 10;
number += getIndexDigit(i, digitIndex);
number %= divisionNumber;
digitIndex++;
}
if (number == 0)
{
isPrime = false;
break;
}
divisionNumber += 2;
}
if (isPrime)
std::cout << "N = " << i << " is prime." << '\n';
else
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
}
}
Its nice to see you are working on the same question I pondered few months ago.
Please refer to question posted in Math Stackexchange for better resources.
TL-DR,
The number you are looking for is called SmarandachePrime.
As per your code, it seems you are dividing with every number that is not a multiple of 2,5. To optimize you can actually check for n = 6k+1 ( 𝑘 ∈ ℕ ).
unfortunately, it is still not a better approach with respect to the number you are dealing with.
The better approach is to use primality test screening to find probable prime numbers in the sequence and then check whether they are prime or not. These tests take a less time ~(O(k log3n)) to check whether a number is prime or not, using mathematical fundamentals, compared to division.
there are several libraries that provide functions for primality check.
for python, you can use gmpy2 library, which uses Miller-Rabin Primality test to find probable primes.
I recommend you to further read about different Primality tests here.
I believe you are missing one very important check, and it's the division by 3:
A number can be divided by 3 is the sum of the numbers can be divided by 3, and your number consists of all numbers from 1 to N.
The sum of all numbers from 1 to N equals:
N * (N+1) / 2
This means that, if N or N+1 can be divided by 3, then your number cannot be prime.
So before you do anything, check MOD(N,3) and MOD(N+1,3). If either one of them equals zero, you can't have a prime number.

Recursive Digit Sum

I was trying to solve this problem on hackerrank. But I got some problem. Specific problem is:
For example:
The sum of digits 9875 will be calculate as: sum(9875) = 9+8+7+5 = 29. sum(29) = 11. sum(11) = 2. (Using recursive function).
In my test case, (n ='9875', k=4) the number p is created by concatenating the string n k times so the initial p = 9875987598759875 ( the string '9875' repeat 4 times ).
But when i code this test case, it doesn't work. Here is my source code:
int SuperDigit(long n){
long sum =0;
if(n==0) return 0;
else{
return sum= sum +(n%10 + SuperDigit(n/10));
}
if(sum>10){
return (sum%10 + SuperDigit(sum/10));
}
}
int main(){
string n;cin>>n;
int T;cin>>T;
string repeat;
for(int i=0; i <T;i++){
repeat += n;
}
cout<<repeat;
long x=0;
stringstream geek(repeat);
geek>>x;
long sum = SuperDigit(x);
printf("\n%ld ",sum);
for(int i=0;i<10;i++){
if(sum>=10){
sum = SuperDigit(sum);
}
else{
break;
}
}
printf("\n%ld ",sum);
}
If i try: n = '123' and k =3 (Expected output: 9)
My output will be correct, here is my output for this test case:
123 3
123123123
18
9
But when i try n = '9875' and k = 4 (Expected output: 8)
My output will be wrong:
9875 4
9875987598759875
46
1
As you can see in this test case, the first sum of all digits must be 116. But mine only show 46. Can anyone explain for me? Thanks a lot!
In your current code you return prematurely in
if(n==0) return 0;
else{
return sum= sum +(n%10 + SuperDigit(n/10));
}
Imagine that n == 89 so n%10 returns 9 and SuperDigit(n/10) returns 8 and you have 17 as an answer (when 8 is expected).
You can put it as
int SuperDigit(long n) {
int result = 0;
/* We compute digital root (sum of digits) */
for (long number = n; number != 0; number /= 10)
result += (int) (number % 10);
/* if result is out of range [-9..9]
we compute digital root again from the answer */
if (result < -9 || result > 9)
result = SuperDigit(result);
return result;
}
You can simplify your program as shown below. Since you want to find the sum recursively, the below program shows one possible way of doing it.
Version 1: Using recursive function
#include <iostream>
int findDigit(int passed_num, int currentSum)
{
int lastDigit;
if (passed_num == 0) {
return currentSum;
}
// find the last didit
lastDigit = passed_num % 10;
currentSum+= lastDigit;
//call findDigit() repeatedly
currentSum = findDigit(passed_num / 10, currentSum);
std::cout<<lastDigit<<" ";
return currentSum;
}
int main()
{
std::cout << "Enter a number: ";
int input_num, sum;
std::cin>>input_num;
sum = findDigit(input_num, 0);
std::cout<<"sum is: "<<sum<<std::endl;
std::cout << "Enter another number: ";
std::cin>>input_num;
sum = findDigit(input_num, 0);
std::cout<<"sum is: "<<sum<<std::endl;
return 0;
}
Note there are simpler(other) ways of finding the sum without recursively. One such way is shown below:
Version 2: Using loop
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int individual_number = 0, sum = 0;//these are local built in types so initialize them
std::string input_num;
std::cin >> input_num;
for(char c : input_num)
{
individual_number = c -'0';
std::cout<<individual_number<<" ";
sum+= individual_number;
}
std::cout<<"total amount: "<<sum<<std::endl;
// std::cout<<"The sum comes out to be: "<<sum<<std::endl;
return 0;
}

Armstrong numbers. print armstrong numbers

I kindly request those who think this question have been asked earlier, read on first.
I need to print all armstrong numbers between 1 and 10000. My problem is that whenever my program is run and reaches 150, it does
(1^3) + ((5^3)-1) + (0^3)
instead of
(1^3) + (5^3) + (0^3).
Thus it does not print 153 (which is an Armstrong number), of course because the sum results in 152. I do not know if some other numbers are also doing this. But i do have checked untill 200 and there is no problem with other numbers except that in 150–160 range.
Is this a compiler error. Should i re-install my compiler? Currently i am using codeblocks.
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
for(int i = 0;i <= 10000;++i)
{
int r = i;
int dig = 0;
while(r != 0)
{
dig++;
r /= 10;
}
int n = i, sum = 0;
while(n != 0)
{
int d = n % 10;
sum += pow(d, dig);
n /= 10;
}
if(sum == i)
cout << i << ' ';
}
cout << "\n\n\n";
return 0;
}
You should run your code in the debugger. Also your code does not compile for me (GCC 6) because you use cout without std:: or using namespace std;. So how does it compile on your system? You are also using math.h, in C++ you should rather use cmath.
After fixing this, I get the following output on my Fedora 24 with g++ in version 6.4.1:
0 1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
The 153 is included in there, so either your compiler has an error or your program has undefined behavior and therefore the error ensues.
I have looked at the definition for Armstrong numbers and did a really short Python implementation:
# Copyright © 2017 Martin Ueding <dev#martin-ueding.de>
# Licensed under the MIT/Expat license.
def is_armstrong(number):
digits = [int(letter) for letter in str(number)]
score = sum(digit**len(digits) for digit in digits)
return score == number
armstrong = list(filter(is_armstrong, range(10000)))
print(' '.join(map(str, armstrong)))
The output matches your C++ program on my machine exactly:
0 1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
Looking through your code I cannot spot undefined behavior, it looks sensible. First you count the number of digits, then you build up the sum. Perhaps you should try with other compilers like GCC, LLVM, or Ideone. Does Code Blocks ship their own compiler or do they use a system compiler? What operating system are you running?
You said that you are just learning to program. That's cool to hear! I hope you have a good C++ book or other resource. For C++, there is a lot of bad advice on the internet. Also make sure that you have a book that has at least C++11, everything else is badly outdated.
I have changed your program and created some short functions that do just one task such that it is easier to read and reason about. I am not sure whether you already know about functions, so don't worry if that seems to complicated for now :-).
#include <cmath>
#include <iostream>
int get_digit_count(int const number) {
int digits = 0;
int remainder = number;
while (remainder > 0) {
++digits;
remainder /= 10;
}
return digits;
}
bool is_armstrong_number(int const number) {
int const digit_count = get_digit_count(number);
int remainder = number;
int sum = 0;
while (remainder > 0) {
int const last_digit = remainder % 10;
sum += std::pow(last_digit, digit_count);
remainder /= 10;
}
return number == sum;
}
int main() {
for (int i = 0; i <= 10000; ++i) {
if (is_armstrong_number(i)) {
std::cout << i << ' ';
}
}
std::cout << std::endl;
}
This algorithm generates and prints out Armstrong numbers to 999, but can easily be expanded to any length using the same methodology.
n = 1; %initialize n, the global loop counter, to 1
for i = 1 : 10 %start i loop
for j = 1 : 10 %start j loop
for k = 1 : 10 %start k loop
rightnum = mod(n, 10); %isolate rightmost digit
midnum = mod(fix((n/10)), 10); %isolate middle digit
leftnum = fix(n/100); %isolate leftmost digit
if ((n < 10)) %calulate an for single-digit n's
an = rightnum;
end
if ((n > 9) & (n < 100)) %calculate an for 2-digit n's
an = fix(rightnum^2 + midnum^2);
end
if ((n > 99) & (n < 1000)) %calculate an for 3-digit n's
an = fix(leftnum^3 + midnum^3 + rightnum^3);
end
if (n == an) %if n = an display n and an
armstrongmatrix = [n an];
disp(armstrongmatrix);
end
n = n + 1; %increment the global loop counter and continue
end
end
end
You can use arrays:
#include<iostream>
using namespace std;
int pow(int, int);
int checkArm(int);
int main() {
int range;
cout<<"Enter the limit: ";
cin>>range;
for(int i{};i<=range;i++){
if(checkArm(i))
cout<<i<<endl;
}
return 0;
}
int pow(int base, int exp){
int i{0};
int temp{base};
if(exp!=0)
for(i;i<exp-1;i++)
base = base * temp;
else
base=1;
return base;
}
int checkArm(int num) {
int ar[10], ctr{0};
int tempDigits{num};
while(tempDigits>0){
tempDigits/=10;
ctr++;
}
int tempArr{num}, tempCtr{ctr};
for(int i{0};i<=ctr;i++){
ar[i] = tempArr / pow(10,tempCtr-1);
tempArr = tempArr % pow(10,tempCtr-1);
tempCtr--;
}
int sum{};
for(int k{};k<ctr;k++){
sum+=pow(ar[k],ctr);
}
if(sum==num)
return 1;
else
return 0;
}

Having issues in power digit sum in C++

2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 2^1000?
currently I am working on power digit sum in C++. my program is working properly but it gives inappropriate output.
#include<iostream>
#include<math.h>
using namespace std;
long double calculate(long double n)
{
long double i,j,temp = 0,sum = 0;
while(n != 0)
{
temp = fmod(n,10);
sum = sum + temp;
n = n / 10;
}
return sum;
}
int main()
{
long double i,j,n = 1000,temp = 1,value = 0;
for(i = 1;i <= n;i++)
{
temp = temp * 2;
}
cout << "Multiplication is : " << temp << endl;
value = calculate(temp);
cout.precision(100);
cout << "Sum is : " << value << endl;
return 0;
}
I am getting o/p like this.
Multiplication is : 1.07151e+301
Sum is : 1200.63580205668592182366438692042720504105091094970703125
it shouldn't be in points.it should print in digits.
Representing 2^1000 in binary would take a 1000 bits. Doubles are only 64bits long (long doubles are 80 or 128 bits depending on compiler/architecture). So doubles represent 2^1000 approximately. The input to calculate isn't 2^1000, but rather as close an approximation to it as 80bits allow. That approximation does not contain the lowest digits that calculate would like to sum over.
You can't use any primitive datatype to calculate 2^1000 and later sum of its digits, as its a big number (however, in languages like python and ruby you can do it).
For solving this problem in C/C++, you have to use array (or any other linear data structure like linked list, etc) and apply logic similar to usual pen-paper method of multiplying numbers.
First try to find a bound on number of digits in 2^1000 and then initialize an integer array of size greater than it with all zeroes. Keep the last element to be 1. Now multiply the array (thinking it as a large number such that each digit is in a different cell of the array) with 2, thousand times, taking modulo and carry overs.
Here is the code for above logic:
int ar[303];
int sum =0;
ar[0]=1;
for(int j=1;j<303;j++)
ar[j]=0;
for(int i=1;i<1001;i++)
{
ar[0]=2*ar[0];
for(int k=1;k<303;k++)
ar[k]=2*ar[k] + ar[k-1]/10;
for(int j=0;j<303;j++)
ar[j]=ar[j]%10;
}
for(int i=0;i<303;i++)
sum = sum + ar[i];
cout<<sum;
Hope it helps.
The reason why you are getting your sum with decimal points is because you are dividing a double by 10. This will not result in a clean integer unless the doubles last digit before the decimal point is a zero.
example:
376 / 10 = 37.6
370 / 10 = 37
To solve this change this in your code on line 12:
n = (n-temp)/10;
This will cut the float numbers from your sum at least.
finally i have solved my problem.
#include<iostream>
#include<math.h>
#include<string>
using namespace std;
long double calculate(string n)
{
long double i,j,temp = 0,sum = 0;
for (i = 0;i < n.length();i++)
{
if(n[i] == '.')
{
break;
}
sum = sum + (n[i] - 48);
}
return sum;
}
int main()
{
long double i,j,n = 1000,temp = 1,value = 0;
string str;
temp = pow(2,n);
cout << "Power is : " << temp << endl;
str = to_string(temp);
cout << str << endl;
value = calculate(str);
cout.precision(100);
cout << "Sum is : " << value << endl;
return 0;
}

Print sum to n numbers

Here is my question...
Input a number n from the user. The program should output the sum of all numbers from 1 to n NOT including the multiples of 5.
For example if the user inputs 13 then the program should compute and print the sum of the numbers: 1 2 3 4 6 7 8 9 11 12 13 (note 5,10 are not included in the sum)
i have made the following program but it is not working..
can any one help me THANK YOU in advance...
#include <iostream>
using namespace std;
int main()
{
int inputnumber = 0;
int sum = 0;
int count= 1;
cout<<"Enter the number to print the SUM : ";
cin>>inputnumber;
while(count<=inputnumber)
{
if (count % 5!=0)
{
sum = sum + count;
}
} count = count +1;
cout<<"the sum of the numbers are : "<<sum;
}
You should increment count inside the loop, not outside it:
while(count<=inputnumber)
{
if (count % 5!=0)
{
sum = sum + count;
}
count = count +1; // here
}
Note, by the way, that using a for loop would be much more convenient here. Additionally, sum = sum + count could be shorthanded to sum += count.
for (int count = 1; count <= inputnumber; ++count)
{
if (count % 5 != 0)
{
sum += count;
}
}
You need to put the count+1 inside your while loop. also add !=0 tou your if statement.
while(count<=inputnumber)
{
if (count % 5!=0)
{
sum = sum + count;
}
count = count +1;
}
No need to use a loop at all:
The sum 1..n is
n * (n+1) / 2;
the sum of the multiples of 5 not above n is
5 * m * (m+1) / 2
where m = n/5 (integer devision). The result is therefore
n * (n+1) / 2 - 5 * m * (m+1) / 2
Try this..
In my condition,checks n value is not equal to zero and % logic
int sum = 0;
int n = 16;
for(int i=0 ; i < n ;i++) {
if( i%5 != 0){
sum += i;
}
}
System.out.println(sum);
Let's apply some maths. We'll use a formula that allows us to sum an arithmetic progression. This will make the program way more efficient with bigger numbers.
sum = n(a1+an)/2
Where sum is the result, n is the inpnum, a1 is the first number of the progression and an is the place that ocuppies n (the inpnum) in the progression.
So what I have done is calculate the sum of all the numbers from 1 to inpnum and then substract the sum of all the multiples of 5 from 5 to n.
#include <iostream>
using namespace std;
int main (void)
{
int inpnum, quotient, sum;
cout << "Enter the number to print the SUM : ";
cin >> inpnum;
// Finds the amount of multiples of 5 from 5 to n
quotient = inpnum/5;
// Sum from 1 to n // Sum from 5 to n of multiples of 5
sum = (inpnum*(1+inpnum))/2 - (quotient*(5+(quotient)*5))/2;
cout << "The sum of the numbers is: " << sum;
}
thanks every one but the problem is solved . the mistake was very small. i forget to write "()" in if condition.
#include <iostream>
using namespace std;
int main()
{
int inputnumber = 0;
int sum = 0;
int count= 1;
cout<<"Enter the number to print the SUM : ";
cin>>inputnumber;
while(count<=inputnumber)
{
if ((count % 5)!=0)//here the ()..
{
sum = sum + count;
}
count = count +1;
}
cout<<"the sum of the numbers are : "<<sum;
}