android模式锁中可能的路径数

时间:2016-01-05 05:15:47

标签: search graph depth-first-search breadth-first-search

android模式锁中可能有多少路径?

我认为它可以简单地通过阶乘计算,公式为(9!)/(9-length)!

示例:

长度为9时,有9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1路径。

长度为8时,有9 * 8 * 7 * 6 * 5 * 4 * 3 * 2路径。

长度为7时,有9 * 8 * 7 * 6 * 5 * 4 * 3路径。

以下是计算此代码的代码:

def paths_of_length(number_of_staring_points, length_of_path):
    print("number_of_staring_points", number_of_staring_points, "length_of_path", length_of_path)
    different_paths = 1
    for choosing_from in range(number_of_staring_points, 
                               number_of_staring_points - length_of_path,
                               -1):
        different_paths = different_paths * choosing_from

    return different_paths

def android_paths():
    """
    Returns number of different android lockscreen paths
    """
    different_paths = 0
    minimum_length = 4
    maximum_length = 9
    number_of_staring_points = 9
    for length in range(minimum_length,maximum_length + 1):
        different_paths += paths_of_length(number_of_staring_points,length)

    return different_paths

if __name__ == '__main__':
    import doctest
    doctest.testmod()

print(android_paths())

我的方法和代码是否正确?或者我计算错了?

提前致谢。

2 个答案:

答案 0 :(得分:0)

您的计算错误,因为并非每个节点都有另一个节点的边缘,并且某些节点只有某些条件启用了某些边缘。

例如:要从左上角节点到达右上角节点,应该访问顶级中间节点。

您无法通过乘以某些数字来计算它。您需要使用路径查找算法。

好消息,我写了一篇。

代码

这是一个实用工具类:

import java.util.ArrayList;
import java.util.HashMap;

public class Node
{

    private String name;

    private HashMap<Node, Node> conditionalNeigbors = new HashMap<>();

    private ArrayList<Node> neigbors = new ArrayList<>();
    private boolean visited = false;

    public Node(String name)
    {
        this.name = name;
    }

    void addNeigbor(Node n)
    {
        this.neigbors.add(n);
    }

    void addConditionalNeigbor(Node condition, Node n)
    {
        conditionalNeigbors.put(condition, n);
    }

    ArrayList<Node> getNeigbors(ArrayList<Node> path)
    {

        ArrayList<Node> toReturn = new ArrayList<>();
        ArrayList<Node> conditionals = new ArrayList<>();
        for (int i = 0; i < path.size(); i++)
        {
            if(conditionalNeigbors.containsKey(path.get(i)))
            {
                conditionals.add(conditionalNeigbors.get(path.get(i)));
            }
        }

        toReturn.addAll(neigbors);
        toReturn.addAll(conditionals);

        return toReturn;
    }

    void setVisited(boolean b)
    {
        visited = b;
    }

    boolean getVisited()
    {
        return visited;
    }

    public String getName()
    {
        return name;
    }


}

主要课程:

import java.util.ArrayList;

public class Pathfinder
{

    static boolean debug = false;

