Skip to content

Commit fd51846

Browse files
authored
Merge pull request #12 from macocci7/dev_#11
#10 #11 implement combinations of multiple arrays
2 parents f6028c2 + fb5fde9 commit fd51846

11 files changed

+338
-40
lines changed

README.md

+100-5
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,13 @@ It will never exceeds the memory limit, and certanily complete the task.
9696

9797
## Methods
9898

99-
- all(): returns all combinations of the param
100-
- pairs(): returns all pairs of the param
101-
- ofN(): returns all combinations of N elements of the param
102-
- ofA2B(): returns all combinations of A to B elements of the param
99+
- `all()`: returns all combinations of the param
100+
- `pairs()`: returns all pairs of the param
101+
- `ofN()`: returns all combinations of N elements of the param
102+
- `ofA2B()`: returns all combinations of A to B elements of the param
103+
- `fromArrays()`: returns all combinations of multiple arrays
104+
105+
`fromArrays()` is only implemented in `Combination` class.
103106

104107
## Limit on the Number of Array Elements
105108

@@ -169,6 +172,23 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
169172
$b,
170173
implode("\n\t", array_map($f, $c->ofA2B($items, $a, $b)))
171174
);
175+
176+
// All Combinations of $a1, $a2 and $a3
177+
$a1 = ['A1', 'A2', ];
178+
$a2 = ['B1', 'B2', 'B3', ];
179+
$a3 = ['C1', 'C2', 'C3', 'C4', ];
180+
181+
echo "All Combinations of multiple arrays:\n";
182+
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
183+
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
184+
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));
185+
186+
$r = $c->fromArrays([$a1, $a2, $a3, ]);
187+
$n = strlen((string) count($r));
188+
echo sprintf("\tThere're %d patterns:\n", count($r));
189+
foreach ($r as $i => $e) {
190+
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
191+
}
172192
```
173193

174194
- Result:
@@ -251,6 +271,35 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
251271
(B, D, E)
252272
(C, D, E)
253273

274+
All Combinations of multiple arrays:
275+
Array1: (A1, A2)
276+
Array2: (B1, B2, B3)
277+
Array3: (C1, C2, C3, C4)
278+
There're 24 patterns:
279+
1: (A1, B1, C1)
280+
2: (A1, B1, C2)
281+
3: (A1, B1, C3)
282+
4: (A1, B1, C4)
283+
5: (A1, B2, C1)
284+
6: (A1, B2, C2)
285+
7: (A1, B2, C3)
286+
8: (A1, B2, C4)
287+
9: (A1, B3, C1)
288+
10: (A1, B3, C2)
289+
11: (A1, B3, C3)
290+
12: (A1, B3, C4)
291+
13: (A2, B1, C1)
292+
14: (A2, B1, C2)
293+
15: (A2, B1, C3)
294+
16: (A2, B1, C4)
295+
17: (A2, B2, C1)
296+
18: (A2, B2, C2)
297+
19: (A2, B2, C3)
298+
20: (A2, B2, C4)
299+
21: (A2, B3, C1)
300+
22: (A2, B3, C2)
301+
23: (A2, B3, C3)
302+
24: (A2, B3, C4)
254303
```
255304

256305
### Using Combination with Sorting
@@ -308,6 +357,23 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
308357
$b,
309358
implode("\n\t", array_map($f, $c->ofA2B($items, $a, $b, $sort)))
310359
);
360+
361+
// All Combinations of $a1, $a2 and $a3: does not support sorting
362+
$a1 = ['A1', 'A2', ];
363+
$a2 = ['B1', 'B2', 'B3', ];
364+
$a3 = ['C1', 'C2', 'C3', 'C4', ];
365+
366+
echo "All Combinations of multiple arrays:\n";
367+
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
368+
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
369+
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));
370+
371+
$r = $c->fromArrays([$a1, $a2, $a3, ]);
372+
$n = strlen((string) count($r));
373+
echo sprintf("\tThere're %d patterns:\n", count($r));
374+
foreach ($r as $i => $e) {
375+
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
376+
}
311377
```
312378

313379
- Result:
@@ -390,6 +456,35 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
390456
(B, D, E)
391457
(C, D, E)
392458

459+
All Combinations of multiple arrays:
460+
Array1: (A1, A2)
461+
Array2: (B1, B2, B3)
462+
Array3: (C1, C2, C3, C4)
463+
There're 24 patterns:
464+
1: (A1, B1, C1)
465+
2: (A1, B1, C2)
466+
3: (A1, B1, C3)
467+
4: (A1, B1, C4)
468+
5: (A1, B2, C1)
469+
6: (A1, B2, C2)
470+
7: (A1, B2, C3)
471+
8: (A1, B2, C4)
472+
9: (A1, B3, C1)
473+
10: (A1, B3, C2)
474+
11: (A1, B3, C3)
475+
12: (A1, B3, C4)
476+
13: (A2, B1, C1)
477+
14: (A2, B1, C2)
478+
15: (A2, B1, C3)
479+
16: (A2, B1, C4)
480+
17: (A2, B2, C1)
481+
18: (A2, B2, C2)
482+
19: (A2, B2, C3)
483+
20: (A2, B2, C4)
484+
21: (A2, B3, C1)
485+
22: (A2, B3, C2)
486+
23: (A2, B3, C3)
487+
24: (A2, B3, C4)
393488
```
394489

