Skip to content

Commit

Permalink
Merge pull request #23 from macocci7/dev_1.1.0
Browse files Browse the repository at this point in the history
Update fromArrays() to return Iterator
  • Loading branch information
macocci7 committed May 15, 2024
2 parents bbe5ccb + 065fcc8 commit 116e3c5
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 54 deletions.
65 changes: 57 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- create all combinations `of N` elements
- create all combinations `of A 2 B` elements
- create all combinations between multiple arrays
- be used in data provider of PHPUnit

## 2. Contents
- [1. Features](#1-features)
Expand Down Expand Up @@ -119,16 +120,15 @@ It will never exceeds the memory limit, and certainly complete the task.
- `pairs()`: returns all pairs of the param
- `ofN()`: returns all combinations of N elements of the param
- `ofA2B()`: returns all combinations of A to B elements of the param
- `fromArrays()`: returns all combinations of multiple arrays

`fromArrays()` is only implemented in `Combination` class.
- `fromArrays()`: returns all combinations of multiple arrays as an instance of `Iterator`.

### 6.2. Macocci7\PhpCombination\CombinationGenenrator

- `all()`: returns all combinations of the param
- `pairs()`: returns all pairs of the param
- `ofN()`: returns all combinations of N elements of the param
- `ofA2B()`: returns all combinations of A to B elements of the param
- `fromArrays()`: returns all combinations of multiple arrays as an instance of `Iterator`.

## 7. Limit on the Number of Array Elements

Expand Down Expand Up @@ -290,8 +290,9 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$n = strlen((string) count($r));
echo sprintf("\tThere're %d patterns:\n", count($r));
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
Expand Down Expand Up @@ -475,8 +476,9 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$n = strlen((string) count($r));
echo sprintf("\tThere're %d patterns:\n", count($r));
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
Expand Down Expand Up @@ -648,6 +650,24 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
echo sprintf($fmt, implode(', ', $e));
}
echo "\n";

// All Combinations of $a1, $a2 and $a3
$a1 = [ 'A1', 'A2', ];
$a2 = [ 'B1', 'B2', 'B3', ];
$a3 = [ 'C1', 'C2', 'C3', 'C4', ];

echo "All Combinations of multiple arrays:\n";
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
```

- Result:
Expand Down Expand Up @@ -730,6 +750,35 @@ The max index number of array in PHP equals to `PHP_INT_MAX`.
(B, D, E)
(C, D, E)

All Combinations of multiple arrays:
Array1: (A1, A2)
Array2: (B1, B2, B3)
Array3: (C1, C2, C3, C4)
There're 24 patterns:
1: (A1, B1, C1)
2: (A1, B1, C2)
3: (A1, B1, C3)
4: (A1, B1, C4)
5: (A1, B2, C1)
6: (A1, B2, C2)
7: (A1, B2, C3)
8: (A1, B2, C4)
9: (A1, B3, C1)
10: (A1, B3, C2)
11: (A1, B3, C3)
12: (A1, B3, C4)
13: (A2, B1, C1)
14: (A2, B1, C2)
15: (A2, B1, C3)
16: (A2, B1, C4)
17: (A2, B2, C1)
18: (A2, B2, C2)
19: (A2, B2, C3)
20: (A2, B2, C4)
21: (A2, B3, C1)
22: (A2, B3, C2)
23: (A2, B3, C3)
24: (A2, B3, C4)
```

### 8.5. Using In PHPUnit
Expand Down Expand Up @@ -931,6 +980,6 @@ with patterns of `size`, `color` and `amount`.

*Document Created: 2023/11/11*

*Document Updated: 2024/04/17*
*Document Updated: 2024/05/15*

Copyright 2023 - 2024 macocci7
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "macocci7/php-combination",
"version": "1.0.5",
"version": "1.1.0",
"description": "a simple PHP library to make combinations",
"type": "library",
"license": "MIT",
Expand Down
5 changes: 3 additions & 2 deletions examples/UseCombination.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$n = strlen((string) count($r));
echo sprintf("\tThere're %d patterns:\n", count($r));
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
18 changes: 18 additions & 0 deletions examples/UseCombinationGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,21 @@
echo sprintf($fmt, implode(', ', $e));
}
echo "\n";

// All Combinations of $a1, $a2 and $a3
$a1 = [ 'A1', 'A2', ];
$a2 = [ 'B1', 'B2', 'B3', ];
$a3 = [ 'C1', 'C2', 'C3', 'C4', ];

echo "All Combinations of multiple arrays:\n";
echo sprintf("\tArray1: (%s)\n", implode(', ', $a1));
echo sprintf("\tArray2: (%s)\n", implode(', ', $a2));
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
29 changes: 29 additions & 0 deletions examples/UseCombinationGenerator.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,32 @@ All Combinations of 3 to 4 elements:
(B, D, E)
(C, D, E)

All Combinations of multiple arrays:
Array1: (A1, A2)
Array2: (B1, B2, B3)
Array3: (C1, C2, C3, C4)
There're 24 patterns:
1: (A1, B1, C1)
2: (A1, B1, C2)
3: (A1, B1, C3)
4: (A1, B1, C4)
5: (A1, B2, C1)
6: (A1, B2, C2)
7: (A1, B2, C3)
8: (A1, B2, C4)
9: (A1, B3, C1)
10: (A1, B3, C2)
11: (A1, B3, C3)
12: (A1, B3, C4)
13: (A2, B1, C1)
14: (A2, B1, C2)
15: (A2, B1, C3)
16: (A2, B1, C4)
17: (A2, B2, C1)
18: (A2, B2, C2)
19: (A2, B2, C3)
20: (A2, B2, C4)
21: (A2, B3, C1)
22: (A2, B3, C2)
23: (A2, B3, C3)
24: (A2, B3, C4)
5 changes: 3 additions & 2 deletions examples/UseCombinationSort.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@
echo sprintf("\tArray3: (%s)\n", implode(', ', $a3));

$r = $c->fromArrays([$a1, $a2, $a3, ]);
$n = strlen((string) count($r));
echo sprintf("\tThere're %d patterns:\n", count($r));
$count = count($a1) * count($a2) * count($a3);
$n = strlen((string) $count);
echo sprintf("\tThere're %d patterns:\n", $count);
foreach ($r as $i => $e) {
echo sprintf("\t%" . $n . "d: (%s)\n", $i + 1, implode(', ', $e));
}
43 changes: 3 additions & 40 deletions src/Combination.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Macocci7\PhpCombination;

use Macocci7\PhpCombination\Util;
use Macocci7\PhpCombination\CombinationTrait;

/**
* Class for generating combinations.
Expand All @@ -11,6 +12,8 @@
*/
class Combination
{
use CombinationTrait;

/**
* returns all combinations from single array.
* returns sorted array when the second param is set as true.
Expand Down Expand Up @@ -124,44 +127,4 @@ public function ofA2B(array $items, int $a, int $b, bool $sort = false)
}
return $combinations;
}

/**
* returns all combinations from arrays
* @param list<array<int, int|float|string>> $arrays each elements must be array.
* @return array<int, array<int, int|float|string>>
* @thrown \Exception
*/
public function fromArrays(array $arrays): array
{
// validate
Util::validateArrays($arrays);
// initialize
$combinations = [];
// make combinations
foreach ($arrays[0] as $a) {
$this->makeCombinationsRecursive([$a], $arrays, $combinations);
}
return $combinations;
}

/**
* makes combinations recusively
* @param array<int, int|float|string> $a
* @param list<array<int, int|float|string>> &$arrays
* @param array<int, int|float|string> &$combinations
* @return void
*/
private function makeCombinationsRecursive($a, &$arrays, &$combinations)
{
$countA = count($a);
if ($countA < count($arrays)) {
foreach ($arrays[$countA] as $b) {
$c = $a;
$c[] = $b;
$this->makeCombinationsRecursive($c, $arrays, $combinations);
}
} else {
$combinations[] = $a;
}
}
}
3 changes: 3 additions & 0 deletions src/CombinationGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Macocci7\PhpCombination;

use Macocci7\PhpCombination\Util;
use Macocci7\PhpCombination\CombinationTrait;

/**
* Class for generating combinations with Generator.
Expand All @@ -11,6 +12,8 @@
*/
class CombinationGenerator
{
use CombinationTrait;

/**
* returns all combinations
* @param array<int, int|float|string> $items
Expand Down
107 changes: 107 additions & 0 deletions src/CombinationIterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Macocci7\PhpCombination;

/**
* Class for generating combinations with Iterator.
*
* @implements \Iterator<int, mixed>
* @author macocci7 <[email protected]>
* @license MIT
*/
class CombinationIterator implements \Iterator
{
/**
* @var mixed[] $arrays
*/
private array $arrays;

/**
* @var int[]|null $pointers
*/
private array|null $pointers = null;

/**
* @var int $key
*/
private int $key;

/**
* constructor
*
* @param array<array<int, mixed[]>> $arrays
*/
public function __construct(array $arrays)
{
$this->arrays = $arrays;
$this->pointers = array_fill(0, count($arrays), 0);
$this->key = 0;
}

/**
* returns current element
*
* @return mixed
*/
public function current(): mixed
{
$result = [];
foreach ($this->pointers as $arrayIndex => $elementIndex) {
$result[] = $this->arrays[$arrayIndex][$elementIndex] ?? null;
}
return $result;
}

/**
* returns current key.
*
* @return int
*/
public function key(): int
{
return $this->key;
}

/**
* advances the pointer one step.
*/
public function next(): void
{
for ($i = count($this->pointers) - 1; $i >= 0; $i--) {
if ($this->pointers[$i] < count($this->arrays[$i]) - 1) {
$this->pointers[$i]++;
// 繰り上げた位より下位の位をゼロにセット
// 1199 + 1 = 1200
// ^ ^^
$count = count($this->pointers);
for ($j = $i + 1; $j < $count; $j++) {
$this->pointers[$j] = 0;
}
$this->key++;
return;
}
}
$this->pointers = null;
}

/**
* rewinds the pointers and the key.
*
* @return void
*/
public function rewind(): void
{
$this->pointers = array_fill(0, count($this->arrays), 0);
$this->key = 0;
}

/**
* returns if the pointers are valid.
*
* @return bool
*/
public function valid(): bool
{
return $this->pointers !== null;
}
}
Loading

0 comments on commit 116e3c5

Please sign in to comment.