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;
}
Related
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.
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.
i have this exercise:" consider some natural number n, if it is not a Palindrom number, change the order of the digits in reverse order and add the resulting number with the original number. If the sum is not a palindrom number, repeat the same procedure on that sum until a palindrom number is obtained. Whether the above process is finite for any n. If yes, print out the number of process "
ex
input:1 output: 0
input: 12 output: 1
my problem is when i encounter larger number such as 19170 it will be over the limit of unsigned long long int
It will also be great if anyone can explain or guide me to resources that can help me understand it further.
#include <iostream>
#include <math.h>
using namespace std;
bool check (long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
if(ans==n)
{
return true;
}
return false;
}
long long int reverse(long long int n)
{
long long int clone_n=n,count=0,ans=0;
while (clone_n!=0)
{
clone_n/=10;
count++;
}
clone_n=n;
for(int i=count;i>=0;i--)
{
ans+=(clone_n%10)*pow(10,i-1);
clone_n/=10;
}
return ans;
}
int main()
{
long long int n,count=0;
cin>>n;
if(check(n))
{
cout<<0;
return 0;
}
else
{
while(check(n)!=1)
{
count++;
n+=reverse(n);
}
}
cout<<count;
}
my code is also included in the link: https://ideone.com/0p7JJU
The natural number that will not terminate the algorithm that the OP describe is called Lychrel number. https://en.wikipedia.org/wiki/Lychrel_number
It is currently unknown if any of these number exists, as correctly guessed by zkoza in the above answer, 196 is the smallest candidate to be a Lychrel number.
So, this is a specifically hard problem to tackle, however, I would like to address the specific overflow issue that the OP is facing. As pointed out by largest_prime_is_463035818 in the comments, there is no actual needs of any integer representation.
#include <iostream>
//take advantage of the fact that std::string use contiguous memory
bool is_palindrome(const char* first, const char* last)
{
--last;
while(first < last) {
if (*first != *last)
return false;
++first;
--last;
}
return true;
}
std::string reverse_and_add(const std::string& digits)
{
size_t size = digits.size();
//the result string will be at least the same length
std::string result(size,'0');
int carry_over = 0;
int ascii_zero = 48;
for (size_t i = 0; i < size; i++)
{
int front = digits.at(i) - ascii_zero;
int back = digits.at(size - i - 1) - ascii_zero;
int sum = front + back + carry_over;
carry_over = sum / 10;
int digit = sum >= 10 ? sum - 10 : sum;
result[size - i - 1] = static_cast<char>(digit + ascii_zero);
}
//if at the last step we have a carry over we need to add an extra digit to
//the string
if (carry_over > 0)
result = static_cast<char>(carry_over + ascii_zero) + result;
return result;
}
void check(const std::string& s, int max_iteration)
{
int counter = 0;
std::string v(s);
while(!is_palindrome(v.c_str(), v.c_str() + v.size()) && counter < max_iteration)
{
v = reverse_and_add(v);
if (counter % 1000 == 0 && counter > 0)
std::cout << "progressing iteration: " << counter << " string size: " << v.size() << std::endl;
counter++;
}
if (counter == max_iteration)
std::cout << "No result found" << std::endl;
else
std::cout << "result: " << counter << std::endl;
}
int main()
{
int max_iteration = 50000;
check("187",max_iteration); // -> return 23
check("19170", max_iteration); // -> doesn't find a solution
// the final string is thousands of characters
}
UPDATE
Just for fun, I run 196 till 1000000 digits (that it took 3 years to complete 1987) and it produce the same result in about an hour and half (these hardware engineers are amazing).
result: 2415836
./a.out 5315.83s user 21.29s system 99% cpu 1:29:12.58 total
I assume this is a homework question.
The first number for which the sequence does not seem to be finite is as small as 196. I terminated a program after it hit 300000 digits.
What can you do?
Write a similar program where you implement your own "big numbers". It's an easy task, because all you need is addition of two same-length numbers, reversal, checking for being a palindrom, perhaps printing. You can use std::vector or std::string.
Then, introduce an ad hoc threshold, like 100 or 1000 iterations. If the sequence will reach the threshold, stop it and return false.
It is possible that you did not present here the complete, detailed description of the problem. I found a similar problem on the internet, but with an explicit threshold of 5 iterations. Or perhaps it is a problem that you've invented yourself, unaware of its complexity? Or the teacher is pulling your leg? Or I made a mistake in my code.
A famous example of a problem that has a simple formulation but no known solution is the Collatz conjecture, https://en.wikipedia.org/wiki/Collatz_conjecture . It can't be ruled out that your problem is of a similar type.
Here, for reference, is my solution for numbers from 180 to 195 (the first number in the sequence, the number of iteration, the last number in the sequence)
180 3 747
181 0 181
182 6 45254
183 4 13431
184 3 2552
185 3 4774
186 3 6996
187 23 8813200023188
188 7 233332
189 2 1881
190 7 45254
191 0 191
192 4 6996
193 8 233332
194 3 2992
195 4 9339
Instead of numeric data type you can use string to store the values and do addition by parsing the whole string like this
#include <iostream>
#include <string>
int main()
{
std::string s1 = "759579537575937593759387";
std::string s2 = "9956775659653876536535637653";
int n1=s1.size()-1,n2=s2.size()-1;
std::string s3 = "";
uint8_t carry = 0;
while(n1>=0 && n2>=0){
uint8_t num1 = (int)s1[n1--] - 48;
uint8_t num2 = (int)s2[n2--] - 48;
uint8_t sum = char(num1+num2) + carry;
carry = sum/10; // to get carry
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n1>=0)
{
uint8_t sum = carry + (int)s1[n1--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
while(n2>=0)
{
uint8_t sum = carry + (int)s2[n2--] - 48;
carry = sum/10;
sum = sum%10;
s3.insert(0,1,char(sum+48));
}
if (carry)
s3.insert(0,1,char(carry+48));
std::cout<<s3<<std::endl;
}
also you check if they are palindromic or not using two pointer method.
The above sum which I get is 9957535239191452474129397040, there is no limit to addition by this method
I'm trying to find the last digit of the sum of the fibonacci series from a starting to an end point. As we find the last digit using %10 , Fibonnaci will repeat it's last digit sequence every 60 times - using the Pisano Series
My attempt at the solution:
We find the last digits of the first 60 digits, store them in an array and then continuously loop over and sum over the digits starting from n%60 to m. We then finally modulo 10 the result.
#include <iostream>
#include <vector>
using std::vector;
int fibonacci_fast(long long n,long long m) {
// write your code here
long long a[60];
a[0]=0;
a[1]=1;
long long sum=0;
for(long long i=2;i<60;i++)
{
a[i] = a[i-1]+a[i-2];
a[i] = a[i] % 10;
}
int j=0;
int p=1;
int c=0;
for(int i=n%60;;i++)
{
if(i==60)
{
i=i%60;
}
sum=sum+a[i];
c=c+1;
if(c==m)
{
break;
}
}
return sum%10;
}
int main() {
long long from, to;
std::cin >> from >> to;
std::cout << fibonacci_fast(from, to) << '\n';
}
The major issue I'm having with this current code is that for lower values, it works fine, but if I input higher values such as 0 to 239, It only works when the condition changes to if(c+1)==m which then results in the smaller values solutions turning wrong.
The c counter works correctly though and goes up to 239 but I still cannot figure out the issue with the code.
#include <vector>
using std::vector;
int fibonacci_fast(long long n,long long m) {
// write your code here
long long a[60];
a[0]=0;
a[1]=1;
long long sum=0;
sum = a[0] + a[1];
for(long long i=2;i<60;i++)
{
a[i] = a[i-1]+a[i-2];
a[i] = a[i] % 10;
sum = (sum + a[i]) % 10;
}
int x = (m - n + 1)/60;
sum = (sum * x) % 10;
int i = n + 60 * x;
while(i <= m)
{
sum = (sum + a[i%60]) % 10;
i++;
}
return sum;
}
int main() {
long long from, to;
std::cin >> from >> to;
std::cout << fibonacci_fast(from, to) << '\n';
}
I think you need to set the variable c to be equal to the value of n and not 0 (zero)
int c = n;
Also, please clear the concept whether you want to include the index m or not.
Example, if user enters:
n -> 10
m -> 20
Then your code provided above will add the last digit values of the Fibonacci numbers from the index 10 to the index 19 only. So please clear this doubt of mine, then I will add further.
Background:
This problem comes from leetcode.com
Write an algorithm to determine if a number is "happy".
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example: 19 is a happy number
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
Question:
I thought of doing a recursion for this particular problem to keep repeating the squaring of the integers until we arrive at 1. I am new with recursion (just read Absolute C++ Ch 13 --- Recursion yesterday).I thought I would give this problem a shot but I am having some trouble.
When I call my function I created I should get a return of 19 since 19 is a "Happy Number", but instead my function just returns 0, and I am not sure why. I just need some help with my approach I have taken and suggestions to changes in my code.
Here is my code:
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int Happy(int n) {
vector<int> nums;
int length = to_string(n).length();
for(int i = 0; i < length; i++) {
int digit = n % 10;
n /= 10;
nums.push_back(digit);
}
reverse(nums.begin(), nums.end());
int sum = 0;
for(int i = 0; i < length; i++) {
sum += pow(nums[i],2);
}
if (sum == 1) {
return n;
}
else {
return Happy(sum);
}
}
int main() {
int n = 19;
int result = Happy(n);
cout << result << endl;
return 0;
}
Again, I am not sure why I get 0 as the result, when it should return 19.
You forgot to place a return in your code, Also you n becomes 0, and you are returning n when you find sum == 1. It should return the original_num.
To Store the original number reference pass it along with your call to happy method.
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int Happy(int n, int original_num) {
vector<int> nums;
int length = to_string(n).length();
for(int i = 0; i < length; i++) {
int digit = n % 10;
n /= 10;
nums.push_back(digit);
}
//reverse(nums.begin(), nums.end());
int sum = 0;
for(int i = 0; i < length; i++) {
sum += nums[i]*nums[i];
}
if (sum == 1) {
return original_num;
}
else {
return Happy(sum, original_num);
}
}
int main() {
int n = 19;
int result = Happy(n, n);
cout << result << endl;
return 0;
}
Hope this helps!