solutions.problem15   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 82
rs 10
c 0
b 0
f 0
wmc 9

2 Functions

Rating   Name   Duplication   Size   Complexity  
A solve() 0 5 1
B search() 0 34 8
1
"""
2
Project Euler Problem 15: Lattice Paths
3
=======================================
4
5
.. module:: solutions.problem15
6
   :synopsis: My solution to problem #15.
7
8
The source code for this problem can be
9
`found here <https://bitbucket.org/nekedome/project-euler/src/master/solutions/problem15.py>`_.
10
11
Problem Statement
12
#################
13
14
Starting in the top left corner of a :math:`2 \\times 2` grid, and only being able to move to the right and down, there
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (119/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
15
are exactly :math:`6` routes to the bottom right corner.
16
17
.. image:: ../images/p015.gif
18
   :align: center
19
20
How many such routes are there through a :math:`20 \\times 20` grid?
21
22
Solution Discussion
23
###################
24
25
Use a dynamic programming algorithm to count the number of paths through a search tree.
26
27
Solution Implementation
28
#######################
29
30
.. literalinclude:: ../../solutions/problem15.py
31
   :language: python
32
   :lines: 35-
33
"""
34
35
from typing import Dict, List, Optional, Tuple
36
37
38
def search(length: int, moves: Optional[List[int]] = None, solutions: Optional[Dict[Tuple[int, int], int]] = None)\
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
39
        -> int:
40
    """ Recursive tree search, branching on possible choices (left or down)
41
42
    Dynamic programming (solutions) is used to cache previous, partial, answers avoiding re-computation.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
43
44
    :param length: the length of each axis in the grid
45
    :param moves: the moves made (down and right) at this point of the search
46
    :param solutions: partial solutions cache for the avoidance of redundant computations
47
    :return: the number of search paths through a :math:`length \\times length` grid
48
    """
49
50
    if moves is None:
51
        moves = [0, 0]  # initialise moves to represent none have been made
52
53
    assert moves[0] <= length, "you cannot move past the edge"
54
    assert moves[1] <= length, "you cannot move past the edge"
55
56
    if solutions is None:
57
        solutions = {}  # initialise solutions to the empty cache
58
59
    if moves[0] == length:
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
60
        return 1  # base case: no further branching possible
61
    elif moves[1] == length:
62
        return 1  # base case: no further branching possible
63
    elif tuple(moves) in solutions:
64
        return solutions[tuple(moves)]  # returned cached answer
65
    else:
66
        # Branch down each possible path via recursion
67
        answer0 = search(length, [moves[0] + 1, moves[1]], solutions)
68
        solutions[(moves[0] + 1, moves[1])] = answer0
69
        answer1 = search(length, [moves[0], moves[1] + 1], solutions)
70
        solutions[(moves[0], moves[1] + 1)] = answer1
71
        return answer0 + answer1
72
73
74
def solve():
75
    """ Compute the answer to Project Euler's problem #15 """
76
    target = 20
77
    answer = search(target)
78
    return answer
79
80
81
expected_answer = 137846528820
0 ignored issues
show
Coding Style Naming introduced by
The name expected_answer does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
82