I have a working algorithm in Python which I want to convert to C++:
def gcd(a, b):
if (a % b == 0):
return b
else:
return gcd(b, a % b)
def solution(N, M):
lcm = N * M / gcd(N, M)
return lcm / M
I'm having a problem with large input values as the multiple of N and M causes integer overflow and using long to store its value doesn't seem to help, unless I'm doing something wrong.
Here's my current code:
int gcd(int a, int b)
{
if (a % b == 0)
return b;
else
return gcd(b, a % b);
}
int solution(int N, int M) {
// Calculate greatest common divisor
int g = gcd(N, M);
// Calculate the least common multiple
long m = N * M;
int lcm = m / g;
return lcm / M;
}
You are computing g=gcd(N,M), then m=N*M, then lcm=m/g, and finally returning lcm/M. That's the same as returning N/gcd(N,M). You don't need those intermediate calculations. Get rid of them. Now there's no problem with overflow (unless M=0, that is, which you aren't protecting against).
int solution(int N, int M) {
if (M == 0) {
handle_error();
}
else {
return N / gcd(N,M);
}
}
To begin with, change:
long m = N * M;
int lcm = m / g;
To:
long long m = (long long)N * M;
int lcm = (int)(m / g);
In general, you might as well change every int in your code to unsigned long long...
But if you have some BigInt class at hand, then you might want to use it instead.
Here is one for free: http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=9735&lngWId=3
It stores a natural number of any conceivable size, and supports all arithmetic operators provided in C++.
The problem is in long m = N*M.
The multiplication takes place as 32 bit integers only. Since both are of int type, overflow occurs.
Correction is long long m = (long long)N*M
Related
I found this implementation of generating a value of minimum run size for a subarray in the timsort algorithm given the size of an initial array n. However I not understand how it works and why must minrun be a value 2^n (Which is to ensure optimality of merge())?
static int MIN_MERGE = 32;
public static int minRunLength(int n)
{
int r = 0;
while (n >= MIN_MERGE)
{
r |= (n & 1);
n >>= 1;
}
return n + r;
}
Any help would be much appreciated!
This question already has answers here:
Why does my recursive function return None?
(4 answers)
Closed 4 years ago.
another one of these stupid questions.
I have a very simpe algorithm here to calculate the greatest commen divider.
My C++ snippet looks like this
int findGcd(int m, int n)
{
int r = m % n;
if(r == 0)
{
return n;
}
else
{
m = n;
n = r;
findGcd(m, n);
}
}
int main()
{
cout << findGcd(13, 3);
return 0;
}
... And it returns (exactly as expected in this example) 1.
If I implement it in Python though - like the following:
def findGcd(m, n):
"""Calculates the greatest common divider """
r = m % n
if r == 0:
return n
else:
m = n
n = r
findGcd(m, n)
number = findGcd(13,3)
print(number)
It just returns NONE instead of 1. I already debugged it and n did indeed have the correct value of 1 stored in it but returns None none the less.
I can fix this by adding "return" to my recursive call of the function in the else branch.
But why is that?
In both cases, you need a return in the recursive call.
Without that, in C++, you have undefined behavior. In Python, you get None.
C++
int findGcd(int m, int n)
{
int r = m % n;
if(r == 0)
{
return n;
}
else
{
m = n;
n = r;
return findGcd(m, n);
}
}
Python:
def findGcd(m, n):
"""Calculates the greatest common divider """
r = m % n
if r == 0:
return n
else:
m = n
n = r
return findGcd(m, n)
You catch such problems in C++ by increasing the warning level on your compiler. With g++ -Wall, I get:
socc.cc: In function ‘int findGcd(int, int)’:
socc.cc:16:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
I'm running these two codes. They both perform the same mathematical procedure (calculate series value up to large terms), and also, as expected, produce the same output.
But for some reason, the PyPy code is running significantly faster than the C code.
I cannot figure out why this is happening, as I expected the C code to run faster.
I'd be thankful if anyone could help me by clarifying that (maybe there is a better way to write the C code?)
C code:
#include <stdio.h>
#include <math.h>
int main()
{
double Sum = 0.0;
long n;
for(n = 2; n < 1000000000; n = n + 1) {
double Sign;
Sign = pow(-1.0, n % 2);
double N;
N = (double) n;
double Sqrt;
Sqrt = sqrt(N);
double InvSqrt;
InvSqrt = 1.0 / Sqrt;
double Ln;
Ln = log(N);
double LnSq;
LnSq = pow(Ln, 2.0);
double Term;
Term = Sign * InvSqrt * LnSq;
Sum = Sum + Term;
}
double Coeff;
Coeff = Sum / 2.0;
printf("%0.14f \n", Coeff);
return 0;
}
PyPy code (faster implementation of Python):
from math import log, sqrt
Sum = 0
for n in range(2, 1000000000):
Sum += ((-1)**(n % 2) * (log(n))**2) / sqrt(n)
print(Sum / 2)
This is far from surprising, PyPy does a number of run-time optimizations by default, where as C compilers by default do not perform any optimization. Dave Beazley's 2012 PyCon Keynote covers this pretty explicitly and provides an deep explanation of why this happens.
Per the referenced talk, C should surpass PyPy when compiled with optimization level 2 or 3 (you can watch the full section on the performance of fibonacci generation in cpython, pypy and C starting here).
Additionally to compiler's optimisation level, you can improve your code as well:
int main()
{
double Sum = 0.0;
long n;
for(n = 2; n < 1000000000; ++n)
{
double N = n; // cast is implicit, only for code readability, no effect on runtime!
double Sqrt = sqrt(N);
//double InvSqrt; // spare that:
//InvSqrt = 1.0/Sqrt; // you spare this division with!
double Ln = log(N);
double LnSq;
//LnSq = pow(Ln,2.0);
LnSq = Ln*Ln; // more efficient
double Term;
//Term = Sign * InvSqrt * LnSq;
Term = LnSq / Sqrt;
if(n % 2)
Term = -Term; // just negating, no multiplication
// (IEEE provided: just one bit inverted)
Sum = Sum + Term;
}
// ...
Now we can simplify the code a little more:
int main()
{
double Sum = 0.0;
for(long n = 2; n < 1000000000; ++n)
// ^^^^ possible since C99, better scope, no runtime effect
{
double N = n;
double Ln = log(N);
double Term = Ln * Ln / sqrt(N);
if(n % 2)
Sum -= Term;
else
Sum += Term;
}
// ...
For example, if L = [1,4,2,6,4,3,2,6,3], then we want 1 as the unique element. Here's pseudocode of what I had in mind:
initialize a dictionary to store number of occurrences of each element: ~O(n),
look through the dictionary to find the element whose value is 1: ~O(n)
This ensures that the total time complexity then stay to be O(n). Does this seem like the right idea?
Also, if the array was sorted, say for example, how would the time complexity change? I'm thinking it would be some variation of binary search which would reduce it to O(log n).
You can use collections.Counter
from collections import Counter
uniques = [k for k, cnt in Counter(L).items() if cnt == 1]
Complexity will always be O(n). You only ever need to traverse the list once (which is what Counter is doing). Sorting doesn't matter, since dictionary assignment is always O(1).
There is a very simple-looking solution that is O(n): XOR elements of your sequence together using the ^ operator. The end value of the variable will be the value of the unique number.
The proof is simple: XOR-ing a number with itself yields zero, so since each number except one contains its own duplicate, the net result of XOR-ing them all would be zero. XOR-ing the unique number with zero yields the number itself.
Your outlined algorithm is basically correct, and it's what the Counter-based solution by #BrendanAbel does. I encourage you to implement the algorithm yourself without Counter as a good exercise.
You can't beat O(n) even if the array is sorted (unless the array is sorted by the number of occurrences!). The unique element could be anywhere in the array, and until you find it, you can't narrow down the search space (unlike binary search, where you can eliminate half of the remaining possibilities with each test).
In the general case, where duplicates can be present any number of times, I don't think you can reduce the complexity below O(N), but for the special case outlined in dasblinkenlight's answer, one can do better.
If the array is already sorted and if duplicates are present an even number of times as is the case in the simple example shown, you can find the unique element in O(log N) time with a binary search. You will search for the position where a[2*n] != a[2*n+1]:
size_t find_unique_index(type *array, size_t size) {
size_t a = 0, b = size / 2;
while (a < b) {
size_t m = (a + b) / 2;
if (array[2 * m] == array[2 * m + 1]) {
/* the unique element is the the right half */
a = m + 1;
} else {
b = m;
}
}
return array[2 * m];
}
You can use variation of binary search if you have array is already sorted. It will reduce your cost to O(lg N). You just have to search left and right appropriate position. Here is the C/C++ implementation of your problem.(I am assuming array is already sorted)
#include<stdio.h>
#include<stdlib.h>
// Input: Indices Range [l ... r)
// Invariant: A[l] <= key and A[r] > key
int GetRightPosition(int A[], int l, int r, int key)
{
int m;
while( r - l > 1 )
{
m = l + (r - l)/2;
if( A[m] <= key )
l = m;
else
r = m;
}
return l;
}
// Input: Indices Range (l ... r]
// Invariant: A[r] >= key and A[l] > key
int GetLeftPosition(int A[], int l, int r, int key)
{
int m;
while( r - l > 1 )
{
m = l + (r - l)/2;
if( A[m] >= key )
r = m;
else
l = m;
}
return r;
}
int CountOccurances(int A[], int size, int key)
{
// Observe boundary conditions
int left = GetLeftPosition(A, 0, size, key);
int right = GetRightPosition(A, 0, size, key);
return (A[left] == key && key == A[right])?
(right - left + 1) : 0;
}
int main() {
int arr[] = {1,1,1,2,2,2,3};
printf("%d",CountOccurances(arr,7,2));
return 0;
}
My goal is to translate the following written in C, into python, so I can evaluate the loop over a string of digits. Originally, the objective takes a range from 0 to 9, gathers input for each iteration while also multiplying, and sums the entire range. Last of all, determines the remainder after dividing by 11.
int checksum(char *str) {
int i, sum = 0;
for (i=0; i<9; i++) {
sum+= (str[i] - '0') * (i + 1);
}
return sum % 11;
}
A direct (but not very idiomatic) translation of the code would look as follows, notice that I renamed some of the variables to avoid clashes with Python's built-in functions:
def checksum(s):
c = 0
for i in range(9):
c += int(s[i]) * (i + 1)
return c % 11
Another more Pythonic option would be to use generator expressions instead of explicit loops:
def checksum(s):
return sum(int(e) * i for i, e in enumerate(s[:9], 1)) % 11