395490
### Using CombinationGenerator
@@ -545,6 +640,6 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
545640

546641
*Document Created: 2023/11/11*
547642

548-
*Document Updated: 2023/12/16*
643+
*Document Updated: 2023/12/18*
549644

550645
Copyright 2023 macocci7

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "macocci7/php-combination",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "a simple PHP library to make combinations",
55
"type": "library",
66
"license": "MIT",

example/UseCombination.php

+17
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,20 @@
4545
$b,
4646
implode("\n\t", array_map($f, $c->ofA2B($items, $a, $b)))
4747
);
48+
49+
// All Combinations of $a1, $a2 and $a3
50+
$a1 = ['A1', 'A2', ];
51+
$a2 = ['B1', 'B2', 'B3', ];
52+
$a3 = ['C1', 'C2', 'C3', 'C4', ];
53+
54+
echo "All Combinations of multiple arrays:\n";
55+
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
56+
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
57+
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));
58+
59+
$r = $c->fromArrays([$a1, $a2, $a3, ]);
60+
$n = strlen((string) count($r));
61+
echo sprintf("\tThere're %d patterns:\n", count($r));
62+
foreach ($r as $i => $e) {
63+
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
64+
}

example/UseCombination.txt

+29
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,32 @@ All Combinations of 3 to 4 elements:
7575
(B, D, E)
7676
(C, D, E)
7777

78+
All Combinations of multiple arrays:
79+
Array1: (A1, A2)
80+
Array2: (B1, B2, B3)
81+
Array3: (C1, C2, C3, C4)
82+
There're 24 patterns:
83+
1: (A1, B1, C1)
84+
2: (A1, B1, C2)
85+
3: (A1, B1, C3)
86+
4: (A1, B1, C4)
87+
5: (A1, B2, C1)
88+
6: (A1, B2, C2)
89+
7: (A1, B2, C3)
90+
8: (A1, B2, C4)
91+
9: (A1, B3, C1)
92+
10: (A1, B3, C2)
93+
11: (A1, B3, C3)
94+
12: (A1, B3, C4)
95+
13: (A2, B1, C1)
96+
14: (A2, B1, C2)
97+
15: (A2, B1, C3)
98+
16: (A2, B1, C4)
99+
17: (A2, B2, C1)
100+
18: (A2, B2, C2)
101+
19: (A2, B2, C3)
102+
20: (A2, B2, C4)
103+
21: (A2, B3, C1)
104+
22: (A2, B3, C2)
105+
23: (A2, B3, C3)
106+
24: (A2, B3, C4)

example/UseCombinationSort.php

+17
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,20 @@
4848
$b,
4949
implode("\n\t", array_map($f, $c->ofA2B($items, $a, $b, $sort)))
5050
);
51+
52+
// All Combinations of $a1, $a2 and $a3: does not support sorting
53+
$a1 = ['A1', 'A2', ];
54+
$a2 = ['B1', 'B2', 'B3', ];
55+
$a3 = ['C1', 'C2', 'C3', 'C4', ];
56+
57+
echo "All Combinations of multiple arrays:\n";
58+
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
59+
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
60+
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));
61+
62+
$r = $c->fromArrays([$a1, $a2, $a3, ]);
63+
$n = strlen((string) count($r));
64+
echo sprintf("\tThere're %d patterns:\n", count($r));
65+
foreach ($r as $i => $e) {
66+
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
67+
}

example/UseCombinationSort.txt

+29
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,32 @@ All Combinations of 3 to 4 elements:
7575
(B, D, E)
7676
(C, D, E)
7777