    /**
     * A B C
     *
     * D E F
     *
     * G H J
     */
    public static void main(String[] args)
    {

        Node a = new Node("A");
        Node b = new Node("B");
        Node c = new Node("C");
        Node d = new Node("D");
        Node e = new Node("E");
        Node f = new Node("F");
        Node g = new Node("G");
        Node h = new Node("H");
        Node j = new Node("J");

        a.addNeigbor(b);
        a.addNeigbor(d);
        a.addNeigbor(e);
        a.addNeigbor(h);
        a.addNeigbor(f);
        a.addConditionalNeigbor(b, c);
        a.addConditionalNeigbor(d, g);
        a.addConditionalNeigbor(e, j);

        b.addNeigbor(a);
        b.addNeigbor(d);
        b.addNeigbor(e);
        b.addNeigbor(f);
        b.addNeigbor(c);
        b.addNeigbor(g);
        b.addNeigbor(j);
        b.addConditionalNeigbor(e, h);

        c.addNeigbor(b);
        c.addNeigbor(e);
        c.addNeigbor(f);
        c.addNeigbor(d);
        c.addNeigbor(h);
        c.addConditionalNeigbor(b, a);
        c.addConditionalNeigbor(e, g);
        c.addConditionalNeigbor(f, j);

        d.addNeigbor(a);
        d.addNeigbor(b);
        d.addNeigbor(e);
        d.addNeigbor(g);
        d.addNeigbor(h);
        d.addNeigbor(c);
        d.addNeigbor(j);
        d.addConditionalNeigbor(e, f);

        e.addNeigbor(a);
        e.addNeigbor(b);
        e.addNeigbor(c);
        e.addNeigbor(d);
        e.addNeigbor(f);
        e.addNeigbor(g);
        e.addNeigbor(h);
        e.addNeigbor(j);

        f.addNeigbor(c);
        f.addNeigbor(b);
        f.addNeigbor(e);
        f.addNeigbor(h);
        f.addNeigbor(j);
        f.addNeigbor(a);
        f.addNeigbor(g);
        f.addConditionalNeigbor(e, d);

        g.addNeigbor(d);
        g.addNeigbor(e);
        g.addNeigbor(h);
        g.addNeigbor(b);
        g.addNeigbor(f);
        g.addConditionalNeigbor(d, a);
        g.addConditionalNeigbor(e, c);
        g.addConditionalNeigbor(h, j);

        h.addNeigbor(d);
        h.addNeigbor(e);
        h.addNeigbor(f);
        h.addNeigbor(g);
        h.addNeigbor(j);
        h.addNeigbor(a);
        h.addNeigbor(c);
        h.addConditionalNeigbor(e, b);

        j.addNeigbor(f);
        j.addNeigbor(e);
        j.addNeigbor(h);
        j.addNeigbor(d);
        j.addNeigbor(b);
        j.addConditionalNeigbor(h, g);
        j.addConditionalNeigbor(f, c);
        j.addConditionalNeigbor(e, a);

        ArrayList<Node> graph = new ArrayList<>();
        graph.add(a);
        graph.add(b);
        graph.add(c);
        graph.add(d);
        graph.add(e);
        graph.add(f);
        graph.add(g);
        graph.add(h);
        graph.add(j);

        int sum = 0;

        System.out.println(countPaths(b, 3, new ArrayList<>()));

        for (int k = 1; k < 10; k++)
        {
            for (int i = 0; i < graph.size(); i++)
            {
                sum += countPaths(graph.get(i), k, new ArrayList<>());
            }

            System.out.println("Number of all paths with length of " + k + ": " + sum);
            sum = 0;
        }
    }

    /*
        Finds number of all possible paths of given length, starting from given node
     */
    static int countPaths(Node start, int length, ArrayList<Node> path)
    {

        start.setVisited(true);
        path.add(start);

        ArrayList<Node> neigbors = start.getNeigbors(path);
        int neigborCount = neigbors.size();
        ArrayList<Node> unvisitedNeighbors = new ArrayList<>();

        for (int i = 0; i < neigborCount; i++)
        {
            Node temp = neigbors.get(i);

            if (temp.getVisited() == false)
            {
                unvisitedNeighbors.add(temp);
            }
        }

        int unvisitedNeighborCount = unvisitedNeighbors.size();

        if (length == 1) // Base case, no more moves, a path found, return 1
        {
            if (debug)
            {
                for (int i = 0; i < path.size(); i++)
                {
                    System.out.print(path.get(i).getName());
                }
                System.out.println("");
            }

            start.setVisited(false); // Backtrack
            path.remove(path.size() - 1);

            return 1;
        } else // There are still moves
        {
            int sum = 0;
            for (int i = 0; i < unvisitedNeighborCount; i++)
            {
                sum += countPaths(unvisitedNeighbors.get(i), length - 1, path);
            }

            start.setVisited(false); // Backtrack
            path.remove(path.size() - 1);

            return sum;
        }
    }

}

