Let\'s define eleven-non-free numbers:
If we consider a number as a string, then if any substring inside is a (non-zero) power of 11, then this
As good starting point is to consider the related problem of counting how many eleven-non-free (ENF) integers there are of N digits. This is not exactly the same thing as finding the n'th ENF integer, but the latter problem can be reduced to the former pretty easily (see the end of this post for java code that does this).
The idea is to do dynamic programming on prefixes. For any string of digits s, and any integer k, let N(k,s) denote the number of ENF strings of length k which start with s. And, for any string s, let s_0 be the longest suffix of s that also occurs as a prefix of any power of eleven (POE) of length k or less. Then, assuming that s itself does not contain any POE substrings, we have the equation:
N(k,s) = N(k-length(s)+length(s_0),s_0)
The reasoning behind this equation is as follows. Since s_0 is a suffix of s, let us write s as a concatenation of some other string q and s_0: s=[q,s_0]. Now, let r be any digit string which starts with s and again let us write this as a concatenation, as r=[s,r_0] = [q,s_0,r_0].
If r contains a POE as a substring, then either this POE is contained in r_0, or else it crosses over the boundary between s and r_0. In this case, s must end in a POE prefix, and, since we know that the longest POE prefix that occurs as a suffix of s is s_0, it follows that if r contains a POE substring, then this substring must be contained in [s_0,r_0]. This gives us a one-to-one correspondence between ENFs that begin with s=[q,s_0] and ENFs that begin with s_0.
This above equation gives rise to a recursive algorithm to count the number of k-digit ENFs with a given prefix. The base cases end up being instances where length(s_0)=length(s) which means that s itself is a prefix of a POE of length k or less. Since there aren't very many such POE prefixes (at most k choose 2 which is O(k^2)), this formula leads to an efficient algorithm. Here is pseudocode:
Given a prefix s and an integer k, this function computes N(k,s)
if s contains a POE then return 10^(k-length(s))
if length(s) = k return 0
let s0 = longest POE prefix which is a suffix of s
if(length(s0)
Using dynamic programming, the running time of this algorithm will be polynomial in k, the number of digits. The algorithm only recurses on POE prefixes, and since there are O(k^2) of these, the running time will be O(k^2) times the running time of each iteration. Using a naive O(k^2) algorithm to find the longest suffix that matches a POE prefix would thus lead to an O(k^4) algorithm, while using a radix tree to find matches in linear time would result in O(k^3). The java code given below uses the naive algorithm, and experimentally, for values up to around k=100 seems to be Θ(k^4.5), though this discrepancy could well be due to implementation details or constant factors affecting runtimes for small input sizes. Here is the code:
public class Eleven {
public static final String[] digits =
{"0","1","2","3","4","5","6","7","8","9"};
public static BigInteger countENF(String prefix, int k){
return countENF(prefix,k,new HashMap(),getPowers(k));
}
public static BigInteger countENF(String prefix,
int k,
// This map contains stored results for dynamic programming
// Pair is an auxiliary class that does what you think it does
Map,BigInteger> resultMap,
// precomputed list of powers of 11
List powers
){
// Dynamic programming case
BigInteger res = resultMap.get(new Pair(prefix,k));
if(res != null)
return res;
// base cases
if(!isEFree(prefix, powers)){
res = new BigInteger("10").pow(k-prefix.length());
resultMap.put(new Pair<>(prefix,k), res);
return res;
}
if(prefix.length() >= k){
res = new BigInteger("0");
resultMap.put(new Pair<>(prefix,k), res);
return res;
}
String s0 = getMaxPrefix(prefix, powers);
if(s0.length() < prefix.length()){
return countENF(s0,k+s0.length()-prefix.length(),resultMap,powers);
}
// recursive summation
res = new BigInteger("0");
for(String d : digits){
String s1 = prefix + d;
res = res.add(countENF(s1,k,resultMap,powers));
}
resultMap.put(new Pair<>(prefix, k), res);
return res;
}
//
// helper functions
//
// returns all POEs of at most length digits
private static List getPowers(int length) {
List ret = new ArrayList<>();
BigInteger val = new BigInteger("11");
BigInteger eleven = new BigInteger("11");
while(val.toString().length() <= length){
ret.add(val.toString());
val = val.multiply(eleven);
}
return ret;
}
// finds the longest string that is both a prefix of s and a suffix of a POE
private static String getMaxSuffix(String s, List powers){
for(int i=s.length(); i>0; i--){
String sub = s.substring(0,i);
for(String p : powers){
if(p.endsWith(sub))
return sub;
}
}
return "";
}
public static boolean isEFree(String s, List powers){
for(String p : powers){
if(s.indexOf(p)>=0)
return false;
}
return true;
}
As mentioned above, this algorithm does not solve the exact problem in the OP. But, modifying this code to actually find the n'th ENF number is pretty simple. Making
repeated callse to countENF, we first figure out how many digits the n'th ENF number has,
and then, one digit at a time, we figure out the digits of the n'th ENF from left to right.
public static String getNthENF(BigInteger i){
int k = i.toString().length();
HashMap results = new HashMap();
List powers = getPowers(k);
while(countENF("",k,results,powers).compareTo(i) < 0){
k++;
powers = getPowers(k);
}
String solution = "";
BigInteger total = new BigInteger("0");
while(solution.length() < k){
for(String d : digits){
BigInteger newTotal = total.add(countENF(solution + d,k,results,powers));
int comp = newTotal.compareTo(i);
if(comp >= 0){
solution = solution + d;
break;
}
total = newTotal;
}
}
return solution;
}
Here is some sample output, giving the N'th ENF as computed using dynamic programming, as well as using brute force, for powers of 10.
Dynamic Programming:
10^1: 118
10^2: 1178
10^3: 11680
10^4: 115730
10^5: 1146628
10^6: 11360558
10^7: 112558960
10^8: 1115229050
10^9: 11049731548
10^10: 103258311161
10^11: 935443232311
10^12: 8576360477119
10^13: 79330786951511
10^14: 732117130575070
10^15: 6880811638385388
10^16: 64284911460844887
10^17: 610616803411054857
10^18: 5759459802926457113
10^19: 54555977711878792498
10^20: 518773721711219891634
Brute Force:
10^1: 118
10^2: 1178
10^3: 11680
10^4: 115730
10^5: 1146628
10^6: 11360558
10^7: 112558960