android lock password combinations

前端 未结 4 435
我寻月下人不归
我寻月下人不归 2020-12-04 19:07

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

相关标签:
4条回答
  • 2020-12-04 19:15

    Summary

    The full combinations of 4 to 9 distinctive numbers, minus the combinations which include invalid "jump"s.

    The Long Version

    The rule for Android 3x3 password grid:

    • one point for once

    • cannot "jump" over a point

    enter image description here

    The author of the original post used Mathematica to generate all 985824 combinations.

    enter image description here

    Because there is no "jump", several pairs of consecutive points are invalid.

    enter image description here

    enter image description here

    Delete all invalid combinations to reach the result.

    enter image description here

    enter image description here

    The combinations for 4-to-9-point paths are respectively 1624, 7152, 26016, 72912, 140704, 140704.

    enter image description here

    The Original Post In Chinese

    The reference is from guokr, a site alike Stack Exchange Skeptics in the form of blogs.

    0 讨论(0)
  • 2020-12-04 19:18

    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;
    }
    
    0 讨论(0)
  • 2020-12-04 19:19

    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
    
    0 讨论(0)
  • 2020-12-04 19:35

    (No of Points- Valid patterns) (4 - 746) (5 - 3268) (6 - 11132) (7 - 27176) (8 - 42432) (9 - 32256)


    Total of 117010 valid Patterns are possible

    0 讨论(0)
提交回复
热议问题