Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<testsuite name="default">
<directory>tests</directory>
</testsuite>
<testsuite name="helper">
<directory>tests/Helper</directory>
</testsuite>
</testsuites>

<source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true">
Expand Down
37 changes: 37 additions & 0 deletions src/CountingSort.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Src;

use Src\helper\ArrayHelper;

class CountingSort
{
/**
* @param array<int> $arr
* @return array<int>
*/
public static function sort(array $arr): array
{
$length = count($arr);
if ($length <= 1) {
return $arr;
}
$minElement = ArrayHelper::getMin($arr);
$maxElement = ArrayHelper::getMax($arr);
$helperArray = [];
for ($i = $minElement; $i <= $maxElement; $i++) {
$helperArray[$i] = 0;
}
foreach ($arr as $element) {
$helperArray[$element]++;
}
for ($i = $minElement + 1; $i <= $maxElement; $i++) {
$helperArray[$i] += $helperArray[$i - 1];
}
$resultArray = [];
for ($i = 0; $i < $length; $i++) {
$resultArray[--$helperArray[$arr[$i]]] = $arr[$i];
}
return $resultArray;
}
}
56 changes: 56 additions & 0 deletions src/helper/ArrayHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Src\helper;

class ArrayHelper
{
/**
* Returns the smallest value of the array
*
* @param array<int, int|float> $array
* @return int|float
*/
public static function getMin(array $array): int|float
{
return min($array);
}

/**
* Returns the biggest value of the array
*
* @param array<int, int|float> $array
* @return int|float
*/
public static function getMax(array $array): int|float
{
return max($array);
}

/**
* Checks the array for non int values and return false if any occur
*
* @param array<int, mixed> $array
* @return bool
*/
public static function consistsOfInt(array $array): bool
{
return count($array) == count(array_filter($array, 'is_int'));
}

/**
* Checks the array is sorted
*
* @param array<int, mixed> $array
* @return bool
*/
public static function isSorted(array $array): bool
{
$length = count($array);
for ($i = 0; $i < $length - 1; $i++) {
if ($array[$i] > $array[$i + 1]) {
return false;
}
}
return true;
}
}
57 changes: 57 additions & 0 deletions tests/CountingSortTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace Tests;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Src\CountingSort;

final class CountingSortTest extends TestCase
{
#[Test]
#[DataProvider('arrayProvider')]
/**
* @param array<int> $arr
*/
public function it_should_return_the_sorted_array(array $arr): void
{
$this->assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], CountingSort::sort($arr));
}

/**
* @return array<array<int>>
*/
public static function arrayProvider(): array
{
return [
[[1, 2, 3, 4, 5, 6, 7, 8, 9]],
[[9, 8, 7, 6, 5, 4, 3, 2, 1]],
[[1, 2, 3, 9, 8, 7, 6, 5, 4]],
[[9, 8, 7, 1, 2, 3, 4, 5, 6]],
[[9, 1, 8, 2, 7, 3, 6, 4, 5]],
[[1, 9, 2, 8, 3, 7, 4, 6, 5]],
[[6, 4, 1, 8, 3, 9, 2, 5, 7]],
];
}

#[Test]
public function it_should_sort_single_element_array(): void
{
$this->assertEquals([4], CountingSort::sort([4]));
}

#[Test]
public function test_empty_array(): void
{
$this->assertEquals([], CountingSort::sort([]));
}

#[Test]
public function it_should_sort_non_consecutive_numbers_correctly(): void
{
$this->assertEquals([2, 5, 6, 8, 9], CountingSort::sort([5, 9, 6, 2, 8]));
}
}
91 changes: 91 additions & 0 deletions tests/Helper/ArrayHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

declare(strict_types=1);

namespace Tests\Helper;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Src\helper\ArrayHelper;

final class ArrayHelperTest extends TestCase
{
#[Test]
#[DataProvider('minMaxProvider')]
public function it_should_return_the_minimum_value(array $array, int|float $expectedMin): void
{
$this->assertEquals($expectedMin, ArrayHelper::getMin($array));
}

#[Test]
#[DataProvider('minMaxProvider')]
public function it_should_return_the_maximum_value(array $array, int|float $expectedMin, int|float $expectedMax): void
{
$this->assertEquals($expectedMax, ArrayHelper::getMax($array));
}

#[Test]
#[DataProvider('intValidationProvider')]
public function it_should_check_if_array_consists_of_only_integers(array $array, bool $expected): void
{
$this->assertEquals($expected, ArrayHelper::consistsOfInt($array));
}

#[Test]
#[DataProvider('isSortedProvider')]
public function it_should_check_if_array_is_sorted(array $array, bool $expected): void
{
$this->assertEquals($expected, ArrayHelper::isSorted($array));
}

/**
* Provides data for min and max tests
*
* @return array<int, array<int, mixed>>
*/
public static function minMaxProvider(): array
{
return [
[[1, 2, 3, 4, 5], 1, 5],
[[-10, 0, 10, 20], -10, 20],
[[5.5, 2.2, 3.3, 4.4], 2.2, 5.5],
[[100], 100, 100],
[[-5, -10, -15], -15, -5],
];
}

/**
* Provides data for integer validation test
*
* @return array<int, array<int, mixed>>
*/
public static function intValidationProvider(): array
{
return [
[[1, 2, 3, 4, 5], true],
[[1.1, 2.2, 3.3], false],
[[1, 2, '3', 4], false],
[[], true],
[[100, -200, 0], true],
];
}

/**
* Provides data for isSorted tests
*
* @return array<int, array<int, mixed>>
*/
public static function isSortedProvider(): array
{
return [
[[1, 2, 3, 4, 5], true], // Sorted ascending
[[5, 4, 3, 2, 1], false], // Descending
[[1, 1, 1, 1], true], // All equal
[[], true], // Empty array
[[10], true], // Single element
[[1, 2, 2, 3, 4], true], // Contains duplicates, sorted
[[1, 3, 2, 4], false], // Unsorted
];
}
}
Loading