Skip to content

Commit df8d30d

Browse files
authored
Add ArrayHelper (#9)
1 parent 0975985 commit df8d30d

File tree

4 files changed

+206
-1
lines changed

4 files changed

+206
-1
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ test: test-unit test-functional codestyle phpstan
7878

7979
.PHONY: coverage
8080
coverage:
81-
COVERAGE_OUTPUT_STYLE=html make test
81+
COVERAGE_OUTPUT_STYLE=html make test-unit
82+
COVERAGE_OUTPUT_STYLE=html make test-functional
8283

8384
.PHONY: test-unit
8485
ifdef PHPUNIT_COVERAGE_OPTION
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Naming conventions & mapping
2+
3+
## SplHeap
4+
SplMinHeap / SplMaxHeap
5+
6+
Construct ➙ 𝑂⟮𝑛⟯
7+
8+
#### Add an element
9+
`add()``insert()`
10+
11+
TC: 𝑂⟮㏒ 𝑛⟯<br>
12+
SC: 𝑂⟮𝟷⟯
13+
14+
#### Pop an element
15+
`pop()``extract()`
16+
17+
TC: 𝑂⟮㏒ 𝑛⟯<br>
18+
SC: 𝑂⟮𝟷⟯
19+
20+
#### Peek element
21+
`peek()``top()`
22+
23+
TC: 𝑂⟮𝟷⟯<br>
24+
SC: 𝑂⟮𝟷⟯
25+
26+
#### DS size
27+
`size()``count()`
28+
29+
TC: 𝑂⟮𝟷⟯<br>
30+
SC: 𝑂⟮𝟷⟯
31+
32+
33+
## SplPriorityQueue
34+
ℹ️ Implemented using a `SplMaxHeap`
35+
36+
#### Add an element
37+
`add()``insert()`
38+
39+
TC: 𝑂⟮㏒ 𝑛⟯<br>
40+
SC: 𝑂⟮𝟷⟯
41+
42+
#### Pop an element
43+
`pop()``extract()`
44+
45+
TC: 𝑂⟮㏒ 𝑛⟯<br>
46+
SC: 𝑂⟮𝟷⟯
47+
48+
#### Peek element
49+
`peek()``top()`
50+
51+
TC: 𝑂⟮𝟷⟯<br>
52+
SC: 𝑂⟮𝟷⟯
53+
54+
#### DS size
55+
`size()``count()`
56+
57+
TC: 𝑂⟮𝟷⟯<br>
58+
SC: 𝑂⟮𝟷⟯
59+
60+
61+
## SplQueue
62+
ℹ️ Implemented using a `SplDoublyLinkedList`
63+
64+
#### Enqueue an element
65+
`enqueue()`
66+
67+
#### Dequeue an element
68+
`dequeue()`
69+
70+
#### Peek element
71+
`peek()``bottom()`
72+
73+
#### DS size
74+
`size()``count()`
75+
76+
#### Front / Rear
77+
⚠️ Not actually available on "real" queue !
78+
79+
`front()``bottom()``peek()`<br>
80+
`rear()``top()`
81+
82+
## SplStack
83+
ℹ️ Implemented using a `SplDoublyLinkedList`
84+
85+
#### push an element
86+
`push()`
87+
88+
#### pop an element
89+
`pop()`
90+
91+
#### Peek element
92+
`peek()``top()`
93+
94+
#### DS size
95+
`size()``count()`
96+
97+
#### Front / Rear
98+
⚠️ Not actually available on "real" stack !
99+
100+
`front()``top()``peek()`<br>
101+
`rear()``bottom()`

src/Helper/ArrayHelper.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Yoanm\CommonDSA\Helper;
4+
5+
use ArrayAccess;
6+
use Countable;
7+
8+
class ArrayHelper
9+
{
10+
/**
11+
* Insert the value at the given index and push back values from $index to tail index
12+
*
13+
*
14+
* ### Time/Space complexity
15+
* With:
16+
* - 𝑛 equals the provided list length.
17+
* - 𝑥 equals to the number of values to push back (𝑥 = ⟮𝑛 − 𝟷 − $index⟯).
18+
*
19+
* TC: 𝑂⟮𝑥⟯ - Algo will iterate over each and every value to push back
20+
*
21+
* SC: 𝑂⟮𝟷⟯ - Constant extra space
22+
*
23+
* @param array<mixed> $list ⚠ Must be a 0 indexed list, 0 to n consecutive indexes !
24+
* @phpstan-param list<mixed> $list
25+
* @param int $index ⚠ Expected to be between 0 and 𝑛 !
26+
* @param mixed $value
27+
*/
28+
public static function insertAt(array &$list, int $index, mixed $value): void
29+
{
30+
$tailIdx = count($list) - 1;
31+
32+
// 1. Move values until the end of original list
33+
$prevValue = $value;
34+
while ($index <= $tailIdx) {
35+
// Backup original value at $index + replace original value by the previous value
36+
[$prevValue, $list[$index]] = [$list[$index], $prevValue]; // @phpstan-ignore parameterByRef.type
37+
++$index;
38+
}
39+
40+
// 2. Append the original tail value at the end of the list (=new index !)
41+
$list[$index] = $prevValue; // @phpstan-ignore parameterByRef.type
42+
}
43+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Technical\Helper;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Yoanm\CommonDSA\Helper\ArrayHelper as Helper;
9+
10+
/**
11+
* @covers \Yoanm\CommonDSA\Helper\ArrayHelper
12+
*/
13+
final class ArrayHelperTest extends TestCase
14+
{
15+
/**
16+
* @dataProvider provideFromLevelOrderListTestCases
17+
*/
18+
public function testInsertAt(array $list, int $index, mixed $value, array $expected): void
19+
{
20+
Helper::insertAt($list, $index, $value);
21+
22+
self::assertSame($expected, $list);
23+
}
24+
25+
public function provideFromLevelOrderListTestCases(): array
26+
{
27+
return [
28+
'Insert in the middle of the list' => [
29+
'list' => [1,2,3,4,5,7,8,9],
30+
'index' => 5,
31+
'value' => 6,
32+
'expected' => [1,2,3,4,5,6,7,8,9],
33+
],
34+
'Replace head value' => [
35+
'list' => [2,3,4,5,6,7,8,9],
36+
'index' => 0,
37+
'value' => 1,
38+
'expected' => [1,2,3,4,5,6,7,8,9],
39+
],
40+
'Replace tail value' => [
41+
'list' => [1,2,3,4,5,6,7,9],
42+
'index' => 7,
43+
'value' => 8,
44+
'expected' => [1,2,3,4,5,6,7,8,9],
45+
],
46+
'As new tail value' => [
47+
'list' => [1,2,3,4,5,6,7,8],
48+
'index' => 8,
49+
'value' => 9,
50+
'expected' => [1,2,3,4,5,6,7,8,9],
51+
],
52+
'Empty list' => [
53+
'list' => [],
54+
'index' => 0,
55+
'value' => 1,
56+
'expected' => [1],
57+
],
58+
];
59+
}
60+
}

0 commit comments

Comments
 (0)