Project Euler # 5; this solution works - but why? - c++

The project Euler problem 5 is stated as : "2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
Here's the c++ code for the function I'm using.
long long unsigned int rangeLCM(int n)
{
long long unsigned int ans=1;
for(int i=1;i<=n;i++)
{
if(ans%i!=0)
{
if(i%(ans%i)==0)ans*=(i/(ans%i));
else ans*=i;
}
}
return ans;
}
The code works well for the example stated in the problem and the problem itself{rangeLCM(10)=2520 and rangeLCM(20)=232792560}, but I think it's not perfect and is missing out on some edge cases.
Instead of actually calculating the LCM(ans,i), I have checked that the bigger of the two(always ans) is divisible by i. If not, then ans is multiplied by a number equal to i/(ans%i) or i depending on whether i is divisible by (ans%i) or not.
This is based on the following facts:
LCM(8,12)=24=12*(8/(12%8));
LCM(9,30)=90=30*(9/(30%9)
LCM(7,13)=91=13*7
However, it fails for the following types of cases:LCM(8,14)=56 != 8*14
Yet, the code for rangeLCM gives the right output for all inputs I have tried yet. Why?

Your logic does not work
if(i%(ans%i)==0)ans*=(i/(ans%i));
else ans*=i;
For example, if ans = 10 and i = 14, so, the lcm should be 70, but in your code, it is 140.
The reason is, between ans and i , there are common divisors, but your code cannot detect that.
For experiment, I have written a small piece of code to check using Java.
class Solution {
public static void main(String[] args) {
long ans = 1;
for (long i = 1; i <= 40; i++) {
if (ans % i != 0) {
long before = (ans*i/gcd(ans,i));
if (i % (ans % i) == 0){
ans *= (i / (ans % i));
}else{
ans *= i;
}
System.out.println(ans + " " + before + " " + i);
}
}
}
public static long gcd(long a, long b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
}
Output
2 2 2
6 6 3
12 12 4
60 60 5
420 420 7
840 840 8
2520 2520 9
27720 27720 11
360360 360360 13
720720 720720 16
12252240 12252240 17
232792560 232792560 19
5354228880 5354228880 23
26771144400 26771144400 25
722820898800 80313433200 27
20961806065200 20961806065200 29
649815988021200 649815988021200 31
1299631976042400 1299631976042400 32
48086383113568800 48086383113568800 37
When i = 27, there is different between the correct answer and ans
The formula for lcm(a,b) is
lcm(a,b) = a*b/gcd(a,b)
With gcd is Greatest common divisor between two number a and b

I think you are missing a lot of cases you have to implement the Euclidean algorithm at
if(i%(ans%i)==0)ans*=(i/(ans%i));

Related

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);
}

Lucky 7 recursion

Prompt: A lucky number is the number has the digit 7 and count of #7 in the number must be odd. Write a recursive function to check whether a number is lucky. (For example, lucky#: 777, 117, 7. not a lucky#: 77, 1277).
I am a beginner. I wrote the code below, but I don't understand how "if(num == 7) return 7" work although it should return a boolean. :(
Here is my code: (it checks if there is any digit 7 and sum off all digit 7 is odd)
bool lucky(int num)
{
if (num < 10)
if (num == 7) return 7; << HOW???? Please!
else return 0;
else if (num % 10 == 7)
return (7 + lucky(num / 10)) % 2 != 0;
else
return lucky(num / 10);
}
In C++ any non-zero value can be considered "true", while zero is "false". Integers are implicitly convertible to bool using this scheme.

Prime Factorization Using Recursion

My program currently outputs the prime factorization of a positive integer in ascending order. I'm trying to figure out how to set up the function so that it outputs the numbers in descending order.
For example, showFactors(100) currently outputs "2 2 5 5".
Instead I want it to output "5 5 2 2".
10 // Void function "showFactors" that takes in an int "number" and another int "factor", which is initialized to 2
11 void showFactors(int number, int factor = 2)
12 {
13
14 if (number<2) //returns nothing if number<2
15 {
16 return;
17 }
18 if (number%factor==0) //modulus function is used to get prime factorization
19 {
20 cout<<factor<<" ";
21 showFactors(number/factor, factor); //recursive call
22 }
23 else //if (number%factor != 0) //this modulus function is used in order to output factor !=2
24 {
25 showFactors(number, factor+1);
26 }
27 }
I feel like there should be an easy fix by simply rearranging where the cout call goes, but I haven't had any luck so far.
Edit: Yeah it was as simple as switching lines 20 and 21.
#include <iostream>
using namespace std;
void sf (int number,int factor=2)
{
if (number<2)
return;
if (number%factor == 0)
{
sf (number/factor,factor);
cout<<factor<<"\t";
}
else
sf (number,factor+1);
}
int main ()
{
sf (1729);
cout<<"\n";
return 0;
}
Here is my Ruby solution to get a list of prime factors of a given number. Maybe it will help someone
def prime_factorization(num)
(2...num).each do |fact|
if (num % fact == 0)
otherFact = num / fact
return [ *prime_factorization(fact), *prime_factorization(otherFact) ]
end
end
return [num]
end

