annotate vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 1fec387a4317
children
rev   line source
Chris@14 1 <?php declare(strict_types=1);
Chris@14 2 /*
Chris@14 3 * This file is part of sebastian/diff.
Chris@14 4 *
Chris@14 5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
Chris@14 6 *
Chris@14 7 * For the full copyright and license information, please view the LICENSE
Chris@14 8 * file that was distributed with this source code.
Chris@14 9 */
Chris@14 10
Chris@14 11 namespace SebastianBergmann\Diff;
Chris@14 12
Chris@14 13 final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator
Chris@14 14 {
Chris@14 15 /**
Chris@14 16 * {@inheritdoc}
Chris@14 17 */
Chris@14 18 public function calculate(array $from, array $to): array
Chris@14 19 {
Chris@14 20 $cFrom = \count($from);
Chris@14 21 $cTo = \count($to);
Chris@14 22
Chris@14 23 if ($cFrom === 0) {
Chris@14 24 return [];
Chris@14 25 }
Chris@14 26
Chris@14 27 if ($cFrom === 1) {
Chris@14 28 if (\in_array($from[0], $to, true)) {
Chris@14 29 return [$from[0]];
Chris@14 30 }
Chris@14 31
Chris@14 32 return [];
Chris@14 33 }
Chris@14 34
Chris@14 35 $i = (int) ($cFrom / 2);
Chris@14 36 $fromStart = \array_slice($from, 0, $i);
Chris@14 37 $fromEnd = \array_slice($from, $i);
Chris@14 38 $llB = $this->length($fromStart, $to);
Chris@14 39 $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to));
Chris@14 40 $jMax = 0;
Chris@14 41 $max = 0;
Chris@14 42
Chris@14 43 for ($j = 0; $j <= $cTo; $j++) {
Chris@14 44 $m = $llB[$j] + $llE[$cTo - $j];
Chris@14 45
Chris@14 46 if ($m >= $max) {
Chris@14 47 $max = $m;
Chris@14 48 $jMax = $j;
Chris@14 49 }
Chris@14 50 }
Chris@14 51
Chris@14 52 $toStart = \array_slice($to, 0, $jMax);
Chris@14 53 $toEnd = \array_slice($to, $jMax);
Chris@14 54
Chris@14 55 return \array_merge(
Chris@14 56 $this->calculate($fromStart, $toStart),
Chris@14 57 $this->calculate($fromEnd, $toEnd)
Chris@14 58 );
Chris@14 59 }
Chris@14 60
Chris@14 61 private function length(array $from, array $to): array
Chris@14 62 {
Chris@14 63 $current = \array_fill(0, \count($to) + 1, 0);
Chris@14 64 $cFrom = \count($from);
Chris@14 65 $cTo = \count($to);
Chris@14 66
Chris@14 67 for ($i = 0; $i < $cFrom; $i++) {
Chris@14 68 $prev = $current;
Chris@14 69
Chris@14 70 for ($j = 0; $j < $cTo; $j++) {
Chris@14 71 if ($from[$i] === $to[$j]) {
Chris@14 72 $current[$j + 1] = $prev[$j] + 1;
Chris@14 73 } else {
Chris@14 74 $current[$j + 1] = \max($current[$j], $prev[$j + 1]);
Chris@14 75 }
Chris@14 76 }
Chris@14 77 }
Chris@14 78
Chris@14 79 return $current;
Chris@14 80 }
Chris@14 81 }