Codility - Count Semiprimes


Codility and other programming lessons: Lesson 9: CountSemiprimes - (Count Semiprimes)
Lesson 9: CountSemiprimes
https://codility.com/programmers/lessons/9
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.
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 zero-indexed 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.
For example, consider an integer N = 26 and arrays P, Q such that:
    P[0] = 1    Q[0] = 26
    P[1] = 4    Q[1] = 10
    P[2] = 16   Q[2] = 20
The number of semiprimes within each of these ranges is as follows:
  • (1, 26) is 10,
  • (4, 10) is 4,
  • (16, 20) is 0.
Assume that the following declarations are given:
struct Results {
  int * A;
  int M;
};
Write a function:
struct Results solution(int N, int P[], int Q[], int M);
that, given an integer N and two non-empty zero-indexed arrays P and Q consisting of M integers, returns an array consisting of M elements specifying the consecutive answers to all the queries.
For example, given an integer N = 26 and arrays P, Q such that:
    P[0] = 1    Q[0] = 26
    P[1] = 4    Q[1] = 10
    P[2] = 16   Q[2] = 20
the function should return the values [10, 4, 0], as explained above.
First, let's implement a simple solution. 
We use Sieve of Eratosthenes to find prime numbers less than and equal to N.

Then we check each k (P[i] <= k <= Q[i]) is a semiprime or not
by using these prime numbers one by one.

https://github.com/styro103/CountSemiprimes/blob/master/CountSemiPrimes.java
    public int [] solution(int N, int [] P, int [] Q) 
    {
        if (N<4) return new int [P.length]; //If Max Number is Less Than 4, Return Array of Zeroes (4 is First Semiprime)
 
  int M = P.length; //Number of Queries
        int [] semiRanges = new int [M]; //Array of Semiprime Counts Between Ranges
        int [] semisCount = getSemis(N); //Get Count of Semiprimes of Each Number Up to Max

        for (int k=0; k<M; k++) //Loop Through Queries
            semiRanges[k] = (Q[k]<4) ? 0 : semisCount[Q[k]] - semisCount[P[k]-1]; //Subtract Counts to Get Semiprimes Count Between Range
        
        return semiRanges; //Return Array of Semiprimes Between Ranges
    }
    
    int [] getSemis(int N)
    {
        int [] sieve = sifter(N); //Get Array of Minimum Prime Factors
        int [] rsc = new int [N+1]; //Array of Counts of Semiprimes
        int sc = 0; //Semiprimes Count
        //Arrays.fill(rsc, 0); //Automatic Initialization to 0 in Java
        for (int i=4; i<rsc.length; i++) //Loop From 4 To One More Than Max Number
        {
            if (sieve[i]!=0 && sieve[i/sieve[i]]==0) sc++; //If Semiprime, Increase Count
            rsc[i] = sc; //Set Count of Semiprimes at Integer
        }
        
        return rsc; //Return Array of Counts of Semiprimes
    }
    
    int [] sifter (int N) //Get Array of Minimum Prime Factors
    {
        int [] sieve = new int [N+1]; //Array of Minimum Prime Factors
        //Arrays.fill(sieve, 0); //Automatic Initialization to 0 in Java
        for (int i=2; i<=Math.sqrt(N); i++) //Loop From 2 till Max Number
        {
            if (sieve[i]==0) //If Prime Number
            {
                for (int j=i*i; j<=N; j+=i) //Find All Multiples
                    if (sieve[j]==0) sieve[j] = i; //If Prime Factor Isn't Listed, Update
            }
        }
        
        return sieve; //Return Array of Minimum Prime Factors
    }

https://www.martinkysel.com/codility-countsemiprimes-solution/
First get all semiprimes from an adaptation of the Sieve of Eratosthenes. Because we will be computing the difference many times a prefix sum is adequate. Get the number of semiprimes up to the point. The index P is decreased by 1 because we want to know all primes that start from P.
Static Range query: use prefix sum.
Java solution: https://github.com/acprimer/Codility/blob/master/src/Lesson9/CountSemiprimes.java
def sieve(N):
    semi = set()
    sieve = [True]* (N+1)
    sieve[0] = sieve[1] = False
    i = 2
    while (i*i <= N):
        if sieve[i] == True:
            for j in xrange(i*i, N+1, i):
                sieve[j] = False
        i += 1
    i = 2
    while (i*i <= N):
        if sieve[i] == True:
            for j in xrange(i*i, N+1, i):
                if (j % i == 0 and sieve[j/i] == True):
                    semi.add(j)
        i += 1
    return semi
