Test Failed
Pull Request — master (#49)
by Josh
04:36
created

LcsService::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 5
c 1
b 0
f 1
nc 2
nop 1
dl 0
loc 10
rs 9.4285
1
<?php
2
3
namespace Caxy\HtmlDiff;
4
5
class LcsService
6
{
7
    /**
8
     * @var null|callable
9
     */
10
    protected $comparator;
11
12
    /**
13
     * LcsService constructor.
14
     *
15
     * @param null|callable $comparator
16
     */
17
    public function __construct($comparator = null)
18
    {
19
        if (null === $comparator) {
20
            $comparator = function ($a, $b) {
21
                return $a === $b;
22
            };
23
        }
24
25
        $this->comparator = $comparator;
26
    }
27
28
    /**
29
     * @param array $a
30
     * @param array $b
31
     *
32
     * @return array
33
     */
34
    public function longestCommonSubsequence(array $a, array $b)
35
    {
36
        $c = array();
37
38
        $m = count($a);
39
        $n = count($b);
40
41
        $comparator = $this->comparator;
42
43
        for ($i = 0; $i <= $m; $i++) {
44
            $c[$i][0] = 0;
45
        }
46
47
        for ($j = 0; $j <= $n; $j++) {
48
            $c[0][$j] = 0;
49
        }
50
51
52
        for ($i = 1; $i <= $m; $i++) {
53
            for ($j = 1; $j <= $n; $j++) {
54
                if ($comparator($a[$i - 1], $b[$j - 1])) {
55
                    $c[$i][$j] = 1 + (isset($c[$i - 1][$j - 1]) ? $c[$i - 1][$j - 1] : 0);
56
                } else {
57
                    $c[$i][$j] = max(
58
                        isset($c[$i][$j - 1]) ? $c[$i][$j - 1] : 0,
59
                        isset($c[$i - 1][$j]) ? $c[$i - 1][$j] : 0
60
                    );
61
                }
62
            }
63
        }
64
65
        $lcs = array_pad([], $m + 1, 0);
66
        $this->compileMatches($c, $a, $b, $m, $n, $comparator, $lcs);
67
68
        return $lcs;
69
    }
70
71
    protected function compileMatches($c, $a, $b, $i, $j, $comparator, &$matches)
72
    {
73
        if ($i > 0 && $j > 0 && $comparator($a[$i - 1], $b[$j - 1])) {
74
            $this->compileMatches($c, $a, $b, $i - 1, $j - 1, $comparator, $matches);
75
            $matches[$i] = $j;
76
        } elseif ($j > 0 && ($i === 0 || $c[$i][$j - 1] >= $c[$i - 1][$j])) {
77
            $this->compileMatches($c, $a, $b, $i, $j - 1, $comparator, $matches);
78
        } elseif ($i > 0 && ($j === 0 || $c[$i][$j - 1] < $c[$i - 1][$j])) {
79
            $this->compileMatches($c, $a, $b, $i - 1, $j, $comparator, $matches);
80
        }
81
    }
82
}
83