Skip to content

Commit 31b6b60

Browse files
Pol DellaieraPol Dellaiera
Pol Dellaiera
authored and
Pol Dellaiera
committed
Update the Combinations generator based on Mark Wilson's array-subsets repository.
1 parent cba6141 commit 31b6b60

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

src/Generators/Combinations.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace drupol\phpermutations\Generators;
4+
5+
use drupol\phpermutations\Combinatorics;
6+
7+
/**
8+
* Class Combinations.
9+
*
10+
* @package drupol\phpermutations\Generators
11+
*
12+
* @author Mark Wilson <mark@89allport.co.uk>
13+
*/
14+
class Combinations extends Combinatorics {
15+
16+
/**
17+
* Alias of the get() method.
18+
*
19+
* @return \Generator
20+
* The prime generator.
21+
*/
22+
public function generator() {
23+
return $this->get($this->getDataset(), $this->getLength());
24+
}
25+
26+
/**
27+
* The generator.
28+
*
29+
* @param array $dataset
30+
* The dataset.
31+
*
32+
* @codingStandardsIgnoreStart
33+
* @return \Generator
34+
* @codingStandardsIgnoreEnd
35+
*/
36+
protected function get(array $dataset, $length) {
37+
$originalLength = count($dataset);
38+
$remainingLength = $originalLength - $length + 1;
39+
for ($i = 0; $i < $remainingLength; $i++) {
40+
$current = $dataset[$i];
41+
if ($length === 1) {
42+
yield [$current];
43+
} else {
44+
$remaining = array_slice($dataset, $i + 1);
45+
foreach ($this->get($remaining, $length - 1) as $permutation) {
46+
array_unshift($permutation, $current);
47+
yield $permutation;
48+
}
49+
}
50+
}
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function count() {
57+
return $this->fact(count($this->getDataset())) / ($this->fact($this->getLength()) * $this->fact(count($this->getDataset()) - $this->getLength()));
58+
}
59+
60+
/**
61+
* Convert the iterator into an array.
62+
*
63+
* @return array
64+
* The elements.
65+
*/
66+
public function toArray() {
67+
$data = array();
68+
69+
foreach ($this->generator() as $value) {
70+
$data[] = $value;
71+
}
72+
73+
return $data;
74+
}
75+
76+
}
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace drupol\phpermutations\Tests\Generators;
4+
5+
use drupol\phpermutations\Generators\Combinations;
6+
use drupol\phpermutations\Permutations;
7+
use PHPUnit\Framework\TestCase;
8+
9+
/**
10+
* Class PermutationsTest.
11+
*
12+
* @package drupol\phpermutations\Tests
13+
*/
14+
class CombinationsTest extends TestCase {
15+
16+
/**
17+
* The tests.
18+
*
19+
* @dataProvider simpleValueProvider
20+
*/
21+
public function testCombinationsClass($input, $expected) {
22+
$combinations = new Combinations($input['dataset'], $input['length']);
23+
24+
$this->assertEquals($input['dataset'], $combinations->getDataset());
25+
$this->assertEquals($input['length'], $combinations->getLength());
26+
$this->assertEquals($expected['dataset'], $combinations->toArray(), "\$canonicalize = true", $delta = 0.0, $maxDepth = 10, $canonicalize = TRUE);
27+
$this->assertEquals($expected['count'], $combinations->count());
28+
}
29+
30+
/**
31+
* The data provider.
32+
*
33+
* @return array
34+
* The test input values and their expected output.
35+
*/
36+
public function simpleValueProvider() {
37+
return [
38+
[
39+
'input' => [
40+
'dataset' => [1, 2, 3, 4, 5],
41+
'length' => 5,
42+
],
43+
'output' => [
44+
'dataset' => [
45+
[1, 2, 3, 4, 5],
46+
],
47+
'count' => 1,
48+
],
49+
],
50+
[
51+
'input' => [
52+
'dataset' => [1, 2, 3, 4, 5],
53+
'length' => 3,
54+
],
55+
'output' => [
56+
'dataset' => [
57+
[1, 2, 3],
58+
[1, 2, 4],
59+
[1, 2, 5],
60+
[1, 3, 4],
61+
[1, 3, 5],
62+
[1, 4, 5],
63+
[2, 3, 4],
64+
[2, 3, 5],
65+
[2, 4, 5],
66+
[3, 4, 5],
67+
],
68+
'count' => 10,
69+
],
70+
],
71+
];
72+
}
73+
74+
}

0 commit comments

Comments
 (0)