def solution(N, P, Q):
    semi_set = sieve(N)
    prefix = []
    prefix.append(0) # 0
    prefix.append(0) # 1
    prefix.append(0) # 2
    prefix.append(0) # 3
    prefix.append(1) # 4
    for idx in xrange(5, max(Q)+1):
        if idx in semi_set:
            prefix.append(prefix[-1]+1)
        else:
            prefix.append(prefix[-1])
    solution = []
    for idx in xrange(len(Q)):
        solution.append(prefix[Q[idx]] - prefix[P[idx]-1])
    return solution

int check(int k, int N, char* sieve, int* next_prime)
{
    //if k is less than 4 or a prime number,
    //it is never a semiprime
    if (k < 4 || sieve[k] == 1){
        return 0;
    }
    //check if k is a semiprime.
    int num = 2;
    while (num * num <= k){
        num = next_prime[num];
        if (k > num && k % num == 0 && k / num <= N && sieve[k / num] == 1){
            return 1;
        }
        num++;
    }
 
    return 0;
}

struct Results solution(int N, int P[], int Q[], int M)
{
    //compute the prime number
    int size = sizeof(char) * (N + 1);
    char* sieve = (char*)alloca(size);
    memset(sieve, 0x01, size);
 
    int i, j, k;
    i = 2;
    sieve[0] = sieve[1] = 0;
    while(i * i <= N){
        if (sieve[i]){
            k = i * i;
            while(k <= N){
                sieve[k] = 0;
                k += i;
            }
        }
        i++;
    }
 
    //the next prime number
    int* next_prime = (int*)alloca(sizeof(int) * (N + 1));
    next_prime[N] = sieve[N] == 1 ? N : -1;
 
    for (i = N - 1; i >= 0; i--){
        if (sieve[i]){
            next_prime[i] = i;
        }
        else {
            next_prime[i] = next_prime[i + 1];
        }
    }

    struct Results result;

    result.A = (int*)malloc(sizeof(int) * M);
    result.M = M;


    //start finding semiprime for each.
    for (i = 0; i < M; i++){
        int cnt = 0;
        for (j = P[i]; j <= Q[i]; j++){
            if (check(j, N, sieve, next_prime)){
                cnt++;
            }
        }
        result.A[i] = cnt;
    }
    return result;
}

https://github.com/acprimer/Codility/blob/master/src/Lesson9/CountSemiprimes.java

boolean[] notPrime, semi;
public void seivee(int n) {
for (int i = 2; i * i <= n; i++) {
if (notPrime[i]) continue;
for (int k = i * i; k <= n; k += i) {
notPrime[k] = true;
}
}
}
public void semi(int n) {
for (int i = 2; i * i <= n; i++) {
if (notPrime[i]) continue;
for (int k = i * i; k <= n; k += i) {
if (!notPrime[k / i]) semi[k] = true;
}
}
}
public int[] solution(int N, int[] P, int[] Q) {
notPrime = new boolean[N + 1];
seivee(N);
semi = new boolean[N + 1];
semi(N);
int[] sum = new int[N + 1];
for (int i = 1; i <= N; i++) {
sum[i] = sum[i - 1];
if (semi[i]) sum[i]++;
}
for (int i = 0; i < P.length; i++) {
P[i] = sum[Q[i]] - sum[P[i] - 1];
}
return P;
}
Let's use the sieve algorithm also to find semiprime numbers. Then use the prefix sum of the occurrence of semiprime numbers from 0 to N, so that we can count the number of semiprime numbers in a constant time.

This strategy gives the O(N*log(log(N))+M) time complexity. As the sieve algorithm is used both for finding prime numbers  and subprime numbers, These parts have the O(2* N*log(log(N))) => O(N*log(log(N))) time complexity. 

The part to make an array of prefix sum is the O(N) time complexity. Then so far, it is still O(N*log(log(N)) + N) => O(N*log(log(N)). 

To compute the return value, as the number of semiprime between P[i] and Q[i] can be found in a constant time and we repeat it M times, the time complexity will be O(M).

Adding this to O(N*log(log(N)), the O(N*log(log(N) + M) time complexity is what we have in this solution.
http://codility-lessons.blogspot.com/2015/03/lesson-9-countsemiprimes.html
Read full article from Codility and other programming lessons: Lesson 9: CountSemiprimes - (Count Semiprimes)

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts