Merge Prime

We define a merge prime as a prime number that can be split into two prime numbers.

Some examples of merge primes are:

  • 73 because 7 and 3 are both prime numbers.
  • 373 because 37 and 3 are both prime numbers.

What are the last three digits of the sum of all 7-digit merge primes?

Clarification

  • 9998903 9998903 is a merge prime because 99989 99989 and 3 3 are primes.


The answer is 399.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

3 solutions

Christopher Boo
Jun 17, 2016

I have two approach :

  1. Try all 7-digit number and check if they are merge primes.
  2. Generate all prime numbers up to 6-digit with sieve . Concatenate those that will form a 7-digit number and check if they are prime.

I tried the latter one and below is the code. It took me two and a half minute, I wonder what is the runtime of the first approach?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MAXN = 1000000

# sieve
prime = []
table = [1 for i in range(MAXN)]
table[0] = table[1] = 0
for i in range(2,MAXN):
    if table[i] == 1:
        prime.append(i)
        for j in range(i+i,MAXN,i):
            table[j] = 0

# concatenate two primes to form a 7-digit prime. Note that they might have zeros in between.
def concatenate(p1, p2):
    length = len(str(p1) + str(p2))
    if length > 7:
        return 0
    return int(str(p1) + (7 - length) * "0" + str(p2))

ans = []    # store merge primes
for p1 in prime:
    for p2 in prime:
        merge = concatenate(p1,p2)
        if merge == 0:
            break
        if isPrime(merge):
            ans.append(merge)

ans = list(set(ans))        # remove duplicates

print sum(ans)

The output is 714940468399 714940468399 .


I didn't include my isPrime(x) function to make the code clearer. You can replace it with any prime testing algorithm you feel comfortable with. Of course, the optimal one will be Miller-Rabin algorithm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def isPrime(n):
    def pow(a,d,n):    # a ^ d % n
        ans = 1
        while d != 0:
            if d & 1:
                ans = (ans * a) % n
            d >>= 1
            a = (a * a) % n
        return ans

    if n < 2: return False
    if n < 4: return True
    if n % 2 == 0: return False

    s = 0
    d = n-1
    while d & 1 == 0:
        s += 1
        d >>= 1

    for i in range(50):    # higher range, higher accuracy
        a = randint(2, n-2)
        x = pow(a,d,n)
        if x == 1: continue
        for j in range(s):
            if x == n-1: break
            x = (x * x) % n
        else:
            return False
    return True

Generate all prime numbers up to 6-digit. Concatenate those that will form a 7-digit number and check if they are prime. So we can split the number into morethan two primes? Let's say is 9998903 a merge prime?

Join Turva - 4 years, 11 months ago

Log in to reply

No, we can only split them into exactly two primes. What I meant is to concatenate 6-digit prime with 1-digit prime, 5-digit prime with 2-digit prime, etc.

Christopher Boo - 4 years, 11 months ago

Log in to reply

is 9998903 a merge prime?

Join Turva - 4 years, 11 months ago

Log in to reply

@Join Turva Yes. But my program missed that. Might need to fix the problem.

Christopher Boo - 4 years, 11 months ago

Log in to reply

@Christopher Boo Which sum do you mean? Let's say, I have a set of number [1,2,3,4,5], sum=5, this sum or ,sum=15, this sum?

Join Turva - 4 years, 11 months ago

Log in to reply

@Join Turva [1,2,3,4,5] sum = 15

Christopher Boo - 4 years, 11 months ago

@Join Turva It's ambigous cause I think 9998903 is a prime but not a merge prime,we can split into 999890 and 3 which mean it's not a merge prime but based on your solution 9998903 can be splited into 99989 and 3 but it will be 6-digit merge prime not 7-digit merge prime

Join Turva - 4 years, 11 months ago

Log in to reply

@Join Turva Yes you are correct. I do agree that 9998903 9998903 is a merge prime but my solution missed that out. I will update the solution accordingly. What did you got?

Christopher Boo - 4 years, 11 months ago

Log in to reply

@Christopher Boo I got the answer 316

Join Turva - 4 years, 11 months ago

bro, change the problem description please, you include the 9998903 as merge prime

Join Turva - 4 years, 11 months ago

Log in to reply

9998903 9998903 is a merge prime.

Christopher Boo - 4 years, 11 months ago

Log in to reply

add an asumption in your problem then

Join Turva - 4 years, 11 months ago

Log in to reply

@Join Turva I've edited the problem, is it clear now?

Christopher Boo - 4 years, 11 months ago

Log in to reply

@Christopher Boo okay by the way you said that you took 2 and half minute with your algorithm, mine only 5 sec

Join Turva - 4 years, 11 months ago

Log in to reply

@Join Turva I'm impressed, what's your solution?

Christopher Boo - 4 years, 11 months ago

Log in to reply

@Christopher Boo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<bits/stdc++.h>
using namespace std;
long long bound;
bitset<100000010> index;
vector<long long> prime;

