There is a natural number n. You have to find a pair of natural numbers x, y whose sum is n and also have the least energy among other pair having the sum n.
Energy(x) = sum of all digits of x
Total Energy = Energy(x) + Energy(y)
1 <= n <= 10^9
For eg,
n = 10000
A few pairs:
5000 + 5000 -> Energy = 10
1000 + 9000 -> Energy = 10
9999 + 1 -> Energy = 37
2999 + 7001 -> Energy = 37
So possible answers are:
(5000, 5000), (1000, 9000) etc
I have tried the solution noted above so far but it is not an optimized approach
I will loop from 1 to n-1 and and try all pairs and check their sum of digits but it will take too much time for big numbers.
e.g.
n= 50
1,49--> energy 14
2,48--> energy 14
3,47--> energy 14
4,46--> energy 14
5,45--> energy 14
.
.
.
.
10,40-->energy 5
(Edited) After some thought, I arrived at the following solution. Would appreciate if somebody can come up with a better solution
public int sum(int n) {
String s = String.valueOf(n);
if (isNonZeroOnlyOne(n)) {
int num = getNonZeroNo(n);
if (num == 1)
return 10;
return num;
}
return calculateEnergy(s);
}
private int calculateEnergy(String s) {
int sum = 0;
for(int i=0; i<s.length(); i++)
sum += s.charAt(i) - '0';
return sum;
}
private int getNonZeroNo(int n) {
String s = String.valueOf(n);
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c != '0')
return c-'0';
}
return '0';
}
private boolean isNonZeroOnlyOne(int n) {
String s = String.valueOf(n);
int count = 0;
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c != '0')
count++;
if (count > 1)
return false;
}
return true;
}
It's simple.
if n is of type 10^x then the answer is 10. otherwise answer is the sum of digits of n.
The idea here is to break down the number into a pair containing digits less than that are present in n. if you break down into smaller digits then sum remains the same as the original number.
example for 7= 1-6,2-5,3-4.
for a number like 100, 1000....
digit 1 can't be broken down into further pairs, so we try to make 10 as the sum of digit so that the sum becomes n.
like for 10=5-5,2-8,3-7
100=20-80,40-60
for other numbers, like 123
it can be broken into 100-23, 120-3, 111-12... all will give you sum 6. which is the sum of digits of the original number.
if you try to break down into further pairs like 80-43, 52-71, you will see that the digit sum increases as you broken down to a number containing digits which is higher than those are present in n. like 8 4,5,7 are greater than 3.
The least energy can be derived by a simple formula.
1) Given N > 100, the pair can be N-100 and 100 , and the energy will be same as the energy of N.
eg : N = 500 ; Pair = 400 and 100 ; Energy = 5
2) N >=10 and N <=100 , pair = N-10 and 10
eg : N = 50 ; Pair = 40 and 10 ; Energy = 5
3) N >=2 and N <=10 , pair = N-1 and 1
eg : N = 5 ; Pair = 4 and 1 ; Energy = 5
I spent more than 1 hour on this problem. What should be answer for n = 1? So I think n should be greater than 1. I am assuming n > 1.
So brute-force solution won't work here because n is huge enough. So you need more optimized solution. You need to think think about how many times you have to carry 1 in the sum to make n. It is at most 9 times!
If you have some basic idea with digit-dp(Dynamic Programming) then this problem is easy. Try to place all possible digit on a place of n and take minimum energy among them. This problem is easy when you fully understand digit-dp technique. You can learn it from here and here.
For practice, you can find a lot of problems here (Dynamic programming section).
For your references, I wrote this code just now and it is working properly. Hope you can use this as a reference.
#include <bits/stdc++.h>
using namespace std;
const string INF_STRING = "9999999";
const int INF_INT = 9999999;
pair<string, int> INF = make_pair(INF_STRING, INF_INT);
int nod;
int digits[10];
int num_of_digits(int a) {
int cnt = 0;
while(a) {
digits[cnt] = a % 10;
a = a / 10;
cnt++;
}
return cnt;
}
pair<string, int> dp[10][2][2][2];
pair<string, int> solve(int ind, int carry, bool is1, bool is2) {
if(ind >= nod) {
if(carry != 0 || !is1 || !is2) return INF;
return make_pair("", 0);
}
pair<string, int> &ret = dp[ind][carry][is1][is2];
if(ret.second != -1) return ret;
ret = INF;
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 10; j++) {
int s = (i + j + carry);
pair<string, int> cur = INF;
if(s % 10 == digits[ind]) {
cur = solve(ind + 1, s / 10, is1 || (i > 0? 1:0), is2 || (j > 0? 1:0));
}
if((cur.second + i + j) < ret.second) {
ret.second = cur.second + i + j;
ret.first = cur.first + (char)(i + '0');
}
}
}
return ret;
}
int stringToInt(string num) {
stringstream ss;
ss<<num;
int ret;
ss >> ret;
return ret;
}
int main() {
int i, t, cases = 1, j, k, pos;
int n;
scanf("%d", &n);
nod = num_of_digits(n);
for(int i = 0; i < 10; i++) {
for(int j = 0; j < 2; j++) {
dp[i][j][0][0] = make_pair(INF_STRING, -1);
dp[i][j][0][1] = make_pair(INF_STRING, -1);
dp[i][j][1][0] = make_pair(INF_STRING, -1);
dp[i][j][1][1] = make_pair(INF_STRING, -1);
}
}
pair<string, int> res = solve(0, 0, 0, 0);
string num1_str = res.first;
int num1 = stringToInt(num1_str);
int num2 = n - num1;
printf("Minimum Energy: %d\n", res.second);
printf("Num1 = %d, Num2 = %d\n", num1, num2);
return 0;
}
/*
Input:
10000
Output:
Minimum energy: 10
Num1 = 1000, Num2 = 9000
*/
Here is the answer in javascript in simple way.
function calculateEnergy(n) {
let e = 0
while(n > 0) {
e += n % 10
n = Math.floor(n / 10)
}
return e
}
function countMinEnergy(n) {
let minE = n
let i = 1
while(i <= n/2) {
let e = calculateEnergy(i) + calculateEnergy(n - i)
minE = e < minE ? e : minE
i++
}
return minE
}
countMinEnergy(4325)
Here is scala solution
object LeastEnergyPair extends App {
private def getCountOfPair(array: Array[Int],sum: Int): mutable.Set[(Int, Int)] = {
val seen = mutable.Set[Int]()
val out = mutable.Set[(Int,Int)]()
array map { x =>
val target = sum - x
if (seen.contains(target) || target*2 == sum)
out += ((Math.min(x,target),Math.max(x,target)))
else
seen += x
}
println(out)
out
}
private def sum(i:Int): Int = i.toString.toCharArray.map(_.asDigit).sum
def findLeastEnergyPair(a: mutable.Set[(Int,Int)]): (Int,Int) = {
var min = Int.MaxValue
var minPair = (0,0)
a.foreach {
case (i,j) =>
if (sum(i) + sum(j) < min) {
min = sum(i) + sum(j)
minPair = (i,j)
println(s"$min ----- $minPair")
}
}
minPair
}
println(findLeastEnergyPair(getCountOfPair((1 to 10000).toArray, 10000)))
}
The below logic will cover all scenarios
if (N%10 == 0) {
x1= (N/10);
x2 = N-x1
}else{
x1 = N-10;
x2 = 10;
}
I am solving Codility problem CountSemiprimes: Count the semiprime numbers in the given range [a..b].
Task description
A prime is a positive integer X that has exactly two distinct divisors: 1 and X. The first few prime integers are 2, 3, 5, 7, 11 and 13.
A semiprime is a natural number that is the product of two (not necessarily distinct) prime numbers. The first few semiprimes are 4, 6, 9, 10, 14, 15, 21, 22, 25, 26.
You are given two non-empty arrays P and Q, each consisting of M integers. These arrays represent queries about the number of semiprimes within specified ranges.
Query K requires you to find the number of semiprimes within the range (P[K], Q[K]), where 1 ≤ P[K] ≤ Q[K] ≤ N.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..50,000];
M is an integer within the range [1..30,000];
each element of arrays P, Q is an integer within the range [1..N];
P[i] ≤ Q[i].
My solution
My current score is 66% and problem is preformance for large data set:
large random, length = ~30,000
all max ranges
Test says, that it should take about 2sec, but my solution takes over 7sec.
This is my current solution
class Solution {
private static List<Integer> getPrimes(int max) {
List<Integer> primes = new ArrayList<>(max / 2);
for (int i = 0; i < max; i++)
if (isPrime(i))
primes.add(i);
return primes;
}
private static boolean isPrime(int val) {
if (val <= 1)
return false;
if (val <= 3)
return true;
for (int i = 2, sqrt = (int)Math.sqrt(val); i <= sqrt; i++)
if (val % i == 0)
return false;
return true;
}
private static boolean[] getSemiPrimes(int N) {
List<Integer> primes = getPrimes(N);
boolean[] semiPrimes = new boolean[N + 1];
for (int i = 0; i < primes.size(); i++) {
if (primes.get(i) > N)
break;
for (int j = i; j < primes.size(); j++) {
if (primes.get(j) > N || N / primes.get(i) < primes.get(j))
break;
int semiPrime = primes.get(i) * primes.get(j);
if (semiPrime <= N)
semiPrimes[semiPrime] = true;
}
}
return semiPrimes;
}
public static int[] solution(int N, int[] P, int[] Q) {
boolean[] semiPrimes = getSemiPrimes(N);
int[] res = new int[P.length];
for (int i = 0; i < res.length; i++)
for (int j = P[i]; j <= Q[i]; j++)
if (semiPrimes[j])
res[i]++;
return res;
}
}
Any ideas about improving performance? My last one was to remove Set for holding semi-primes with array. It helped me to solve couple of performance tests.
A Java solution which scores 100% is as follow:
Find the set of prime numbers which their products is not greater than N
create semi-prime from them as a bit wise array of 0 and 1
create a prefix sum of the semi-primes
calculate the queries from P[i] to Q[i] in O(M)
The whole algorithm is of O(N * log(log(N)) + M) stated by the Codility's test result evaluation.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CountSemiPrime {
public static void main(String[] args) {
int[] P = new int[] {1, 4, 16};
int[] Q = new int[] {26, 10, 20};
System.out.println( Arrays.toString( new CountSemiPrime().solution( 26, P, Q ) ) );
}
public int[] solution(int N, int[] P, int[] Q) {
Integer[] primes = sieve(N/2+1);
int[] temp = new int[N+1];
for (int i = 0; i < primes.length; i++) {
for (int j = 0; j < primes.length; j++) {
int semiPrime = primes[i] * primes[j];
if(semiPrime <= N)
temp[semiPrime] = 1;
}
}
int[] prefix = new int[N+1];
for (int i = 1; i < temp.length; i++) {
prefix[i] = temp[i] + prefix[i-1];
}
int[] retVal = new int[P.length];
for (int i = 0; i < retVal.length; i++) {
retVal[i] = prefix[Q[i]] - prefix[P[i]-1];
}
return retVal;
}
public Integer[] sieve(int n) {
boolean[] temp = new boolean[n+1];
for (int i = 0; i < temp.length; i++) {
temp[i] = true;
}
temp[0] = temp[1] = false;
int i = 2;
while (i * i <= n) {
removeProducts( temp, i );
i++;
}
List<Integer> ret = new ArrayList<>();
for (int j = 0; j < temp.length; j++) {
if(temp[j])
ret.add( j );
}
return ret.toArray( new Integer[ret.size()] );
}
private void removeProducts(boolean[] temp, int i) {
for (int j = i*i; j < temp.length; j++) {
if(temp[j] && j % i == 0) {
temp[j] = false;
}
}
}
}
You can precompute an array A of size N+1, which stores at A[i] the number of semiprimes less than or equal to i. Then a query p, q can be computed immediately: the number of semiprimes between p and q (inclusive) is A[q] - A[p-1].
This array can be computed efficiently: let P be an array of primes less than or equal to N/2. Then (in java-like pseudocode):
A = new int[N+1]
for (int p : P) {
for (int q : P) {
if (p*q > N || q > p) break;
A[p*q] = 1
}
}
for (int i = 1; i <= N; i++)
A[i] += A[i-1]
This works by marking the semiprimes with a 1 in the array, and then taking a cumulative sum. It runs in better than O(N^2) and worse than O(N) time -- there's about N/2logN primes in P, so the first part is O((N/logN)^2), and the summing-up is O(N). [Note: I guess the first part has better complexity than O((N/log N)^2) because of the early termination of the inner loop, but I've not proved that]. Computing the primes in P is O(N log log N) using the sieve of Erastothenes.
A Python version of this program takes 0.07s to precompute A for N=50000, and to perform 30000 queries. It gets a perfect score (100) when run on codility, and codility reports that it detects the code to be have complexity O(N log(log(N)) + M).
Ruby 100% solution
require 'prime'
require 'set'
def solution(n, p, q)
primes = Prime::EratosthenesGenerator.new.take_while {|i| i <= n/2 }
sqrt = Math.sqrt(n)
semiprimes = primes.each_with_index.inject(Set.new) do |acc, (e,i)|
break acc if e > sqrt.to_i
primes[i..-1].each{ |pr| e*pr > n ? break : acc << e*pr }
acc
end
offsets = semiprimes.sort.each_with_index.inject([]) {|acc,(el,i)| acc[el] = i+1;acc }
p.each_with_index.inject([]) do |acc, (el,i)|
next acc << 0 unless offsets[el..q[i]]
left = offsets[el..q[i]].detect{|a| a}
next acc << 0 unless left
right = offsets[el..q[i]].reverse_each.detect{|a| a}
acc << ((left..right).size)
end
end
My solution uses Sieve of Eratosthenes such that smallest prime factor of number N is stored in the array Factor[N].
Then if Factor[N/Factor[N]] = 0, we have a semi prime number incrementing a sum scan.
The entry r of the returned array will then be:
A[r]=Inclusive_scan[Q[r]]-Inclusive_scan[P[r]-1].
Here the corresponding python code (100% task score):
def solution(N, P, Q):
A=len(P)*[0]
if N<4:
return A
#Minimum prime factor of n stored in Factor[n]
Factor = [0] * (N + 1)
i = 2
while (i * i <= N):
if (Factor[i] == 0):
k = i * i
while (k <= N):
if (Factor[k] == 0):
Factor[k] = i;
k += i
i += 1
#Count semi prime numbers and store
#sum scan in array Incluse_scan
Incluse_scan=[0] * (N + 1)
cnt_semi=0
for k in range(4,N+1):
if Factor[k]!=0:
d=int(k/Factor[k])
if Factor[d]==0:
cnt_semi+=1
Incluse_scan[k]=cnt_semi
#Do the difference of semi prime counters
for r in range(0,len(P)):
if(P[r]<=4):
min_inclusive=0
else:
min_inclusive=P[r]-1
A[r]=Incluse_scan[Q[r]]-Incluse_scan[min_inclusive]
return A
this is my 100% solution in C++. you can find other answers in my github in cpp:
vector<int> getFactArr(int n) {
vector<int> f(n+1, 0);
f[1] = 1;
int i = 2;
while (i * i <= n) {
if (f[i] == 0) {
int k = i * i;
while (k <= n) {
if (f[k] == 0)
f[k] = i;
k+=i;
}
}
i++;
}
return f;
}
vector<int> solution(int N, vector<int> &P, vector<int> &Q) {
vector<int> F = getFactArr(N);
vector<int> prefix_semi_primes(N + 1, 0);
for (int x = 1; x <= N; x++) {
if (F[x] > 0 && F[x / F[x]] == 0)
prefix_semi_primes[x]++;
prefix_semi_primes[x] += prefix_semi_primes[x - 1];
}
const int M = P.size();
vector<int> ans(M, 0);
for (int i = 0; i < M; i++) {
ans[i] = prefix_semi_primes[Q[i]] - prefix_semi_primes[P[i] - 1];
}
return ans;
}
This was an interesting problem. I tried it and got 88% score.
Here is my strategy:
I used Sieve of Eratosthenes for getting a BitSet for primes.
Now I looped over that BitSet and added all the primes in a primeList.
My strategy for finding semi-primes was a bit interesting and I reached to this strategy incrementally.
private static boolean isSemiPrime(int n) {
if(n==1 || n==0 || primeBitSet.get(n))
return false;
int firstFactor = findFirstFactor(n);
if(firstFactor==0 || firstFactor==1)
return false;
return isPrime(n / firstFactor);
}
private static int findFirstFactor(int n) {
for (int i = 0; i < primeList.size(); i++) {
if (n % primeList.get(i) == 0)
return primeList.get(i);
}
// should never be the case
return 0;
}
I'm not very sure why I got 88% score. (What I'm missing)
But the most interesting and worth noting part was the strategy to check whether a given number is Semi-prime or not:
Find the first prime factor of the given number
Then checking that the quotient of the given number and the first-prime-factor is a prime or not.
If it is prime, then the given number is a semi-prime, otherwise the given number is not a semi prime.
Note that I also did a very naive form of book-keeping where I made a cumulative array which stores the total number of semi-primes till index x. One time filling this array and answering each of the query in O(1) is again obvious optimization.
Not related to the solution, but my Task Score was 88%, Correctness 100% and Performance 80%. I'll be happy to hear suggestions and anything that I missed.
Hope this helps. :)
const isSemiPrime = (num) => {
let cnt = 0
for (let i = 2; cnt < 2 && i * i <= num; ++i) {
while (num % i == 0) {
num /= i
++cnt
}
}
if (num > 1)++cnt
return cnt == 2 ? true : false
}
console.log(
[4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49, 51, 55].filter(isSemiPrime)
.length
)
Here the Javascript version of the solution, but it is 55%:
function solution(N, P, Q) {
function isPrime(num) {
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
const min = Math.min(...P)
const max = Math.max(...Q)
const A = []
for(let i=min;i<max;i++) {
for(let j=min;j<max;j++) {
if (isPrime(i) && isPrime(j)) {
const prod = j * i
if (prod > max) break
if (A.includes(prod)) continue
A.push(j * i)
}
}
}
const result = []
for(let i=0;i<P.length;i++) {
for(let j=P[i];j<=Q[i];j++) {
result[i] = result[i] || 0
if (A.includes(j)) {
result[i]++
}
}
}
return result
}
I would like to mention that the method you use for finding primes is inefficient.
Your code:
private static List<Integer> getPrimes(int max) {
List<Integer> primes = new ArrayList<>(max / 2);
** for (int i = 0; i < max; i++)
** if (isPrime(i))
** primes.add(i);
return primes;
}
private static boolean isPrime(int val) {
if (val <= 1)
return false;
if (val <= 3)
return true;
** for (int i = 2, sqrt = (int)Math.sqrt(val); i <= sqrt; i++)
** if (val % i == 0)
** return false;
return true;
}
I have marked the lines to pay attention to.
I would do something like this:
private static List<Integer> getPrimes(int max) {
List<Integer> primes = new ArrayList<>(max / 2);
primes.add(2);
for (int i = 3; i < max; i++)
if (isPrime(i, primes))
primes.add(i);
return primes;
}
private static boolean isPrime(int val, List<Integer> primes) {
int sqrtv = Math.sqrt(val);
for (int i = 0; i < primes.length(); i++)
{
int prime = primes.get(i);
if (val % primes.get(i) == 0)
{
return false;
} else if (prime > sqrtv) {
return true;
}
}
return true;
}
This plays on the fact that:
the only call to isPrime is from getPrimes. getPrimes will always call val in ascending order.
by the time isPrime is called with the parameter val, getPrimes has already got a list of all primes that are smaller than val.
there's no point in dividing with non-primes when determining primes. If we already know that a number 'a' is not divisible by 2, then why bother with dividing it by 4, 6, 8 or 10? If we know it isn't divisible by 3, then it won't be divisible by 9... so all of the non-prime checks are filtered by using the previously calculated primes only to perform the checking.
Here is my 100% in c++. I'm using prefixSum. Time complexity O(N * log(log(N)) + M).
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
vector<int> solution(int N, vector<int> &P, vector<int> &Q)
{
vector<bool> sieve(N, true);
vector<int> ret;
sieve[0] = sieve[1] = false;
int i = 2;
while (i * i <= N)
{
if (sieve[i])
{
int k = i * i;
while (k <= N)
{
sieve[k] = false;
k += i;
}
}
i++;
}
vector<int> prefixSum(N + 1, 0);
for (int i = 2; i <= sqrt(N); i++)
if (sieve[i])
for (int j = i; j <= N; j++)
{
if (j * i > N)
break;
if (sieve[j])
prefixSum[j * i]++;
}
int carry;
for (unsigned int i = 5; i < prefixSum.size(); i++)
{
carry = prefixSum[i - 1];
prefixSum[i] += carry;
}
for (unsigned int i = 0; i < P.size(); i++)
ret.push_back(prefixSum[Q[i]] - prefixSum[P[i] - 1]);
return ret;
}
A 100% solution broken down. https://app.codility.com/demo/results/trainingGVNHKU-MA5/
Firstly use the sieve of Eratosthenes to workout what is prime.
def get_sieve(n):
# Use the sieve or Eratosthenes to produce an array of primes
# where factor[n] == 0 indicates a prime number
factors = [0] * (n+1)
i=2
i2 = i*i
while (i2 <= n):
if not factors[i]:
k = i2
while k <= n:
if not factors[k]:
factors[k] = i
k += i
i += 1
i2 = i*i
return factors
Next, determine if the number is semi prime. If both its factors are prime its semiprime.
def is_semi_prime(n, factors):
if factors[n]: # Check its not a prime
for r in range(int(n**.5)+1, 1, -1):
if not n%r:
d = n//r
return (not factors[d]) and (not factors[r])
return False
Then scan the range up to N numbers to count slope of increasing semi primes. simply measure the slope within a slice to see how many semi primes occur during that slice.
def solution(N, P, Q):
# produce a slope of increasing semi primes
factors = get_sieve(N)
slope = [0] * (N+1)
for i in range(1, N+1):
slope[i] = slope[i-1] + is_semi_prime(i, factors) # Auto casting!! :-)
# Optimus Prime!
# print(list(enumerate(slope)))
return [slope[Q[j]] - slope[P[j]-1] for j in range(len(P))]
https://github.com/niall-oc/things/blob/master/codility/count_semiprimes.py
and more at
https://github.com/niall-oc/things/blob/master/codility/
I took a slightly different approach. The other efficient solutions in this thread builds a regular Sieve of Eratosthenes (F) with a twist of recording the smallest prime factor in the slot, so semiprimes are those x for which F[x] > 0 and F[x // F[x]] == 0, i.e. dividing by the smallest prime factor yields another prime number.
My approach is a little slower but does not use division, and builds an interesting intermediate: a sieve that computes exactly how many factors make up the prime factorization of the number (and zeros at the primes). For each prime p, I would increment the sieve at position 2p, 3p, 4p,... but also count a factor for p^2, 2p^2, 3p^2..., p^3, 2p^3, 3p^3, 4p^3,... and so forth. The slot for 16 stores the value 4 (prime factorization: 2*2*2*2), because the slot gets hit by visits from 2, 2^2, 2^3 and 2^4.
Then the semiprimes are those positions having exactly 2 prime factors.
After that I build a prefix count of semiprimes with which to answer the queries in constant time.
def solution(N, P, Q):
num_factors = [0] * (N+1)
for i in range(2, N+1):
if num_factors[i] == 0:
# Count visits to multiples of i by adding i each time
add_visit = i+i
while add_visit < N+1:
num_factors[add_visit] += 1
add_visit += i
# But squares of prime count as 2 factors, cubes count as 3 etc,
# so also run visits for multiples of the squares, cubes, etc.
power_prime = i*i
while power_prime < N+1:
visit = power_prime
while visit < N+1:
num_factors[visit] += 1
visit += power_prime
power_prime *= i
semiprime_prefix_count = [0] * (N+1)
for i in range(1, N+1):
semiprime_prefix_count[i] = semiprime_prefix_count[i-1]
if num_factors[i] == 2:
semiprime_prefix_count[i] += 1
results = []
for p, q in zip(P, Q):
results.append(semiprime_prefix_count[q] - semiprime_prefix_count[p-1])
#print(list(zip(range(N+1),num_factors)))
#print(list(zip(range(N+1),semiprime_prefix_count)))
return results
Use the usual sieve to get the prime numbers up to N.
Use the prime number to get semi-prime numbers up to N. You can do this by checking any number for two prime factors.
Create prefix sums to store the number of semi-primes up to a particular index.
Finally, get the semi prime counts by subtracting the numbers at the query end and start.
vector<int> solution(int N, vector<int> &P, vector<int> &Q)
{
vector<int> sieve(N, 0);
for (int prime = 2; prime * prime <= N; ++prime) {
for (int composite = prime * prime; composite <= N; composite += prime) {
if (!sieve[composite - 1]) sieve[composite - 1] = prime;
}
}
vector<int> semi_primes;
for (int i = 3; i < N; ++i) {
const int e = sieve[i];
if (e > 0 && !sieve[i / e]) semi_primes.push_back(i + 1);
}
if (semi_primes.empty()) semi_primes.push_back(0);
vector<int> prefix_sums(N + 1, 0);
for (int i = 1, spi = 0; i <= N; ++i) {
prefix_sums[i] = ((semi_primes[spi] != i) ? spi : ++spi);
}
int M = P.size();
vector<int> semi_prime_counts(M, 0);
for (int i = 0; i < M; ++i) {
semi_prime_counts[i] = prefix_sums[Q[i]] - prefix_sums[P[i] - 1];
}
return semi_prime_counts;
}
function solution(N, P, Q) {
// write your code in JavaScript (Node.js 8.9.4)
let pr =[];let fn =[]
for(var i=2;i<=N;i++){
if(isPrime(i)){
pr.push(i)
}
}
let spr = [],mul,br=0
for(var i=0;i<pr.length;i++){
for(var j=0; j <pr.length;j++){
mul = pr[i] * pr[j];
if(mul <= N) {
spr.push(mul)
}else{
br =1;
break;
}
}
// if(br==1) break;
}
let nm = [];
//let o =0
for(var i=0;i<=N;i++){
if(spr.indexOf(i) >=0){
// ++o
nm.push(1)
}else{
nm.push(0)
}
}
// spr = Array.from(new Set(spr))
// spr.sort((a,b)=> a- b)
let a,b,c
for(var i =0;i<P.length;i++){
// a= findme(P[i],spr)
// b= findme(Q[i],spr)
// a= nm[P[i]]
// b= nm[Q[i]]
c= nm.slice(P[i],Q[i]+1).reduce((a,b)=> a+b)
// c=c <=0 ? 0 : c+1
// fn.push(b - a + 1)
fn.push(c)
}
return fn
}
function findme(a,arr){
for(var i= 0; i< arr.length;i++){
if(a <= arr[i]) return i;
}
}
function isPrime(num){
if (num ===2) return true
for(var i = 2; i < num; i++)
if(num % i === 0) return false;
return num > 1;
}
/**
* https://app.codility.com/demo/results/trainingPBRVXK-28Q/
* time complexity: O(N * log(log N) + M
* space complexity: O(2N + N)
*/
public class CountSemiPrime {
/**
* 2D array for sieving numbers 1..N
* 1 - prime, 2 - semiprime, 3 - composite
*/
public int[][] sieve(int N) {
int[][] sieve = new int[N+1][1];
for (int i=1; i<=N; i++) {
sieve[i][0] = 1; // make prime default
}
for (int i=2; i<= N; i++) {
if (sieve[i][0] == 1) { // if this num is prime, tag its multiples as semi-prime
int next_number = i + i;
while (next_number <= N) {
sieve[next_number][0] = 2;
next_number += i;
}
}
// if this num is semi-prime, tag its multiples as composite
else if (sieve[i][0] == 2) {
int next_number = i + i;
while (next_number <= N) {
sieve[next_number][0] = 3;
next_number += i;
}
}
}
return sieve;
}
public int[] solution(int N, int[] P, int[] Q) {
// first, we need to establish prime and semi-prime numbers from 1 to N, in a sieve
int[][] sieve = sieve(N);
int[] prefix_sum_of_sieve = new int[sieve.length];
for (int i=1; i<sieve.length; i++) {
if (sieve[i][0]==2) {
prefix_sum_of_sieve[i] = prefix_sum_of_sieve[i-1] + 1;
}
else {
prefix_sum_of_sieve[i] = prefix_sum_of_sieve[i-1];
}
}
int[] results = new int[P.length];
// we count the semiprime of N from P and Q, for each P & Q from the prefix sum
for (int i=0; i < P.length; i++) {
results[i] = prefix_sum_of_sieve[Q[i]] - prefix_sum_of_sieve[P[i]-1];
}
return results;
}
}
Hope the explanation / comments are easy to understand.
Given a range of [1, 1000000000] we need to find prime numbers and all the digits of the prime number must be odd. (Example: 23 is not okay, 31 is okay)
If we go on by looping through each number and checking if it is prime etc, it is very slow. Is there a way to make this close to O(N) ?
I tried to eliminate as much as possible by looking at digits first. But after eliminating numbers with even digits the prime test is too slow.
for all numbers in [1, N]
check all digits, if any even digit, continue
check primality (this step is very slow)
And the primality test should not be very complex (probabilistic etc. is not possible, it must be possible to implement in a few minutes). The one I use is:
private static boolean isPrime(int n) {
boolean isPrime = true;
for (int divisor = 2; divisor <= n / 2; divisor++) {
if (n % divisor == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
Maybe there is a trick to ensure a quick primality test but I couldn't find. Any suggestions? Thanks for reading.
You don't need to check all milliard numbers. Generate all numbers with only odd digits - there are at most 5^9~2 millions of them. Exclude those ending with 5 and not generate numbers divisible by 3 (in the moment of the last digit generation)
Then check these numbers for primality. Note that loop limit might be sqrt(n)
Ideone
class Ideone
{
static int oddcnt;
public static void checkprime(int x) {
for (int i=3; i <= Math.sqrt(x); i +=2)
if ((x % i) == 0)
return;
oddcnt++;
}
public static void genodd(int x, int curlen, int maxlen) {
x *= 10;
for (int i=1; i<10; i+=2) {
int nx = x + i;
checkprime(nx);
if (curlen < maxlen)
genodd(nx, curlen + 1, maxlen);
}
}
public static void main (String[] args) throws java.lang.Exception
{
genodd(0, 1, 8);
System.out.println(oddcnt);
}
}
The best way I can think of is to run a Prime Sieve of Eratosthenes to find all the primes in the range (0; sqrt(1000000000)) - which is around (0, 31622) - and time complexity O(n*log(log(n))) where n=31622. We will need those prime for a faster primality test.
Then, just loop through each number with odd digits - there are 5^10 = 9765625 ~ 10000000 such numbers. You saved 1000 times compared to iterating through all number in the original range.
The primality test using the primes we found in step 1 can be fast, as you only need to check with primes < sqrt(n), and you already have the primes. Even for the largest number in the range which is 999999999, the number of candidate primes is just 3432.
The following is a Java implementation
public class Execute {
private ArrayList<Long> primes = new ArrayList<>();
#org.junit.Test
public void findOddDecimalPrimes() {
primeSieve(32000);
System.out.println(primes.size());
for (int i = 0; i < 9765625; i++) {
String inBase5 = convertFromBaseToBase(i);
long evenDec = convertToOddDecimal(inBase5);
if (isPrime(evenDec)) {
System.out.println(evenDec);
}
}
}
private String convertFromBaseToBase(long i) {
return Long.toString(i, 5);
}
private long convertToOddDecimal(String str) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
s.append(1 + 2 * Integer.parseInt("" + str.charAt(i)));
}
return Long.parseLong(s.toString());
}
private boolean isPrime(long n) {
for (int i = 0; i < primes.size(); i++) {
if (primes.get(i) * primes.get(i) > n) break;
long divisor = n / primes.get(i);
if (divisor * primes.get(i) == n) return false;
}
return true;
}
/**
* References: www.geeksforgeeks.org
*/
private void primeSieve(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
boolean prime[] = new boolean[n+1];
for(int i=0;i<n;i++)
prime[i] = true;
for(int p = 2; p*p <=n; p++)
{
// If prime[p] is not changed, then it is a prime
if(prime[p] == true)
{
// Update all multiples of p
for(int i = p*p; i <= n; i += p)
prime[i] = false;
}
}
for (int i = 2; i < prime.length; i++) {
if (prime[i]) this.primes.add(Long.valueOf(i));
}
}
}
If your numbers are in order, you can optimize your isPrime function.
Here is a js sample version.
var primes = [];
function checkDigits(n) {
while(n > 1) {
var d = n % 10;
if ( d % 2 == 0) { return false; }
n = parseInt(n/10,10);
}
return true;
}
function isPrime(n) {
for(var i = 1; i < primes.length; i++) {
if(n % primes[i] == 0) {
return false;
}
}
var lastPrime = primes.length > 2 ? primes[primes.length - 1] : 1;
var inc = 2;
for(var i = lastPrime + inc; i < Math.sqrt(n); i += inc) {
if(n % i == 0) {
return false;
}
}
primes.push(n);
return true;
}
for(var i = 1; i < 100; i++) {
if(checkDigits(i) && isPrime(i)) {
console.log(i);
}
}
This is an open question in math and computer science in general.
In a nutshell no, there is no know way to solve that problem in O(1) to get your loop running in O(N) over the whole range.
If you solve that, dont tell anyone, and go get rich by breaking most of the encryptions today that use large prime numbers.
What you could do though, is make the loop over the devisor a bit smaller by useing sqrt(n).
That will bring that inner loop down from O(N^2) to O(sqrt(N))
And the whole complexity from O(N^2) to O(N*sqrt(N))=O(N^(3/2))
Anotger optimization would be to check the odd digits first beforre doing the complex Prime calculation
I was solving the Magical Number Problem where the number at nth position is the sum of the previous 3 numbers, minus 1. For example: 0 1 1 1 2 3 5 9 16.... and so on.
I solved it in 2 ways.
Code 1) Using Recursion
int magicNumber(int n){
int f = 0;
if (n == 1)
return 0;
else if (n > 1 && n <= 4)
return 1;
else
f = (magicNumber(n-1) + magicNumber(n-2) + magicNumber(n-3)) - 1;
return f;
}
Code 2) Using Array
void magicNumber(int n){
long arr[] = new long[100];
int i=1;
for(i = 1; i <= n; i++)
{
if(i==1)
arr[i] = 0;
else if(i>1&&i<=4)
arr[i] = 1;
else
arr[i] = (arr[i-1] + arr[i-2] + arr[i-3]) - 1;
}
System.out.println("Result is : "+arr[n]);
}
Code 1 works fine when I provide a small integer number to the program, but it hangs with the input of bigger integer numbers and Code 2 runs fine without any problem.
So I need your suggestions, how can I improve the performance of the recursion program Code 1?
You can speed up your recursion like this:
int magicNumber2(int n, int a, int b, int c){
if (n <= 1) return a;
return magicNumber2(n - 1, b, c, a + b + c - 1);
}
int magicNumber(int n) {
magicNumber2(n, 0, 1, 1);
}
You're experiencing delay for higher numbers because each recursive call ends up in 3 more recursive calls. Hence the time rises exponentially. Try this approach:
Maintain a lookup table. Here I have an array magic_num[100] with all it's elements initialized to -1.
int magicNumber(int n){
if(n == 1)
{
magic_num[n] = 0;
return 0;
}
else if(n>1 && n<=4)
{
magic_num[n] = 1;
return 1;
}
else if(magic_num[n] == -1)
{
magic_num[n] = magicNumber(n-1) + magicNumber(n-2) + magicNumber(n-3) - 1;
return magic_num[n];
}
else
return magic_num[n];
}
I have got a solution for problem 21 in python and it gives the right answer. I tried out someone else's java code and I get the same answer for a value of 10000 and 100000 but when 1000000 is tried, the solution returned by my code differs from two other solutions returned by java code even though all three solutions returned are same for tested values of 10000 and 1000000 and 50000. Anyone got any ideas?
My Python code
def amicable_pairs(n):
"""returns sum of all amicable pairs under n. See project euler for
definition of an amicable pair"""
div_sum = [0]*n
amicable_pairs_set = [0]*n
for i in range(1, n):
for j in range(i*2, n, i):
div_sum[j] += i
#for i in range(1, n):
# div_sum[i] = sum([j + i/j for j in range(2, int(math.sqrt(i)) + 1) if i % j == 0 and i != i/j])
# div_sum[i] = div_sum[i] + 1
#print div_sum
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
amicable_pairs_set[j] = j
amicable_pairs_set[div_sum[j]] = div_sum[j]
return sum(amicable_pairs_set)
Java code 1:
public class AmicableNumbers {
public static void main(String[] args) {
long strTime = System.currentTimeMillis();
int sum_ami = 0;
for (int j = 1; j < 1000000; j++) {
int ad = sum_devisors(j);
if (((sum_devisors(ad)) == j) && (j != ad)) {
sum_ami += j;
}
}
System.out.println(sum_ami);
long endTime = System.currentTimeMillis();
System.out.println("time is " + (endTime - strTime) + " ms");
}
public static int sum_devisors(int number) {
if ((number == 1) || (number == 2)) {
return 1;
}
int sum = 0;
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
if (number % i == 0) {
sum += i;
sum += (number / i);
}
}
if (k * k == number) {
sum += k;
}
return (sum + 1);// every number divided by 1
}
}
Java code 2:
import java.util.Scanner;
public class AmicableNumbers {
/**
* #author Pavan Koppolu
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//scan the input
System.out.println("Enter a number, to find out sum of amicable numbers: ");
Scanner scan=new Scanner(System.in);
int input=scan.nextInt();
long before=System.currentTimeMillis();
// getting the result
long result=sumOfAllAmicableNumbersUptoGivenNumber(input);
long after=System.currentTimeMillis();
// prints the result on the console
System.out.println("Sum of all amicable numbers below "+input+" : "+result+" Elasped Time : "+(after-before)+" ms");
}
/*
* calculate the sum of the amicable numbers upto the given number
*/
private static long sumOfAllAmicableNumbersUptoGivenNumber(int input)
{
long sum=0,factorsSum=0,sumOfFactors=0;
for(long j=2;j<input;j++)
{
factorsSum=getFactorsSum(j);
if(j!=factorsSum)
{
sumOfFactors=getFactorsSum(factorsSum);
if(j==sumOfFactors)
sum+=j;
}
else
continue;
}
return sum;
}
/*
* find out the sum of the factors
*/
private static long getFactorsSum(long j)
{
long sum=1;
for(int k=2;k<=Math.sqrt(j);k++)
{
if(j%k==0)
sum+=k+j/k;
}
return sum;
}
}
In fact the solutions returned by all three above differ from each other for an input of 1000000
The point is that there are amicable pairs where one partner is less than 1 million and the other is larger than 1 million, namely
(947835,1125765), (998104,1043096)
The Python code doesn't count them,
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
but the Java code counts the smaller members of these pairs. That explains the output of the second Java code, since
25275024 + 947835 + 998104 == 27220963
The output of the first Java code is smaller because it omits the amicable pair
(356408, 399592)
The reason is that
356408 = 596*598
but in the code there is
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
thus the divisor sum is miscalculated for all numbers divisible by floor(sqrt(n)) that are not squares (Note that the second Java code miscalculates the divisor sum for all squares).