版权声明:代码属于原创,转载请联系作者并注明出处。 https://blog.csdn.net/weixin_43379056/article/details/85095820
Problem 51: Prime digit replacements
By replacing the 1st digit of the 2-digit number *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.
By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property.
Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family.
C++ 代码
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <iterator>
#include <cmath>
#include <cassert>
using namespace std;
class PE0051
{
private:
bool checkPrime(int number);
bool getDigitsOfPrime(int prime, int numOfDigits, int numOfSameDigits,
vector<int>& digit_v, int& sameDigit,
vector<int>& sameDigit_pos);
bool checkPosInVector(int pos, vector<int>pos_vec);
public:
int getXdigitSmallestPrime(int numOfDigits, int numOfSameDigits,
int numOfPrimes);
};
bool PE0051::checkPrime(int number)
{
long double squareRoot=sqrt((long double)number);
if (number%2 == 0 && number!=2 || number < 2)
{
return false;
}
for(int i=3;i<=(int)squareRoot;i+=2) // 3, 5, 7, ...(int)squareRoot
{
if (number % i == 0)
{
return false;
}
}
return true;
}
bool PE0051::getDigitsOfPrime(int prime, int numOfDigits, int numOfSameDigits,
vector<int>& digit_v, int & sameDigit,
vector<int>& sameDigit_pos)
{
map<int, int> digits_mp;
bool foundSameDigit = false;
for (int i=numOfDigits-1; i>=0 && prime > 0; i--)
{
digits_mp[prime%10] += 1;
digit_v[i] = prime%10; // save all digits of the prime
prime /= 10;
}
map<int, int>::iterator iter = digits_mp.begin();
for(;iter!=digits_mp.end();iter++)
{
if (digits_mp[iter->first] >= numOfSameDigits) // found all same digits
{
foundSameDigit = true;
sameDigit = iter->first;
break;
}
}
// 2-digit: *Z
// 5-digit: XY**Z
// 6-digit: *X*Y*Z
for(int i=numOfDigits-1, j=numOfSameDigits-1; i>=0 && j>=0; i--)
{
if (digit_v[i] == sameDigit)
{
sameDigit_pos[j] = i; // save same digit position
j--;
}
}
if (sameDigit_pos[numOfSameDigits-1] == numOfDigits-1)
{
foundSameDigit = false; // last digit can not be position of same digit
}
return foundSameDigit;
}
bool PE0051::checkPosInVector(int pos, vector<int> pos_vec)
{
vector<int>::iterator pos_vec_iter = pos_vec.begin();
for( ;pos_vec_iter != pos_vec.end(); pos_vec_iter++)
{
if (pos == *pos_vec_iter)
{
return true;
}
}
return false;
}
int PE0051::getXdigitSmallestPrime(int numOfDigits, int numOfSameDigits,
int numOfPrimes)
{
vector<int> digitsVec(numOfDigits); // all digits of prime
vector<int> sameDigitsPosVec(numOfSameDigits); // same digits pos of prime
int sameDigit = 0;
// 2-digit: [10, 99], 5-digit: [ 10000, 99999], 6-digit: [100000...999999]
int range_start = (int)pow(10.0, numOfDigits-1);
int range_end = (int)pow(10.0, numOfDigits) - 1;
set<int> primes_set;
set<int>::iterator ps_iter;
for (int n=range_start; n<=range_end; n++)
{
if (true == checkPrime(n))
{
primes_set.insert(n);
if (true == getDigitsOfPrime(n, numOfDigits, numOfSameDigits,
digitsVec, sameDigit, sameDigitsPosVec))
{
for (int i=sameDigit+1; i<=9; i++)
{
int number = 0;
for(int j=0;j<numOfDigits;j++)
{
number *= 10;
if (true == checkPosInVector(j, sameDigitsPosVec))
{
number += i;
}
else
{
number += digitsVec[j];
}
}
if (true == checkPrime(number))
{
primes_set.insert(number);
}
}
if (primes_set.size() == numOfPrimes)
{
ps_iter = primes_set.begin();
#ifdef UNIT_TEST
copy(primes_set.begin(), primes_set.end(),
ostream_iterator<int>(cout, "\t"));
cout << endl;
#endif
return *ps_iter; // first prime in primes set
}
}
primes_set.clear();
}
}
return 0;
}
int main()
{
PE0051 pe0051;
assert (13 == pe0051.getXdigitSmallestPrime(2, 1, 6));
assert (56003 == pe0051.getXdigitSmallestPrime(5, 2, 7));
cout << "8-digit first smallest prime is ";
cout << pe0051.getXdigitSmallestPrime(6, 3, 8) << endl;
return 0;
}
C++11 代码
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <iterator>
#include <cmath>
#include <cassert>
using namespace std;
//#define UNIT_TEST
class PE0051
{
private:
bool checkPrime(int number);
int getSameDigitOfPrime(int prime, int numOfDigits, int numOfSameDigits);
int replaceAllSameDigits(string s, int sameDigit, int newDigit);
public:
int getXdigitSmallestPrime(int numOfDigits, int numOfSameDigits,
int numOfPrimes);
};
bool PE0051::checkPrime(int number)
{
long double squareRoot = sqrt((long double)number);
if (number % 2 == 0 && number != 2 || number < 2)
{
return false;
}
for (int i = 3; i <= (int)squareRoot; i += 2) // 3, 5, 7, ...(int)squareRoot
{
if (number % i == 0)
{
return false;
}
}
return true;
}
int PE0051::getSameDigitOfPrime(int prime, int numOfDigits, int numOfSameDigits)
{
map<int, int> digits_mp;
int sameDigit = 0;
for (int i = numOfDigits - 1; i >= 0 && prime > 0; i--)
{
digits_mp[prime % 10] += 1;
prime /= 10;
}
map<int, int>::iterator iter = digits_mp.begin();
for (; iter != digits_mp.end(); iter++)
{
if (digits_mp[iter->first] == numOfSameDigits)
{
sameDigit = iter->first; // found same digit
break;
}
}
return sameDigit;
}
int PE0051::replaceAllSameDigits(string s, int sameDigit, int newDigit)
{
for (unsigned int i=0; i<s.size(); i++)
{
if (s[i] == (char)('0'+sameDigit))
{
s[i] = (char)('0'+ newDigit);
}
}
return stoi(s);
}
int PE0051::getXdigitSmallestPrime(int numOfDigits, int numOfSameDigits,
int numOfPrimes)
{
// 2-digit: [10, 99], 5-digit: [ 10000, 99999], 6-digit: [100000...999999]
int range_start = (int)pow(10.0, numOfDigits - 1);
int range_end = (int)pow(10.0, numOfDigits) - 1;
set<int> primes_set;
for (int n = range_start; n <= range_end; n++)
{
if (true == checkPrime(n))
{
primes_set.insert(n);
int sameDigit = getSameDigitOfPrime(n, numOfDigits, numOfSameDigits);
string digitsStr = to_string(n);
for (int newDigit = sameDigit + 1; newDigit <= 9; newDigit++)
{
int number = replaceAllSameDigits(digitsStr, sameDigit, newDigit);
if (true == checkPrime(number))
{
primes_set.insert(number);
}
}
if (primes_set.size() == numOfPrimes)
{
#ifdef UNIT_TEST
copy(primes_set.begin(), primes_set.end(),
ostream_iterator<int>(cout, " "));
cout << endl;
#endif
return n; // n is the first prime in primes set
}
primes_set.clear();
}
}
return 0;
}
int main()
{
PE0051 pe0051;
assert( 13 == pe0051.getXdigitSmallestPrime(2, 1, 6));
assert(56003 == pe0051.getXdigitSmallestPrime(5, 2, 7));
int prime = pe0051.getXdigitSmallestPrime(6, 3, 8);
cout << "8-digit first smallest prime is " << prime << "." << endl;
return 0;
}
Python 代码
import re
def checkPrime(n):
"""
check whether n is a prime
"""
if n < 2 or n != 2 and n%2 == 0:
return False
for i in range(3, int(n**0.5)+1, 2):
if 0 == n % i:
return False
return True
def getDigitsOfPrime(prime):
"""
covert a prime to digits list
"""
return [ int(digit) for digit in sorted(list(str(prime))) ]
def getXdigitSmallestPrime(numOfDigits, numOfPrimes):
"""
get smallest prime with such property
"""
for n in range(10**(numOfDigits-1), 10**numOfDigits):
primes_list = []
if True == checkPrime(n):
primes_list.append(n)
digits_list = getDigitsOfPrime(n)
same_digit = digits_list[0]
s = str(n)
for i in range(same_digit+1, 10):
strinfo = re.compile(str(same_digit))
ns = strinfo.sub(str(i), s)
number = int(ns)
if True == checkPrime(number):
primes_list.append(number)
if numOfPrimes == len(primes_list):
#print(primes_list)
return primes_list[0]
else:
primes_list.clear()
return 0
def main():
assert 13 == getXdigitSmallestPrime(2, 6)
assert 56003 == getXdigitSmallestPrime(5, 7)
print("8-digit first smallest prime is",getXdigitSmallestPrime(6, 8))
if __name__ == '__main__':
main()