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.
素数数字替换
将两位数*3的第一个数字代换为任意数字,在九个可能值中有六个是素数:13、23、43、53、73和83。
将五位数56**3的第三和第四位数字代换为相同的任意数字,就得到了十个可能值中有七个是素数的最小例子,这个素数族是:56003、56113、56333、56443、56663、56773和56993。56003作为这一族中最小的成员,也是最小的满足这个性质的素数。
通过将部分数字(不一定相邻)代换为相同的任意数字,有时能够得到八个素数,求满足这一性质的最小素数。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import junit.framework.TestCase;
public class Prj51 extends TestCase {
public void testPrimeDigitReplacements() {
for (int i = 5;; i++) {
DfsPrimeDigitReplacements dfsP = new DfsPrimeDigitReplacements(i);
if (dfsP.doTest()) {
return;
}
}
}
public class PrimeTestCase {
public int[] dataList;
public int[] ids;
public boolean[] marks;
public int val;
public PrimeTestCase(int[] _ids) {
marks = new boolean[_ids.length];
for (int i = 0; i < _ids.length; i++) {
if (_ids[i] == 1) {
marks[i] = true;
}
}
dataList = Arrays.copyOf(_ids, _ids.length);
ids = Arrays.copyOf(_ids, _ids.length);
}
public void markNext(int id, int val) {
marks[id] = true;
dataList[id] = val;
}
public void unMarkNext(int id) {
dataList[id] = 0;
marks[id] = false;
}
public int getNextUnMark() {
for (int i = 0; i < marks.length; i++) {
if (!marks[i]) {
return i;
}
}
return -1;
}
public boolean isFind() {
int[] copy = Arrays.copyOf(dataList, dataList.length);
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i <= 9; i++) {
for (int j = 0; j < ids.length; j++) {
if (ids[j] == 1) {
copy[j] = i;
}
}
int p = (int) getIntVal(copy);
// except 000109
if (isPrime(p) && Integer.toString(p).length() == dataList.length) {
set.add((int) getIntVal(copy));
}
}
if( set.size() >= 8){
for( int val : set){
System.out.print(val + ",");
}
System.out.println();
}
return set.size() >= 8;
}
}
// depth first assign value
public class DfsPrimeDigitReplacements {
public static final int ITER_SIZE = 3;
public int N;
public DfsPrimeDigitReplacements(int n) {
this.N = n;
}
public boolean doTest() {
for (int i = 3; i < N; i = i + 3) {
Comb cb = new Comb(N, i);
List<int[]> allCbs = cb.calculateComb();
// sort all combination temlpates , nCr
Collections.sort(allCbs, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
int i = 0;
while (i < o1.length && o1[i] == o2[i] && (i++ > 0))
;
return (i == o1.length) ? 0 : (o1[i] < o2[i] ? 1 : 0);
}
});
for (int iter = 0; iter < allCbs.size(); iter++) {
int[] _ids = allCbs.get(iter);
PrimeTestCase ts = new PrimeTestCase(_ids);
if (dfs(ts)) {
System.out.println("vals=" + getIntVal(ts.dataList));
System.out.println("marks=" + getIntVal(ts.ids));
return true;
}
}
}
return false;
}
public boolean dfs(PrimeTestCase ts) {
if (ts.getNextUnMark() == -1) {
if (ts.isFind()) {
return true;
}
return false;
}
for (int i = 0; i <= 9; i++){
int id = ts.getNextUnMark();
ts.markNext(id, i);
if( dfs( ts)){
return true;
}
ts.unMarkNext(id);
}
return false;
}
}
public static boolean isPrime(int num) {
assert (num > 1);
if (num <= 10) {
if (num == 2 || num == 3 || num == 5 || num == 7) {
return true;
}
return false;
}
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
public static long getIntVal(int[] arr) {
long sum = arr[0];
for (int i = 1; i < arr.length; i++) {
sum = sum * 10 + arr[i];
}
return sum;
}
/**
* get all marks nCr
* @param num
* @return
*/
public static class Comb {
private int n;
private int p;
public Comb(int n, int p) {
this.n = n;
this.p = p;
}
public List<int[]> calculateComb() {
assert (p < n && p > 0);
List<int[]> ret = new ArrayList<int[]>();
int[] arrs = new int[n];
for (int i = 0; i < p; i++) {
arrs[i] = 1;
}
ret.add(Arrays.copyOf(arrs, arrs.length));
for (;;) {
boolean find = findNext(arrs);
ret.add(Arrays.copyOf(arrs, arrs.length));
if (!find) {
break;
}
}
return ret;
}
private boolean findNext(int[] arrs) {
int count = 0;
int find = -1;
for (int i = 0; i < arrs.length - 1; i++) {
if (arrs[i] == 1) {
count++;
}
if (arrs[i] == 1 && arrs[i + 1] == 0) {
int tmp = arrs[i + 1];
arrs[i + 1] = arrs[i];
arrs[i] = tmp;
find = i;
break;
}
}
count--;
for (int i = 0; i < find; i++) {
if (i < count) {
arrs[i] = 1;
} else {
arrs[i] = 0;
}
}
return !(find == -1);
}
}
}