long long sieve(long long limit){
    bound=++limit;

    long long i=0;
    index.set();
    index[0]=index[1]=0;
     while(i<bound){
        if(index[i]){
            long long k=i*i;
                while(k<=bound){ 
                    index[k]=0;
                    k+=i;
                }

                prime.push_back(i);
        }
    i++;
}
    return prime.size();
}

bool isprimes(long long n){

if(n<=bound) return index[n];

    long long j=0;
    while(j<prime.size()){
        if(n%prime[j]==0) return false;
    j++;
    }

    return true;

}

bool mergeprime(long long x){
    long long ten,left,right,iterator=7;

        while(--iterator){
            merge=0;
            ten=pow(10,iterator);
            left=x/ten; right=x%ten;
            if((isprimes(left)) && (isprimes(right))) return true;  
    }

    return false;

}

unsigned long long int mergeprimes(long long a, long long z){
    unsigned long long int sum= 0;
    long long indicator=a;

        while(indicator<=z){ if(isprimes(indicator) && mergeprime(indicator)) sum+=indicator; indicator+=2; }

    return sum;
}

int main(){

    sieve(10000000);
    cout<<mergeprimes(1000001,9999999)%1000<<endl;

}

Join Turva - 4 years, 11 months ago

@Christopher Boo I simply using sieve and little bit modification in my solution

Join Turva - 4 years, 11 months ago

Isn't 1000032 a 7 digit merge prime? But in your answer you didn't count that as 7 digit merge prime. Can you explain why?

fahim saikat - 2 years, 7 months ago
Kristian Takvam Staff
Jul 1, 2016

Here's the more naive solution of testing all 7-digit numbers for primality.

Takes about 9 seconds to run. I first started writing it in Python, but I was too impatient for it to finish running. It might be fast using NumPy, but I haven't tried.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

static bool prime_map[(int)1e7];

bool is_prime(int number) {
    if (number <= 1) {
        return false;
    }
    for (int i = 2; i < ((int)powf(number, 0.5) + 1); ++i) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

bool is_merge_prime(int number) {
    char string[11]; // max 32-bit int is 10 digits, +1 for null terminator
    sprintf(string, "%d", number);
    int num_digits = (int)strlen(string);

    char first_string[11], second_string[11];
    for (int i = 0; i < num_digits - 1; ++i) {
        int first_string_len = 0, second_string_len = 0;
        for (int j = 0; j < num_digits; ++j) {
            if (j > i) {
                second_string[second_string_len++] = string[j];
            }
            else {
                first_string[first_string_len++] = string[j];
            }
        }
        first_string[first_string_len++] = '\0';
        second_string[second_string_len++] = '\0';

        int first_number = atoi(first_string);
        int second_number = atoi(second_string);
        if (prime_map[first_number] && prime_map[second_number]) {
            //printf("%d is a merge prime because %d and %d are prime.\n", number, first_number, second_number);
            return true;
        }
    }
    return false;
}

char *suffix(char *string, int suffix_length) {
    int length = (int)strlen(string);
    if (length < suffix_length) {
        return string;
    }
    return string + length - suffix_length;
}

void build_prime_map() {
    for (int i = 0; i < (int)1e7; ++i) {
        prime_map[i] = is_prime(i);
    }
}

int main(int argc, const char * argv[]) {
    build_prime_map();

    // 4.5e6 is assuming all odd numbers are prime, obviously overkill.
    // Could use dynamic allocation instead and realloc as needed, but
    // that would be slower.
    static int seven_digit_primes[(int)4.5e6];
    int num_seven_digit_primes = 0;
    for (int i = 1e6; i < (int)1e7; ++i) {
        if (is_prime(i)) {
            seven_digit_primes[num_seven_digit_primes++] = i;
        }
    }

    static int merge_primes[(int)4.5e6];
    int num_merge_primes = 0;
    for (int i = 0; i < num_seven_digit_primes; ++i) {
        int seven_digit_prime = seven_digit_primes[i];
        if (is_merge_prime(seven_digit_prime)) {
            merge_primes[num_merge_primes++] = seven_digit_prime;
        }
    }

    uint64_t sum = 0;
    for (int i = 0; i < num_merge_primes; ++i) {
        sum += merge_primes[i];
    }

    char string[21];
    sprintf(string, "%llu", sum);
    char *last_three_digits = suffix(string, 3);
    printf("%s\n", last_three_digits);

    return 0;
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from gmpy import is_prime
p=is_prime                  #skip if you can type is_prime faster
def mp(n):
    st=str(n)
    if not p(n):return False
    for i in range(1,len(st)):
        if p(int(st[:i])) and p(int(st[i:])):return True
    return False
su=0                         #initiate sum to 0
for i in range(1000000,9999999):
    if mp(i):su+=i
print(su%1000)

(Time: 23.5 s)

1 pending report

Vote up reports you agree with

×

Problem Loading...

Note Loading...

Set Loading...