I just came across with this interesting question from my colleague. I\'m trying now, but meanwhile I thought I could share it here.
With the password grid shown in
The full combinations of 4 to 9 distinctive numbers, minus the combinations which include invalid "jump"s.
The rule for Android 3x3 password grid:
one point for once
cannot "jump" over a point
The author of the original post used Mathematica to generate all 985824 combinations.
Because there is no "jump", several pairs of consecutive points are invalid.
Delete all invalid combinations to reach the result.
The combinations for 4-to-9-point paths are respectively 1624, 7152, 26016, 72912, 140704, 140704.
The reference is from guokr, a site alike Stack Exchange Skeptics in the form of blogs.
I brute forced the answer with a recursive search and i found a bigger answer, 487272. The algorithm is simple: trying it all. I quoted it down here. I didn't found any error in my code (but I'm not very skilled with c++). Sorry for the grammatical error I'm not English.
#include <iostream>
#include <stdlib.h>
using namespace std;
int combo; //counter
void research(int Ipoints /*number of points already took*/, bool Icheck[9]/*points matrix*/,int Ilast/*last took point*/,
int Icomboval/*combination representation, only for printing purpose*/, int deep/*number of iteration, only for printing purpose*/)
{
// int numcall = 0; //DEBUG
for( int i=0; i<9; i++) //Controlling every free point in search of a valid way to contimue
if( Icheck[i] == false )
{
//Just for security, coping every variable in a new variable. I don't know how c++ works but I will make it works
int points = Ipoints;
int last = Ilast;
int comboval = Icomboval;
bool check[9];
for( int j=0; j<9; j++)
check[j] = Icheck[j];
int e1,e2;
int middle = -1;
e1=i; e2=last; //Ccontrolling duble jumps
if( e1 == 0 && e2 == 2 ) middle = 1;
if( e1 == 3 && e2 == 5 ) middle = 4;
if( e1 == 6 && e2 == 8 ) middle = 7;
if( e1 == 0 && e2 == 6 ) middle = 3;
if( e1 == 1 && e2 == 7 ) middle = 4;
if( e1 == 2 && e2 == 8 ) middle = 5;
if( e1 == 0 && e2 == 8 ) middle = 4;
if( e1 == 6 && e2 == 2 ) middle = 4;
e2=i; e1=last; // in both way
if( e1 == 0 && e2 == 2 ) middle = 1;
if( e1 == 3 && e2 == 5 ) middle = 4;
if( e1 == 6 && e2 == 8 ) middle = 7;
if( e1 == 0 && e2 == 6 ) middle = 3;
if( e1 == 1 && e2 == 7 ) middle = 4;
if( e1 == 2 && e2 == 8 ) middle = 5;
if( e1 == 0 && e2 == 8 ) middle = 4;
if( e1 == 6 && e2 == 2 ) middle = 4;
if((middle != -1) && !(check[middle])) {
check[middle] = true;
points++; //adding middle points
comboval *= 10;
comboval += middle;
}
check[i] = true;
points++; // get the point
comboval*=10;
comboval += i+1;
if(points > 3)
{
combo++; // every iteration over tree points is a valid combo
// If you want to see they all, beware because printing they all is truly slow:
// cout << "Combination n. " << combo << " found: " << comboval << " , points " << points << " with " << deep << " iterations\n";
}
if(points > 9) //Just for sure, emergency shutdown,
{ exit(1); }
research(points,check,i,comboval,deep+1); /*Recursive, here is the true program!*/
// numcall++; //DEBUG
}
// cout << "Ended " << deep << " , with " << numcall << " subs called\n"; // Only for debug purposes,remove with all the //DEBUG thing
}
int main ()
{
combo = 0; //no initial knows combo
bool checkerboard[9];
for( int i=0; i<9; i++) checkerboard[i]=false; //blank initial pattern
research(0/*no point taken*/,checkerboard,-1/*just a useless value*/,0/*blank combo*/,1/*it's the firs iteration*/); //let's search!
cout << "\n" ;
cout << "And the answer is ... " << combo << "\n"; //out
char ans='\0';
while(ans=='\0')
{ //just waiting
cin >> ans;
}
return 0;
}
I know this question is old, but I answered it in another question (before finding this question) with a brute force approach in python, so adding it here for posterity:
pegs = {
1: {3:2, 7:4, 9:5},
2: {8:5},
3: {1:2, 7:5, 9:6},
4: {6:5},
5: {},
6: {4:5},
7: {1:4, 3:5, 9:8},
8: {2:5},
9: {1:5, 3:6, 7:8}
}
def next_steps(path):
return (n for n in range(1,10) if (not path or n not in path and
(n not in pegs[path[-1]]
or pegs[path[-1]][n] in path)))
def patterns(path, steps, verbose=False):
if steps == 0:
if verbose: print(path)
return 1
return sum(patterns(path+[n], steps-1) for n in next_steps(path))
So you can list all the # of patterns for any number of steps:
>>> [(steps, patterns([], steps)) for steps in range(1,10)]
[(1, 9),
(2, 56),
(3, 320),
(4, 1624),
(5, 7152),
(6, 26016),
(7, 72912),
(8, 140704),
(9, 140704)]
>>> sum(patterns([], steps) for steps in range(4,10))
389112
This is not the most efficient way of solving it because you could use reflections and only calculate a 4*corner + 4*mid-edge + 1*middle, e.g.:
>>> patterns([], 6) == 4*patterns([1], 5) + 4*patterns([2], 5) + patterns([5], 5)
True
(No of Points- Valid patterns) (4 - 746) (5 - 3268) (6 - 11132) (7 - 27176) (8 - 42432) (9 - 32256)
Total of 117010 valid Patterns are possible