Related
What is the best way to divide two numbers that have more than 50 digits, but less than 200.
I have structure to represent a number:
struct number{
int digit[MAX_SIZE]; // MAX_SIZE = 5;
bool negative; // Is it negative or positive number
};
The problem that I face when trying to implement this algorithm is that, if I'm trying to divide a number 'n' with a number 'm' (n > m) that has more digits then you can store in a variable, how can you divide it ?
For example:
1234567891234567891234567 / 12345678912345678
My first guess is to do with repeated subtractions, but isn't that too slow?
Think about how you do it by hand:
You calculate the most significant digit first. And if the numbers are great enough you do it by repeated subtraction, finding one digit at a time.
In your case:
The first number has 25 digits and the second number has 17 digits.
So you start with the digit corresponding to 1E8.
Here is some C-style pseudocode.
struct number n1 = 1234567891234567891234567;
struct number n2 = 12345678912345678;
int start = floor(log10(n1) - log10(n2)); // Position of most significant digit in answer
struct number result = 0;
int i,j;
struct number remainder = n1;
// Start with the most significant digit
for i = start to 0 {
// Find the highest digit that gives a remainder >= 0
for j = 9 to 0 step -1 {
if (remainder - j * n2 * pow(10, i) >= 0) {
// We found the digit!
result = result + j * pow(10, i);
remainder = remainder - j * n2 * pow(10, i);
break; // Move on to the next digit
}
}
}
// We now have the result and the remainder.
This is an interview question. Count all numbers with unique digits (in decimal) in the range [1, N].
The obvious solution is to test each number in the range if its digits are unique. We can also generate all numbers with unique digits (as permutations) and test if they are in the range.
Now I wonder if there is a DP (dynamic programming) solution for this problem.
I'm thinking:
Number of unique digits numbers 1-5324
= Number of unique digits numbers 1-9
+ Number of unique digits numbers 10-99
+ Number of unique digits numbers 100-999
+ Number of unique digits numbers 1000-5324
So:
f(n) = Number of unique digits numbers with length n.
f(1) = 9 (1-9)
f(2) = 9*9 (1-9 * 0-9 (excluding first digit))
f(3) = 9*9*8 (1-9 * 0-9 (excluding first digit) * 0-9 (excluding first 2 digits))
f(4) = 9*9*8*7
Add all of the above until you get to the number of digits that N has minus 1.
Then you only have to do Number of unique digits numbers 1000-5324
And:
Number of unique digits numbers 1000-5324
= Number of unique digits numbers 1000-4999
+ Number of unique digits numbers 5000-5299
+ Number of unique digits numbers 5300-5319
+ Number of unique digits numbers 5320-5324
So:
N = 5324
If N[0] = 1, there are 9*8*7 possibilities for the other digits
If N[0] = 2, there are 9*8*7 possibilities for the other digits
If N[0] = 3, there are 9*8*7 possibilities for the other digits
If N[0] = 4, there are 9*8*7 possibilities for the other digits
If N[0] = 5
If N[1] = 0, there are 8*7 possibilities for the other digits
If N[1] = 1, there are 8*7 possibilities for the other digits
If N[1] = 2, there are 8*7 possibilities for the other digits
If N[1] = 3
If N[2] = 0, there are 7 possibilities for the other digits
If N[2] = 1, there are 7 possibilities for the other digits
If N[2] = 2
If N[3] = 0, there is 1 possibility (no other digits)
If N[3] = 1, there is 1 possibility (no other digits)
If N[3] = 2, there is 1 possibility (no other digits)
If N[3] = 3, there is 1 possibility (no other digits)
The above is something like:
uniques += (N[0]-1)*9!/(9-N.length+1)!
for (int i = 1:N.length)
uniques += N[i]*(9-i)!/(9-N.length+1)!
// don't forget N
if (hasUniqueDigits(N))
uniques += 1
You don't really need DP as the above should be fast enough.
EDIT:
The above actually needs to be a little more complicated (N[2] = 2 and N[3] = 2 above is not valid). It needs to be more like:
binary used[10]
uniques += (N[0]-1)*9!/(9-N.length+1)!
used[N[0]] = 1
for (int i = 1:N.length)
uniques += (N[i]-sum(used 0 to N[i]))*(9-i)!/(9-N.length+1)!
if (used[N[i]] == 1)
break
used[N[i]] = 1
// still need to remember N
if (hasUniqueDigits(N))
uniques += 1
For an interview question like this, a brute-force algorithm is probably intended, to demonstrate logic and programming competency. But also important is demonstrating knowledge of a good tool for the job.
Sure, after lots of time spent on the calculation, you can come up with a convoluted mathematical formula to shorten a looping algorithm. But this question is a straightforward example of pattern-matching, so why not use the pattern-matching tool built in to just about any language you'll be using: regular expressions?
Here's an extremely simple solution in C# as an example:
string csv = string.Join(",", Enumerable.Range(1, N));
int numUnique = N - Regex.Matches(csv, #"(\d)\d*\1").Count;
Line 1 will differ depending on the language you use, but it's just creating a CSV of all the integers from 1 to N.
But Line 2 would be very similar no matter what language: count how many times the pattern matches in the csv.
The regex pattern matches a digit possibly followed by some other digits, followed by a duplicate of the first digit.
Lazy man's DP:
Prelude> :m +Data.List
Data.List> length [a | a <- [1..5324], length (show a) == length (nub $ show a)]
2939
Although this question had been posted in 2013, I feel like it is still worthy to provide an implementation for reference as other than the algorithm given by Dukeling I couldn't find any implementation on the internet.
I wrote the code in Java for both brute force and Dukeling's permutation algorithm and, if I'm correct, they should always yield the same results.
Hope it can help somebody trying so hard to find an actual running solution.
public class Solution {
public static void main(String[] args) {
test(uniqueDigitsBruteForce(5324), uniqueDigits(5324));
test(uniqueDigitsBruteForce(5222), uniqueDigits(5222));
test(uniqueDigitsBruteForce(5565), uniqueDigits(5565));
}
/**
* A math version method to count numbers with distinct digits.
* #param n
* #return
*/
static int uniqueDigits(int n) {
int[] used = new int[10];
String seq = String.valueOf(n);
char[] ca = seq.toCharArray();
int uniq = 0;
for (int i = 1; i <= ca.length - 1; i++) {
uniq += uniqueDigitsOfLength(i);
}
uniq += (getInt(ca[0]) - 1) * factorial(9) / factorial(9 - ca.length + 1);
used[getInt(ca[0])] = 1;
for (int i = 1; i < ca.length; i++) {
int count = 0;
for (int j = 0; j < getInt(ca[i]); j++) {
if (used[j] != 1) count++;
}
uniq += count * factorial(9 - i) / factorial(9 - ca.length + 1);
if (used[getInt(ca[i])] == 1)
break;
used[getInt(ca[i])] = 1;
}
if (isUniqueDigits(n)) {
uniq += 1;
}
return uniq;
}
/**
* A brute force version method to count numbers with distinct digits.
* #param n
* #return
*/
static int uniqueDigitsBruteForce(int n) {
int count = 0;
for (int i = 1; i <= n; i++) {
if (isUniqueDigits(i)) {
count++;
}
}
return count;
}
/**
* http://oeis.org/A073531
* #param n
* #return
*/
static int uniqueDigitsOfLength(int n) {
if (n < 1) return 0;
int count = 9;
int numOptions = 9;
while(--n > 0) {
if (numOptions == 0) {
return 0;
}
count *= numOptions;
numOptions--;
}
return count;
}
/**
* Determine if given number consists of distinct digits
* #param n
* #return
*/
static boolean isUniqueDigits(int n) {
int[] used = new int[10];
if (n < 10) return true;
while (n > 0) {
int digit = n % 10;
if (used[digit] == 1)
return false;
used[digit] = 1;
n = n / 10;
}
return true;
}
static int getInt(char c) {
return c - '0';
}
/**
* Calculate Factorial
* #param n
* #return
*/
static int factorial(int n) {
if (n > 9) return -1;
if (n < 2) return 1;
int res = 1;
for (int i = 2; i <= n; i++) {
res *= i;
}
return res;
}
static void test(int expected, int actual) {
System.out.println("Expected Result: " + expected.toString());
System.out.println("Actual Result: " + actual.toString());
System.out.println(expected.equals(actual) ? "Correct" : "Wrong Answer");
}
}
a python solution is summarized as follow :
the solution is based on the mathematical principle of Bernhard Barker provided previous in the answer list:
thanks to Bernhard's ideal
def count_num_with_DupDigits(self, n: int) -> int:
# Fill in your code for the function. Do not change the function name
# The function should return an integer.
n_str = str(n)
n_len = len(n_str)
n_unique = 0
# get the all the x000 unique digits
if n > 10:
for i in range(n_len-1):
n_unique = n_unique + 9*int(np.math.factorial(9)/np.math.factorial(10-n_len+i+1))
m=0
if m == 0:
n_first = (int(n_str[m])-1)*int(np.math.factorial(9)/np.math.factorial(10-n_len))
m=m+1
count_last=0
n_sec=0
for k in range(n_len-1):
if m == n_len-1:
count_last = int(n_str[m])+1
for l in range(int(n_str[m])+1):a
if n_str[0:n_len-1].count(str(l)) > 0:
count_last = count_last-1
else:
for s in range(int(n_str[k+1])):
if n_str[0:k+1].count(str(s))>0:
n_sec=n_sec
else:
n_sec = int(np.math.factorial(9-m)/np.math.factorial(10-n_len))+n_sec
if n_str[0:k+1].count(n_str[k+1]) > 0:
break
m= m+1
value=n-(n_sec+n_first+n_unique+count_last)
else:
value = 0
return value
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
int rem;
Scanner in=new Scanner(System.in);
int num=in.nextInt();
int length = (int)(Math.log10(num)+1);//This one is to find the length of the number i.e number of digits of a number
int arr[]=new int[length]; //Array to store the individual numbers of a digit for example 123 then we will store 1,2,3 in the array
int count=0;
int i=0;
while(num>0) //Logic to store the digits in array
{ rem=num%10;
arr[i++]=rem;
num=num/10;
}
for( i=0;i<length;i++) //Logic to find the duplicate numbers
{
for(int j=i+1;j<length;j++)
{
if(arr[i]==arr[j])
{
count++;
break;
}
}
}
//Finally total number of digits minus duplicates gives the output
System.out.println(length-count);
}
}
Here is what you want, implemented by Python
def numDistinctDigitsAtMostN(n):
nums = [int(i) for i in str(n+1)]
k = len(str(n+1))
res = 0
# Here is a paper about Number of n-digit positive integers with all digits distinct
# http://oeis.org/A073531
# a(n) = 9*9!/(10-n)!
# calculate the number of n-digit positive integers with all digits distinct
for i in range(1, k):
res += 9 * math.perm(9,i-1)
# count no duplicates for numbers with k digits and smaller than n
for i, x in enumerate(nums):
if i == 0:
digit_range = range(1,x) # first digit can not be 0
else:
digit_range = range(x)
for y in digit_range:
if y not in nums[:i]:
res += math.perm(9-i,k-1-i)
if x in nums[:i]:
break
return res
And here are some good test cases.
They are big enough to test my code.
numDistinctDigitsAtMostN(100) = 90 #(9+81)
numDistinctDigitsAtMostN(5853) = 3181
numDistinctDigitsAtMostN(5853623) = 461730
numDistinctDigitsAtMostN(585362326) = 4104810
To count the subsequences of length 4 of a string of length n which are divisible by 9.
For example if the input string is 9999
then cnt=1
My approach is similar to Brute Force and takes O(n^3).Any better approach than this?
If you want to check if a number is divisible by 9, You better look here.
I will describe the method in short:
checkDividedByNine(String pNum) :
If pNum.length < 1
return false
If pNum.length == 1
return toInt(pNum) == 9;
Sum = 0
For c in pNum:
Sum += toInt(pNum)
return checkDividedByNine(toString(Sum))
So you can reduce the running time to less than O(n^3).
EDIT:
If you need very fast algorithm, you can use pre-processing in order to save for each possible 4-digit number, if it is divisible by 9. (It will cost you 10000 in memory)
EDIT 2:
Better approach: you can use dynamic programming:
For string S in length N:
D[i,j,k] = The number of subsequences of length j in the string S[i..N] that their value modulo 9 == k.
Where 0 <= k <= 8, 1 <= j <= 4, 1 <= i <= N.
D[i,1,k] = simply count the number of elements in S[i..N] that = k(mod 9).
D[N,j,k] = if j==1 and (S[N] modulo 9) == k, return 1. Otherwise, 0.
D[i,j,k] = max{ D[i+1,j,k], D[i+1,j-1, (k-S[i]+9) modulo 9]}.
And you return D[1,4,0].
You get a table in size - N x 9 x 4.
Thus, the overall running time, assuming calculating modulo takes O(1), is O(n).
Assuming that the subsequence has to consist of consecutive digits, you can scan from left to right, keeping track of what order the last 4 digits read are in. That way, you can do a linear scan and just apply divisibility rules.
If the digits are not necessarily consecutive, then you can do some finangling with lookup tables. The idea is that you can create a 3D array named table such that table[i][j][k] is the number of sums of i digits up to index j such that the sum leaves a remainder of k when divided by 9. The table itself has size 45n (i goes from 0 to 4, j goes from 0 to n-1, and k goes from 0 to 8).
For the recursion, each table[i][j][k] entry relies on table[i-1][j-1][x] and table[i][j-1][x] for all x from 0 to 8. Since each entry update takes constant time (at least relative to n), that should get you an O(n) runtime.
How about this one:
/*NOTE: The following holds true, if the subsequences consist of digits in contagious locations */
public int countOccurrences (String s) {
int count=0;
int len = s.length();
String subs = null;
int sum;
if (len < 4)
return 0;
else {
for (int i=0 ; i<len-3 ; i++) {
subs = s.substring(i, i+4);
sum = 0;
for (int j=0; j<=3; j++) {
sum += Integer.parseInt(String.valueOf(subs.charAt(j)));
}
if (sum%9 == 0)
count++;
}
return count;
}
}
Here is the complete working code for the above problem based on the above discussed ways using lookup tables
int fun(int h)
{
return (h/10 + h%10);
}
int main()
{
int t;
scanf("%d",&t);
int i,T;
for(T=0;T<t;T++)
{
char str[10001];
scanf("%s",str);
int len=strlen(str);
int arr[len][5][10];
memset(arr,0,sizeof(int)*(10*5*len));
int j,k,l;
for(j=0;j<len;j++)
{
int y;
y=(str[j]-48)%10;
arr[j][1][y]++;
}
//printarr(arr,len);
for(i=len-2;i>=0;i--) //represents the starting index of the string
{
int temp[5][10];
//COPYING ARRAY
int a,b,c,d;
for(a=0;a<=4;a++)
for(b=0;b<=9;b++)
temp[a][b]=arr[i][a][b]+arr[i+1][a][b];
for(j=1;j<=4;j++) //represents the length of the string
{
for(k=0;k<=9;k++) //represents the no. of ways to make it
{
if(arr[i+1][j][k]!=0)
{
for(c=1;c<=4;c++)
{
for(d=0;d<=9;d++)
{
if(arr[i][c][d]!=0)
{
int h,r;
r=j+c;
if(r>4)
continue;
h=k+d;
h=fun(h);
if(r<=4)
temp[r][h]=( temp[r][h]+(arr[i][c][d]*arr[i+1][j][k]))%1000000007;
}}}
}
//copy back from temp array
}
}
for(a=0;a<=4;a++)
for(b=0;b<=9;b++)
arr[i][a][b]=temp[a][b];
}
printf("%d\n",(arr[0][1][9])%1000000007);
}
return 0;
}
It's easy enough to make a simple sieve:
for (int i=2; i<=N; i++){
if (sieve[i]==0){
cout << i << " is prime" << endl;
for (int j = i; j<=N; j+=i){
sieve[j]=1;
}
}
cout << i << " has " << sieve[i] << " distinct prime factors\n";
}
But what about when N is very large and I can't hold that kind of array in memory? I've looked up segmented sieve approaches and they seem to involve finding primes up until sqrt(N) but I don't understand how it works. What if N is very large (say 10^18)?
The basic idea of a segmented sieve is to choose the sieving primes less than the square root of n, choose a reasonably large segment size that nevertheless fits in memory, and then sieve each of the segments in turn, starting with the smallest. At the first segment, the smallest multiple of each sieving prime that is within the segment is calculated, then multiples of the sieving prime are marked as composite in the normal way; when all the sieving primes have been used, the remaining unmarked numbers in the segment are prime. Then, for the next segment, for each sieving prime you already know the first multiple in the current segment (it was the multiple that ended the sieving for that prime in the prior segment), so you sieve on each sieving prime, and so on until you are finished.
The size of n doesn't matter, except that a larger n will take longer to sieve than a smaller n; the size that matters is the size of the segment, which should be as large as convenient (say, the size of the primary memory cache on the machine).
You can see a simple implementation of a segmented sieve here. Note that a segmented sieve will be very much faster than O'Neill's priority-queue sieve mentioned in another answer; if you're interested, there's an implementation here.
EDIT: I wrote this for a different purpose, but I'll show it here because it might be useful:
Though the Sieve of Eratosthenes is very fast, it requires O(n) space. That can be reduced to O(sqrt(n)) for the sieving primes plus O(1) for the bitarray by performing the sieving in successive segments. At the first segment, the smallest multiple of each sieving prime that is within the segment is calculated, then multiples of the sieving prime are marked composite in the normal way; when all the sieving primes have been used, the remaining unmarked numbers in the segment are prime. Then, for the next segment, the smallest multiple of each sieving prime is the multiple that ended the sieving in the prior segment, and so the sieving continues until finished.
Consider the example of sieve from 100 to 200 in segments of 20. The five sieving primes are 3, 5, 7, 11 and 13. In the first segment from 100 to 120, the bitarray has ten slots, with slot 0 corresponding to 101, slot k corresponding to 100+2k+1, and slot 9 corresponding to 119. The smallest multiple of 3 in the segment is 105, corresponding to slot 2; slots 2+3=5 and 5+3=8 are also multiples of 3. The smallest multiple of 5 is 105 at slot 2, and slot 2+5=7 is also a multiple of 5. The smallest multiple of 7 is 105 at slot 2, and slot 2+7=9 is also a multiple of 7. And so on.
Function primesRange takes arguments lo, hi and delta; lo and hi must be even, with lo < hi, and lo must be greater than sqrt(hi). The segment size is twice delta. Ps is a linked list containing the sieving primes less than sqrt(hi), with 2 removed since even numbers are ignored. Qs is a linked list containing the offest into the sieve bitarray of the smallest multiple in the current segment of the corresponding sieving prime. After each segment, lo advances by twice delta, so the number corresponding to an index i of the sieve bitarray is lo + 2i + 1.
function primesRange(lo, hi, delta)
function qInit(p)
return (-1/2 * (lo + p + 1)) % p
function qReset(p, q)
return (q - delta) % p
sieve := makeArray(0..delta-1)
ps := tail(primes(sqrt(hi)))
qs := map(qInit, ps)
while lo < hi
for i from 0 to delta-1
sieve[i] := True
for p,q in ps,qs
for i from q to delta step p
sieve[i] := False
qs := map(qReset, ps, qs)
for i,t from 0,lo+1 to delta-1,hi step 1,2
if sieve[i]
output t
lo := lo + 2 * delta
When called as primesRange(100, 200, 10), the sieving primes ps are [3, 5, 7, 11, 13]; qs is initially [2, 2, 2, 10, 8] corresponding to smallest multiples 105, 105, 105, 121 and 117, and is reset for the second segment to [1, 2, 6, 0, 11] corresponding to smallest multiples 123, 125, 133, 121 and 143.
You can see this program in action at http://ideone.com/iHYr1f. And in addition to the links shown above, if you are interested in programming with prime numbers I modestly recommend this essay at my blog.
It's just that we are making segmented with the sieve we have.
The basic idea is let's say we have to find out prime numbers between 85 and 100.
We have to apply the traditional sieve,but in the fashion as described below:
So we take the first prime number 2 , divide the starting number by 2(85/2) and taking round off to smaller number we get p=42,now multiply again by 2 we get p=84, from here onwards start adding 2 till the last number.So what we have done is that we have removed all the factors of 2(86,88,90,92,94,96,98,100) in the range.
We take the next prime number 3 , divide the starting number by 3(85/3) and taking round off to smaller number we get p=28,now multiply again by 3 we get p=84, from here onwards start adding 3 till the last number.So what we have done is that we have removed all the factors of 3(87,90,93,96,99) in the range.
Take the next prime number=5 and so on..................
Keep on doing the above steps.You can get the prime numbers (2,3,5,7,...) by using the traditional sieve upto sqrt(n).And then use it for segmented sieve.
There's a version of the Sieve based on priority queues that yields as many primes as you request, rather than all of them up to an upper bound. It's discussed in the classic paper "The Genuine Sieve of Eratosthenes" and googling for "sieve of eratosthenes priority queue" turns up quite a few implementations in various programming languages.
If someone would like to see C++ implementation, here is mine:
void sito_delta( int delta, std::vector<int> &res)
{
std::unique_ptr<int[]> results(new int[delta+1]);
for(int i = 0; i <= delta; ++i)
results[i] = 1;
int pierw = sqrt(delta);
for (int j = 2; j <= pierw; ++j)
{
if(results[j])
{
for (int k = 2*j; k <= delta; k+=j)
{
results[k]=0;
}
}
}
for (int m = 2; m <= delta; ++m)
if (results[m])
{
res.push_back(m);
std::cout<<","<<m;
}
};
void sito_segment(int n,std::vector<int> &fiPri)
{
int delta = sqrt(n);
if (delta>10)
{
sito_segment(delta,fiPri);
// COmpute using fiPri as primes
// n=n,prime = fiPri;
std::vector<int> prime=fiPri;
int offset = delta;
int low = offset;
int high = offset * 2;
while (low < n)
{
if (high >=n ) high = n;
int mark[offset+1];
for (int s=0;s<=offset;++s)
mark[s]=1;
for(int j = 0; j< prime.size(); ++j)
{
int lowMinimum = (low/prime[j]) * prime[j];
if(lowMinimum < low)
lowMinimum += prime[j];
for(int k = lowMinimum; k<=high;k+=prime[j])
mark[k-low]=0;
}
for(int i = low; i <= high; i++)
if(mark[i-low])
{
fiPri.push_back(i);
std::cout<<","<<i;
}
low=low+offset;
high=high+offset;
}
}
else
{
std::vector<int> prime;
sito_delta(delta, prime);
//
fiPri = prime;
//
int offset = delta;
int low = offset;
int high = offset * 2;
// Process segments one by one
while (low < n)
{
if (high >= n) high = n;
int mark[offset+1];
for (int s = 0; s <= offset; ++s)
mark[s] = 1;
for (int j = 0; j < prime.size(); ++j)
{
// find the minimum number in [low..high] that is
// multiple of prime[i] (divisible by prime[j])
int lowMinimum = (low/prime[j]) * prime[j];
if(lowMinimum < low)
lowMinimum += prime[j];
//Mark multiples of prime[i] in [low..high]
for (int k = lowMinimum; k <= high; k+=prime[j])
mark[k-low] = 0;
}
for (int i = low; i <= high; i++)
if(mark[i-low])
{
fiPri.push_back(i);
std::cout<<","<<i;
}
low = low + offset;
high = high + offset;
}
}
};
int main()
{
std::vector<int> fiPri;
sito_segment(1013,fiPri);
}
Based on Swapnil Kumar answer I did the following algorithm in C. It was built with mingw32-make.exe.
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
const int MAX_PRIME_NUMBERS = 5000000;//The number of prime numbers we are looking for
long long *prime_numbers = malloc(sizeof(long long) * MAX_PRIME_NUMBERS);
prime_numbers[0] = 2;
prime_numbers[1] = 3;
prime_numbers[2] = 5;
prime_numbers[3] = 7;
prime_numbers[4] = 11;
prime_numbers[5] = 13;
prime_numbers[6] = 17;
prime_numbers[7] = 19;
prime_numbers[8] = 23;
prime_numbers[9] = 29;
const int BUFFER_POSSIBLE_PRIMES = 29 * 29;//Because the greatest prime number we have is 29 in the 10th position so I started with a block of 841 numbers
int qt_calculated_primes = 10;//10 because we initialized the array with the ten first primes
int possible_primes[BUFFER_POSSIBLE_PRIMES];//Will store the booleans to check valid primes
long long iteration = 0;//Used as multiplier to the range of the buffer possible_primes
int i;//Simple counter for loops
while(qt_calculated_primes < MAX_PRIME_NUMBERS)
{
for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
possible_primes[i] = 1;//set the number as prime
int biggest_possible_prime = sqrt((iteration + 1) * BUFFER_POSSIBLE_PRIMES);
int k = 0;
long long prime = prime_numbers[k];//First prime to be used in the check
while (prime <= biggest_possible_prime)//We don't need to check primes bigger than the square root
{
for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
if ((iteration * BUFFER_POSSIBLE_PRIMES + i) % prime == 0)
possible_primes[i] = 0;
if (++k == qt_calculated_primes)
break;
prime = prime_numbers[k];
}
for (i = 0; i < BUFFER_POSSIBLE_PRIMES; i++)
if (possible_primes[i])
{
if ((qt_calculated_primes < MAX_PRIME_NUMBERS) && ((iteration * BUFFER_POSSIBLE_PRIMES + i) != 1))
{
prime_numbers[qt_calculated_primes] = iteration * BUFFER_POSSIBLE_PRIMES + i;
printf("%d\n", prime_numbers[qt_calculated_primes]);
qt_calculated_primes++;
} else if (!(qt_calculated_primes < MAX_PRIME_NUMBERS))
break;
}
iteration++;
}
return 0;
}
It set a maximum of prime numbers to be found, then an array is initialized with known prime numbers like 2, 3, 5...29. So we make a buffer that will store the segments of possible primes, this buffer can't be greater than the power of the greatest initial prime that in this case is 29.
I'm sure there are a plenty of optimizations that can be done to improve the performance like parallelize the segments analysis process and skip numbers that are multiple of 2, 3 and 5 but it serves as an example of low memory consumption.
A number is prime if none of the smaller prime numbers divides it. Since we iterate over the prime numbers in order, we already marked all numbers, who are divisible by at least one of the prime numbers, as divisible. Hence if we reach a cell and it is not marked, then it isn't divisible by any smaller prime number and therefore has to be prime.
Remember these points:-
// Generating all prime number up to R
// creating an array of size (R-L-1) set all elements to be true: prime && false: composite
#include<bits/stdc++.h>
using namespace std;
#define MAX 100001
vector<int>* sieve(){
bool isPrime[MAX];
for(int i=0;i<MAX;i++){
isPrime[i]=true;
}
for(int i=2;i*i<MAX;i++){
if(isPrime[i]){
for(int j=i*i;j<MAX;j+=i){
isPrime[j]=false;
}
}
}
vector<int>* primes = new vector<int>();
primes->push_back(2);
for(int i=3;i<MAX;i+=2){
if(isPrime[i]){
primes->push_back(i);
}
}
return primes;
}
void printPrimes(long long l, long long r, vector<int>*&primes){
bool isprimes[r-l+1];
for(int i=0;i<=r-l;i++){
isprimes[i]=true;
}
for(int i=0;primes->at(i)*(long long)primes->at(i)<=r;i++){
int currPrimes=primes->at(i);
//just smaller or equal value to l
long long base =(l/(currPrimes))*(currPrimes);
if(base<l){
base=base+currPrimes;
}
//mark all multiplies within L to R as false
for(long long j=base;j<=r;j+=currPrimes){
isprimes[j-l]=false;
}
//there may be a case where base is itself a prime number
if(base==currPrimes){
isprimes[base-l]= true;
}
}
for(int i=0;i<=r-l;i++){
if(isprimes[i]==true){
cout<<i+l<<endl;
}
}
}
int main(){
vector<int>* primes=sieve();
int t;
cin>>t;
while(t--){
long long l,r;
cin>>l>>r;
printPrimes(l,r,primes);
}
return 0;
}
I'm looking for an algorithm to generate all permutations with repetition of 4 elements in list(length 2-1000).
Java implementation
The problem is that the algorithm from the link above alocates too much memory for calculation. It creates an array with length of all possible combination. E.g 4^1000 for my example. So i got heap space exception.
Thank you
Generalized algorithm for lazily-evaluated generation of all permutations (with repetition) of length X for a set of choices Y:
for I = 0 to (Y^X - 1):
list_of_digits = calculate the digits of I in base Y
a_set_of_choices = possible_choices[D] for each digit D in list_of_digits
yield a_set_of_choices
If there is not length limit for repetition of your 4 symbols there is a very simple algorithm that will give you what you want. Just encode your string as a binary number where all 2 bits pattern encode one of the four symbol. To get all possible permutations with repetitions you just have to enumerate "count" all possible numbers. That can be quite long (more than the age of the universe) as a 1000 symbols will be 2000 bits long. Is it really what you want to do ? The heap overflow may not be the only limit...
Below is a trivial C implementation that enumerates all repetitions of length exactly n (n limited to 16000 with 32 bits unsigned) without allocating memory. I leave to the reader the exercice of enumerating all repetitions of at most length n.
#include <stdio.h>
typedef unsigned char cell;
cell a[1000];
int npack = sizeof(cell)*4;
void decode(cell * a, int nbsym)
{
unsigned i;
for (i=0; i < nbsym; i++){
printf("%c", "GATC"[a[i/npack]>>((i%npack)*2)&3]);
}
printf("\n");
}
void enumerate(cell * a, int nbsym)
{
unsigned i, j;
for (i = 0; i < 1000; i++){
a[i] = 0;
}
while (j <= (nbsym / npack)){
j = 0;
decode(a, nbsym);
while (!++a[j]){
j++;
}
if ((j == (nbsym / npack))
&& ((a[j] >> ((nbsym-1)%npack)*2)&4)){
break;
}
}
}
int main(){
enumerate(a, 5);
}
You know how to count: add 1 to the ones spot, if you go over 9 jump back to 0 and add 1 to the tens, etc..
So, if you have a list of length N with K items in each spot:
int[] permutations = new int[N];
boolean addOne() { // Returns true when it advances, false _once_ when finished
int i = 0;
permutations[i]++;
while (permutations[i] >= K) {
permutations[i] = 0;
i += 1;
if (i>=N) return false;
permutations[i]++;
}
return true;
}