Uses @Arnauld's idea of computing the length of each decimal digit separately. A magic hash in the form x**a%b%5
seems to work well.
f=lambda n:n and(n%10)**24%8684%5+f(n/10)
Try it online!
Other magic:
lambda n:sum(7125144/ord(c)%5for c in`n`) # 41
f=lambda n:n and(n%5+n/5%2>>n%5/4)+f(n/10) # 42 (has actual strategy)
Alternatively, the same length, but who doesn't love a little magic hash
?
lambda n:sum(hash(c+'WQDE')%5for c in`n`)
Try it online!
The little C script below finds all possible 4-byte long suffixes to seed the hash, and takes roughly a second to complete. Interestingly, out of the 12 valid solutions, 'WQDE'
is the only one with all uppercase characters. If you think about it, the chances of this occurrence are only 26^4/127^4 ~ 0.176%
!
// https://github.com/python/cpython/blob/v2.7/Objects/stringobject.c#L1263
#include <stdio.h>
#include <time.h>
int py_mod(long long x, int m) { int ret = x % m; return ret >= 0 ? ret : ret + m; }
const long long h[10] = {6144036912055440, 6272037681056595, 6400038450057750, 6528039219058905, 6656039988060060, 6784040757061215, 6912041526062370, 7040042295063525, 7168043064064680, 7296043833065835};
long long h0[10], h1[10], h2[10];
int main() {
clock_t sclock = clock();
for (int c0 = 1; c0 < 128; c0++) {
for (int i0 = 0; i0 < 10; i0++) h0[i0] = (h[i0] ^ c0) * 1000003;
for (int c1 = 1; c1 < 128; c1++) {
for (int i1 = 0; i1 < 10; i1++) h1[i1] = (h0[i1] ^ c1) * 1000003;
for (int c2 = 1; c2 < 128; c2++) {
for (int i2 = 0; i2 < 10; i2++) h2[i2] = (h1[i2] ^ c2) * 1000003 ^ 5;
for (int c3 = 1; c3 < 128; c3++) {
if (py_mod(h2[0] ^ c3, 5) != 0) continue;
if (py_mod(h2[1] ^ c3, 5) != 1) continue;
if (py_mod(h2[2] ^ c3, 5) != 2) continue;
if (py_mod(h2[3] ^ c3, 5) != 3) continue;
if (py_mod(h2[4] ^ c3, 5) != 2) continue;
if (py_mod(h2[5] ^ c3, 5) != 1) continue;
if (py_mod(h2[6] ^ c3, 5) != 2) continue;
if (py_mod(h2[7] ^ c3, 5) != 3) continue;
if (py_mod(h2[8] ^ c3, 5) != 4) continue;
if (py_mod(h2[9] ^ c3, 5) != 2) continue;
printf("found: (%d,%d,%d,%d) [%c%c%c%c]\n",
c0, c1, c2, c3, c0, c1, c2, c3);
}
}
}
}
printf("Time elapsed: %.3fs\n", (double) (clock() - sclock) / CLOCKS_PER_SEC);
return 0;
}