Passed
Push — master ( f7e6da...898aad )
by Pol
13:25
created

Permutations::permute()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 26
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 6
cts 6
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 9
nc 10
nop 2
crap 6
1
<?php
2
3
namespace drupol\phpermutations;
4
5
use drupol\phpermutations\Iterators\Combinations;
6
7
/**
8
 * Class Permutations.
9
 *
10
 * @package drupol\phpermutations
11
 */
12
class Permutations extends Combinatorics {
13
14
  /**
15
   * Count the number of permutations.
16
   *
17
   * @return int
18
   *   The number of element.
19
   */
20
  public function count() {
21
    return $this->fact(count($this->getDataset())) / $this->fact(count($this->getDataset()) - $this->getLength());
22 4
  }
23 4
24 4
  /**
25
   * Return the permutations.
26
   *
27
   * @return array
28
   *   The permutations result set.
29
   */
30
  public function generator() {
31
    $combinations = new Combinations($this->getDataset(), $this->getLength());
32 4
    $result = array();
33 4
34
    foreach ($combinations->toArray() as $subset) {
35
      $set = $subset;
36
      $perms = array();
37
      $size = count($subset) - 1;
38
      $perm = range(0, $size);
39
      $j = 0;
40
41
      do {
42 3
        foreach ($perm as $i) {
43 3
          $perms[$j][] = $set[$i];
44 3
        }
45
      } while ($perm = $this->permute($perm, $size) and ++$j);
46 3
47 3
      $result = array_merge($result, $perms);
48 3
    }
49 3
50 3
    return $result;
51 3
  }
52
53
  /**
54 3
   * Internal method to compute the permutations.
55 3
   *
56 3
   * @param array $items
57 3
   *   The items.
58
   * @param int $length
59 3
   *   The length.
60 3
   *
61
   * @return bool|array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|array.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
62 3
   *   The permutations.
63
   */
64
  protected function permute(array $items, $length) {
65
    // Slide down the array looking for where we're smaller than the next guy.
66
    for ($i = $length - 1; $i >= 0 && $items[$i] >= $items[$i + 1]; --$i) {
67
    }
68
69
    // If this doesn't occur, we've finished our permutations
70
    // the array is reversed: (1, 2, 3, 4) => (4, 3, 2, 1)
71
    if ($i == -1) {
72
      return FALSE;
73
    }
74
75
    // Slide down the array looking for a bigger number
76 3
    // than what we found before.
77
    for ($j = $length; $items[$j] <= $items[$i]; --$j) {
78 3
    }
79 3
80
    // Swap them.
81
    $this->swap($items[$i], $items[$j]);
82
83 3
    // Now reverse the elements in between by swapping the ends.
84 3
    for (++$i, $j = $length; $i < $j; ++$i, --$j) {
85
      $this->swap($items[$i], $items[$j]);
86
    }
87
88
    return $items;
89 3
  }
90 3
91
  /**
92
   * Swap two variables.
93 3
   *
94
   * @param mixed $x
95
   *   The first variable.
96 3
   * @param mixed $y
97 3
   *   The second variable.
98 3
   */
99
  protected function swap(&$x, &$y) {
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $x. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $y. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
100 3
    $x ^= $y ^= $x ^= $y;
101
  }
102
103
  /**
104
   * Transform the iterator into an array.
105
   *
106
   * @return array
107
   *   The permutations result set.
108
   */
109
  public function toArray() {
110
    $results = array();
111 3
112 3
    foreach ($this->generator() as $value) {
113 3
      $results[] = $value;
114
    }
115
116
    return $results;
117
  }
118
119
}
120