From 41d9aa9eb50090eaec12c23b498d2c5a21756391 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 18:04:47 +0100 Subject: [PATCH 01/15] initial commit --- src/ShellSort.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/ShellSort.php diff --git a/src/ShellSort.php b/src/ShellSort.php new file mode 100644 index 0000000..b390191 --- /dev/null +++ b/src/ShellSort.php @@ -0,0 +1,15 @@ + $arr + * @return array + */ + public static function sort(array $arr): array + { + return $arr; + } +} From f0c798dce5ede9baf6145331f651beb5a763094b Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 19:26:05 +0100 Subject: [PATCH 02/15] implement helper for step sequence calculation --- src/ShellSort.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/ShellSort.php b/src/ShellSort.php index b390191..ee6877d 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -12,4 +12,19 @@ public static function sort(array $arr): array { return $arr; } + + /** + * Returns the next step sequence based on the current lenght/step + * + * @param int $start current step sequence or array length + * @return int next lower step sequence + */ + private function stepSequence(int $start): int + { + $next = 1; + while ($start > $new = ($next + 1) * 3) { + $next = $new; + } + return $next; + } } From adb1f1ea28575895d1453cfe9d835bc5eeb7616d Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 19:27:26 +0100 Subject: [PATCH 03/15] make helper static --- src/ShellSort.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index ee6877d..333b98d 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -19,7 +19,7 @@ public static function sort(array $arr): array * @param int $start current step sequence or array length * @return int next lower step sequence */ - private function stepSequence(int $start): int + private static function stepSequence(int $start): int { $next = 1; while ($start > $new = ($next + 1) * 3) { From d44691d1c2423b838e18984a9b9239b8866fc4fa Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 19:49:43 +0100 Subject: [PATCH 04/15] add outer iteration logic --- src/ShellSort.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ShellSort.php b/src/ShellSort.php index 333b98d..d7c95f6 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -10,6 +10,17 @@ class ShellSort */ public static function sort(array $arr): array { + $length = count($arr); + $stepSequence = self::stepSequence($length); + do { + $stepSequence = self::stepSequence($stepSequence); + $columns = (int)$length / $stepSequence; + for ($i = 0; $i < $columns; $i++) { + for ($j = $i + $stepSequence; $j<$length; $j += $stepSequence) { + // basic insertion sort + } + } + } while ($stepSequence > 1); return $arr; } From 47afc11a5b75305be0a247df3f0a4bf579c90854 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 19:53:14 +0100 Subject: [PATCH 05/15] add basic insertion sort logic --- src/ShellSort.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index d7c95f6..55cf4d8 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -17,7 +17,13 @@ public static function sort(array $arr): array $columns = (int)$length / $stepSequence; for ($i = 0; $i < $columns; $i++) { for ($j = $i + $stepSequence; $j<$length; $j += $stepSequence) { - // basic insertion sort + for ($k = $j - $stepSequence; $k >= $i; $k -= $stepSequence) { + if ($arr[$j] < $arr[$k]) { + $safe = $arr[$k]; + $arr[$k] = $arr[$j]; + $arr[$j] = $safe; + } + } } } } while ($stepSequence > 1); From c09aad0abeed780338b5f3d122b48c0a3deb5f5d Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 20:09:15 +0100 Subject: [PATCH 06/15] remove first stepSequence call to prevent reduction of stepSequence initially --- src/ShellSort.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index 55cf4d8..d627a2e 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -11,7 +11,7 @@ class ShellSort public static function sort(array $arr): array { $length = count($arr); - $stepSequence = self::stepSequence($length); + $stepSequence = $length; do { $stepSequence = self::stepSequence($stepSequence); $columns = (int)$length / $stepSequence; From fa2535b2eaf6008f44ce5988cedbd3404e87bf81 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 20:09:46 +0100 Subject: [PATCH 07/15] fix column int cast --- src/ShellSort.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index d627a2e..6a13f7b 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -14,7 +14,7 @@ public static function sort(array $arr): array $stepSequence = $length; do { $stepSequence = self::stepSequence($stepSequence); - $columns = (int)$length / $stepSequence; + $columns = (int)($length / $stepSequence); for ($i = 0; $i < $columns; $i++) { for ($j = $i + $stepSequence; $j<$length; $j += $stepSequence) { for ($k = $j - $stepSequence; $k >= $i; $k -= $stepSequence) { From 60971ac69a3af280f93f2d2e1984799a158ec552 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 20:50:16 +0100 Subject: [PATCH 08/15] remove column logic and outer loop --- src/ShellSort.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index 6a13f7b..dbb7e20 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -14,15 +14,12 @@ public static function sort(array $arr): array $stepSequence = $length; do { $stepSequence = self::stepSequence($stepSequence); - $columns = (int)($length / $stepSequence); - for ($i = 0; $i < $columns; $i++) { - for ($j = $i + $stepSequence; $j<$length; $j += $stepSequence) { - for ($k = $j - $stepSequence; $k >= $i; $k -= $stepSequence) { - if ($arr[$j] < $arr[$k]) { - $safe = $arr[$k]; - $arr[$k] = $arr[$j]; - $arr[$j] = $safe; - } + for ($i = 0; $i < $length; $i++) { + for ($j = $i - $stepSequence; $j >= 0; $j -= $stepSequence) { + if ($arr[$j] > $arr[$i]) { + $safe = $arr[$j]; + $arr[$j] = $arr[$i]; + $arr[$i] = $safe; } } } From 2b0a65386802f01969c5d7a28dd256de97a023f6 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 21:41:14 +0100 Subject: [PATCH 09/15] scrap everything and start over --- src/ShellSort.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index dbb7e20..3003bc7 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -13,16 +13,6 @@ public static function sort(array $arr): array $length = count($arr); $stepSequence = $length; do { - $stepSequence = self::stepSequence($stepSequence); - for ($i = 0; $i < $length; $i++) { - for ($j = $i - $stepSequence; $j >= 0; $j -= $stepSequence) { - if ($arr[$j] > $arr[$i]) { - $safe = $arr[$j]; - $arr[$j] = $arr[$i]; - $arr[$i] = $safe; - } - } - } } while ($stepSequence > 1); return $arr; } From a4d3a5a7cc3074fd75dbbbe4c492565e490903f9 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 21:43:58 +0100 Subject: [PATCH 10/15] iterate over the first elements of the column --- src/ShellSort.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ShellSort.php b/src/ShellSort.php index 3003bc7..fe5291f 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -12,7 +12,10 @@ public static function sort(array $arr): array { $length = count($arr); $stepSequence = $length; + $columns = (int)($length / $stepSequence); do { + for ($i = 0; $i < $columns; $i++) { + } } while ($stepSequence > 1); return $arr; } From a071b33275db5f2cf7bf433ea332b84628c5c940 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 21:49:47 +0100 Subject: [PATCH 11/15] perform insertion sort in column starting at the second element of the column and going over all the elements of the columns, sorting them this way --- src/ShellSort.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ShellSort.php b/src/ShellSort.php index fe5291f..fda97b8 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -15,6 +15,13 @@ public static function sort(array $arr): array $columns = (int)($length / $stepSequence); do { for ($i = 0; $i < $columns; $i++) { + for ($j = $i+$stepSequence; $j < $length; $j += $stepSequence) { + for ($k = $j-$stepSequence; $k >= $i; $k -= $stepSequence) { + if ($arr[$j] < $arr[$k]) { + [$arr[$j], $arr[$k]] = [$arr[$k], $arr[$j]]; + } + } + } } } while ($stepSequence > 1); return $arr; From 727b12c41dc398d4ebd34690fe70a707295e3a06 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 21:51:12 +0100 Subject: [PATCH 12/15] add reduction of stepSequence effectively approaching the basic insertion sort but with a more sorted array --- src/ShellSort.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ShellSort.php b/src/ShellSort.php index fda97b8..b7fd7c0 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -14,6 +14,7 @@ public static function sort(array $arr): array $stepSequence = $length; $columns = (int)($length / $stepSequence); do { + $stepSequence = self::stepSequence($stepSequence); for ($i = 0; $i < $columns; $i++) { for ($j = $i+$stepSequence; $j < $length; $j += $stepSequence) { for ($k = $j-$stepSequence; $k >= $i; $k -= $stepSequence) { From d3bdc842551de2cfdf555a47bb4e9ebb71091878 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 22:02:18 +0100 Subject: [PATCH 13/15] move column calculation to correct place --- src/ShellSort.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index b7fd7c0..722aa66 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -12,9 +12,9 @@ public static function sort(array $arr): array { $length = count($arr); $stepSequence = $length; - $columns = (int)($length / $stepSequence); do { $stepSequence = self::stepSequence($stepSequence); + $columns = (int)($length / $stepSequence); for ($i = 0; $i < $columns; $i++) { for ($j = $i+$stepSequence; $j < $length; $j += $stepSequence) { for ($k = $j-$stepSequence; $k >= $i; $k -= $stepSequence) { From ba59e985daf07c0afc9dddb1d3989a6eb8742227 Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 22:16:01 +0100 Subject: [PATCH 14/15] refactor to correct approach of columns --- src/ShellSort.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ShellSort.php b/src/ShellSort.php index 722aa66..97bcbf6 100644 --- a/src/ShellSort.php +++ b/src/ShellSort.php @@ -14,12 +14,11 @@ public static function sort(array $arr): array $stepSequence = $length; do { $stepSequence = self::stepSequence($stepSequence); - $columns = (int)($length / $stepSequence); - for ($i = 0; $i < $columns; $i++) { + for ($i = 0; $i < $stepSequence; $i++) { for ($j = $i+$stepSequence; $j < $length; $j += $stepSequence) { - for ($k = $j-$stepSequence; $k >= $i; $k -= $stepSequence) { - if ($arr[$j] < $arr[$k]) { - [$arr[$j], $arr[$k]] = [$arr[$k], $arr[$j]]; + for ($k = $j; $k >= $stepSequence; $k -= $stepSequence) { + if ($arr[$k - $stepSequence] > $arr[$k]) { + [$arr[$k], $arr[$k - $stepSequence]] = [$arr[$k - $stepSequence], $arr[$k]]; } } } From 6cbdbafb5c89f0ac95db54d72d09db0e763b8d7f Mon Sep 17 00:00:00 2001 From: dimitrijjedich Date: Sat, 21 Dec 2024 22:16:52 +0100 Subject: [PATCH 15/15] add tests for shell sort --- tests/ShellSortTest.php | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/ShellSortTest.php diff --git a/tests/ShellSortTest.php b/tests/ShellSortTest.php new file mode 100644 index 0000000..3beba15 --- /dev/null +++ b/tests/ShellSortTest.php @@ -0,0 +1,60 @@ +assertEquals([1,2,3,4,5,6,7,8,9], ShellSort::sort($arr)); + } + + /* + * @return array + */ + 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], ShellSort::sort([4])); + } + + #[Test] + public function test_empty_array(): void + { + $this->assertEquals([], ShellSort::sort([])); + } + + #[Test] + public function it_should_sort_non_consecutive_numbers_correctly(): void + { + $this->assertEquals([2,5,6,8,9], ShellSort::sort([5,9,6,2,8])); + } + + #[Test] + public function it_can_sort_array_with_1000_elements(): void + { + $random = range(1, 1000); + shuffle($random); + $this->assertEquals(range(1, 1000), ShellSort::sort($random)); + } +}