Min::path()   B
last analyzed

Complexity

Conditions 10
Paths 21

Size

Total Lines 41
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 22
c 1
b 0
f 0
nc 21
nop 2
dl 0
loc 41
ccs 23
cts 23
cp 1
crap 10
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Component\Math\Graph\Path;
6
7
/**
8
 * Find least number of hops between nodes collection.
9
 * Graph should be considered as oriented.
10
 * @author Pierre Fromager <[email protected]>
11
 */
12
class Min
13
{
14
    /**
15
     * graph
16
     *
17
     * @var array
18
     */
19
    protected $graph;
20
21
    /**
22
     * visited
23
     *
24
     * @var array
25
     */
26
    protected $visited = [];
27
28
    /**
29
     * instanciate
30
     *
31
     * @param array $graph
32
     */
33 2
    public function __construct(array $graph)
34
    {
35 2
        $this->graph = $graph;
36
    }
37
38
    /**
39
     * return path search as array
40
     *
41
     * @param string  $origin
42
     * @param string  $destination
43
     * @return array
44
     */
45 1
    public function path(string $origin, string $destination): array
46
    {
47
        // check exists origin destination
48 1
        if (!isset($this->graph[$origin]) || !isset($this->graph[$destination])) {
49 1
            return [];
50
        }
51
        // mark all nodes as unvisited
52 1
        foreach ($this->graph as $vertex => $adj) {
53 1
            $this->visited[$vertex] = false;
54
        }
55
        // create an empty queue
56 1
        $q = new \SplQueue();
57
        // enqueue the origin vertex and mark as visited
58 1
        $q->enqueue($origin);
59 1
        $this->visited[$origin] = true;
60
        // this is used to track the path back from each node
61 1
        $path = [];
62 1
        $path[$origin] = new \SplDoublyLinkedList();
63 1
        $path[$origin]->setIteratorMode(
64 1
            \SplDoublyLinkedList::IT_MODE_FIFO | \SplDoublyLinkedList::IT_MODE_KEEP
65
        );
66 1
        $path[$origin]->push($origin);
67
        // while queue is not empty and destination not found
68 1
        while (!$q->isEmpty() && $q->bottom() != $destination) {
69 1
            $t = $q->dequeue();
70 1
            if (!empty($this->graph[$t])) {
71
                // for each adjacent neighbor
72 1
                foreach ($this->graph[$t] as $vertex) {
73 1
                    if (!$this->visited[$vertex]) {
74
                        // if not yet visited, enqueue vertex and mark
75
                        // as visited
76 1
                        $q->enqueue($vertex);
77 1
                        $this->visited[$vertex] = true;
78
                        // add vertex to current path
79 1
                        $path[$vertex] = clone $path[$t];
80 1
                        $path[$vertex]->push($vertex);
81
                    }
82
                }
83
            }
84
        }
85 1
        return (isset($path[$destination])) ? iterator_to_array($path[$destination]) : [];
86
    }
87
}
88