modular arithmetic-mod of huge numbers in c++

In my short sports programming career i encountered many time Calculating mod of numbers like
26164615615665561165154564545......%(10000007)
I have done some research but could only find calculation of mods of numbers in the form
(a^b)%c
can anybody explain how to calculate mod of numbers like the first example.
C++ does not have any long integer arithmetic facilities as part of the standard library.
If you want to compute with long integers, you need to rely on an external library.
Two good choices seem to be
GMP: https://gmplib.org - if you are not afraid of C-like interface (there is also gmpxx though)
NTL: http://www.shoup.net/ntl/ - my personal favourite, provides clear and easy interface (e.g. class ZZ for long integers and ZZ_p for long integers modulo)
Here is an example (taken from NTL examples) of how a modular exponentiation could be done using NTL:
ZZ PowerMod(const ZZ& a, const ZZ& e, const ZZ& n)
{
if (e == 0) return ZZ(1);
long k = NumBits(e);
ZZ res;
res = 1;
for (long i = k-1; i >= 0; i--) {
res = (res*res) % n;
if (bit(e, i) == 1) res = (res*a) % n;
}
if (e < 0)
return InvMod(res, n);
else
return res;
}
I have found the solution(maybe)
So,here goes explaination.If we want to calculate mod of very big numbers that cannot be stored as any data type than we have to take number as a string.Than we will do something like this
int remainder(string &s,first)
{
int rem=0;
for(int i=0;i<s.length();++i)
rem=rem*10+(s[i]-'0');//Explaining this below
return rem;
}
Why does it work ?Take a paper and pen and start doing division of string with the number first(taking 100) for ease.
For example, for 1234 % 100.
1 mod 100 = 1
12 mod 100 =(1 * 10 + 2) mod 100 =12
123 mod 100 =(12 * 10 + 3) mod 100 =23
1234 mod 100 =(23 * 10 + 4) mod 100 =34
PS:This is my first answer.Sorry i wrote answer to my own question but i thought it would be good for future readers.

Number guessing game with illogical bug

#include <iostream>
#include <cstdlib>
#include <windows.h>
using namespace std;
srand(time(NULL));
int main(){
int botguess;
int playerinput;
int mi=1, ma=100;
int turns = 0;
cout<<" what do you want guessed:";
cin>> playerinput;
cout<< "time for me to start guessing\n";
for(int i = 0;i < 50;i++) {
botguess = rand() % ma + mi;
if(playerinput > botguess){ //<--the problem
mi = botguess;
}
if(playerinput < botguess) {
ma = botguess;
}
cout<<"Max:"<<ma<<"\n"<<botguess<<"\n";
Sleep(1000);
if(botguess == playerinput)
{
cout<<"you win";
}
}
cin.get();
return 0;
}
So I've been tearing my hair out about why logically this doesn't work. This is a program that is supposed to guess the players number quickly but not instantly. The program doesn't perform like it looks.
The line that I noted causes a bug where the max number possible is being ignored. im getting number that are 100+ but under 200 and i don't know why. When I remove the lines concerning the mi variable nested in the statement in the for loop. The program doesn't go over 100 but I don't get the other end of the program solving the player number.
Also if you figure it out can you please explain it to me I don't just want a answer.
botguess = rand() % (ma - mi + 1) + mi
You don't want ma different numbers, you want much less of them. Look at an example: (5..10) contains 6 different numbers: [5, 6, 7, 8, 9, 10]; but if you do rand() % 10 + 5, you're getting numbers from 5 (5 + 0) to 14 (5 + 9). What you need is rand() % 6 + 5, where 6 is 10 - 5 + 1.
The problem you are having is caused by the fact that mi is set to botguess, which can easily be greater than zero, then on the next cycle if ma is still 100 (or anywhere near it), you're going to sometimes get numbers greater than 100 set into botguess.
Edit added: the % operator in C++ is mod division (ie. gives the remainder of integer division) So for example, 98 % 100 + 15 will be 98 + 15, i.e. 113
This link may help you:
http://www.cplusplus.com/reference/cstdlib/rand/