78+
All Combinations of multiple arrays:
79+
Array1: (A1, A2)
80+
Array2: (B1, B2, B3)
81+
Array3: (C1, C2, C3, C4)
82+
There're 24 patterns:
83+
1: (A1, B1, C1)
84+
2: (A1, B1, C2)
85+
3: (A1, B1, C3)
86+
4: (A1, B1, C4)
87+
5: (A1, B2, C1)
88+
6: (A1, B2, C2)
89+
7: (A1, B2, C3)
90+
8: (A1, B2, C4)
91+
9: (A1, B3, C1)
92+
10: (A1, B3, C2)
93+
11: (A1, B3, C3)
94+
12: (A1, B3, C4)
95+
13: (A2, B1, C1)
96+
14: (A2, B1, C2)
97+
15: (A2, B1, C3)
98+
16: (A2, B1, C4)
99+
17: (A2, B2, C1)
100+
18: (A2, B2, C2)
101+
19: (A2, B2, C3)
102+
20: (A2, B2, C4)
103+
21: (A2, B3, C1)
104+
22: (A2, B3, C2)
105+
23: (A2, B3, C3)
106+
24: (A2, B3, C4)

src/Combination.php

+75-14
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,10 @@
22

33
namespace Macocci7\PhpCombination;
44

5+
use Macocci7\PhpCombination\Util;
6+
57
class Combination
68
{
7-
/**
8-
* returns system bit
9-
* @param
10-
* @return int
11-
*/
12-
public function systemBit()
13-
{
14-
// PHP_INT_MAX:
15-
// - 32bit-system: 4 (bytes)
16-
// - 64bit-system: 8 (bytes)
17-
return PHP_INT_MAX * 8;
18-
}
19-
209
/**
2110
* returns all combinations
2211
* @param array $items
@@ -29,7 +18,7 @@ public function all(array $items, bool $sort = false)
2918
if (0 === $count) {
3019
throw new \Exception("Empty array set.");
3120
}
32-
if ($count >= $this->systemBit() - 1) {
21+
if ($count >= Util::systemBit() - 1) {
3322
throw new \Exception("Too many elements.");
3423
}
3524
$numberOfAllPatterns = 2 ** $count;
@@ -125,4 +114,76 @@ public function ofA2B(array $items, int $a, int $b, bool $sort = false)
125114
}
126115
return $combinations;
127116
}
117+
118+
/**
119+
* validates the param
120+
* @param array $arrays
121+
* @return void
122+
* @thrown \Exception
123+
*/
124+
public function validateArrays(array $arrays): void
125+
{
126+
// check if empty
127+
if (empty($arrays)) {
128+
throw new \Exception("Empty array set.");
129+
}
130+
// check types
131+
$counts = [];
132+
foreach ($arrays as $index => $array) {
133+
if (!is_array($array)) {
134+
$message = sprintf("index[%d]: Array expected.", $index);
135+
throw new \Exception($message);
136+
}
137+
$counts[] = count($array);
138+
}
139+
// check number of combination patterns
140+
$patterns = 1;
141+
foreach ($counts as $count) {
142+
$patterns *= $count;
143+
}
144+
if (is_float($patterns)) {
145+
$message = $patterns . " patterns found (over limit).";
146+
throw new \Exception($message);
147+
}
148+
}
149+
150+
/**
151+
* returns all combinations from arrays
152+
* @param array $arrays each elements must be array.
153+
* @return array
154+
* @thrown \Exception
155+
*/
156+
public function fromArrays(array $arrays): array
157+
{
158+
// validate
159+
$this->validateArrays($arrays);
160+
// initialize
161+
$combinations = [];
162+
// make combinations
163+
foreach ($arrays[0] as $i => $a) {
164+
$this->makeCombinationsRecursive([$a], $arrays, $combinations);
165+
}
166+
return $combinations;
167+
}
168+
169+
/**
170+
* makes combinations recusively
171+
* @param array $a
172+
* @param array &$arrays
173+
* @param array &$combinations
174+
* @return void
175+
*/
176+
private function makeCombinationsRecursive($a, &$arrays, &$combinations)
177+
{
178+
$countA = count($a);
179+
if ($countA < count($arrays)) {
180+
foreach ($arrays[$countA] as $b) {
181+
$c = $a;
182+
$c[] = $b;
183+
$this->makeCombinationsRecursive($c, $arrays, $combinations);
184+
}
185+
} else {
186+
$combinations[] = $a;
187+
}
188+
}
128189
}

0 commit comments

Comments
 (0)