不,你不必运行它。我已经为你计算了一切:

Number of all paths with length of 1: 9
Number of all paths with length of 2: 56
Number of all paths with length of 3: 320
Number of all paths with length of 4: 1624
Number of all paths with length of 5: 7152
Number of all paths with length of 6: 26016
Number of all paths with length of 7: 72912
Number of all paths with length of 8: 140704
Number of all paths with length of 9: 140704

说明

我将问题转变为无向循环图搜索问题。

A  B  C
D  E  F 
G  H  J
  • 积分表示为Node s
  • 法律移动表示为Edge s
  • 每个Node都有一个visited属性
  • 有两种类型的边:始终可用的边和条件边。条件移动的示例:只有在访问B时才可能使用A-C。
  • 从给定节点开始搜索给定长度的路径,并使用空路径。在每次迭代中,算法获得可能的边(考虑条件边)并递归调用从下一个节点开始的子搜索。

示例

这是一个示例调用跟踪,用于从节点B开始搜索路径长度为3。

_\ countPaths(B, 3, null)
   _\ countPaths(A, 2, B)
      _\ countPaths(C, 1, BA)
      _\ countPaths(D, 1, BA)
      _\ countPaths(E, 1, BA)
      _\ countPaths(F, 1, BA)
      _\ countPaths(H, 1, BA)
   _\ countPaths(C, 2, B)
      _\ countPaths(A, 1, BC)
      _\ countPaths(D, 1, BC)
      _\ countPaths(H, 1, BC)
      _\ countPaths(E, 1, BC)
      _\ countPaths(F, 1, BC)
   _\ countPaths(D, 2, B)
      _\ countPaths(A, 1, BD)
      _\ countPaths(E, 1, BD)
      _\ countPaths(G, 1, BD)
      _\ countPaths(H, 1, BD)
      _\ countPaths(C, 1, BD)
      _\ countPaths(J, 1, BD)
   _\ countPaths(E, 2, B)
      _\ countPaths(A, 1, BE)
      _\ countPaths(C, 1, BE)
      _\ countPaths(D, 1, BE)
      _\ countPaths(F, 1, BE)
      _\ countPaths(G, 1, BE)
      _\ countPaths(H, 1, BE)
      _\ countPaths(J, 1, BE)
   _\ countPaths(F, 2, B)
      _\ countPaths(C, 1, BF)
      _\ countPaths(E, 1, BF)
      _\ countPaths(H, 1, BF)
      _\ countPaths(J, 1, BF)
      _\ countPaths(A, 1, BF)
      _\ countPaths(G, 1, BF)
   _\ countPaths(G, 2, B)
      _\ countPaths(D, 1, BG)
      _\ countPaths(E, 1, BG)
      _\ countPaths(H, 1, BG)
      _\ countPaths(F, 1, BG)
   _\ countPaths(J, 2, B)
      _\ countPaths(F, 1, BJ)
      _\ countPaths(E, 1, BJ)
      _\ countPaths(H, 1, BJ)
      _\ countPaths(D, 1, BJ)

所以它只是将问题分成较小的子问题,直到问题的长度为1,其中解为1(基本情况)。

因此,在找到来自给定节点的所有路径之后,我们需要做的就是为所有9个节点枚举此操作,这通过main()方法中的简单for循环完成,只需调用{{1方法。

答案 1 :(得分:0)

更新:发现此问题已在另一篇帖子android lock password combinations

中介绍

允许的移动包括相邻(包括对角线),骑士(例如1-> 6)和钉住移动(例如,如果路径中已经有2个,则为1> 3)。

所以在python中快速蛮力:

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, verbose) for n in next_steps(path))

[(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)]

所以android(4-9)的总数是:

>>> sum(patterns([], steps) for steps in range(4,10))
389112