Skip to content

Commit

Permalink
Change lowest_missing function signature
Browse files Browse the repository at this point in the history
  • Loading branch information
oboukli committed Aug 2, 2023
1 parent c158b98 commit d708d90
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 44 deletions.
14 changes: 11 additions & 3 deletions benchmark/first_missing_positive_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

// SPDX-License-Identifier: MIT

#include <array>

#include <catch2/catch_test_macros.hpp>

#include <nanobench.h>
Expand All @@ -13,14 +15,18 @@
#include "forfun/first_missing_positive.hpp"

TEST_CASE("forfun::first_missing_positive benchmarking") {
using ContainerType = std::array<int, 128>;

ankerl::nanobench::Bench()

.title("Lowest missing positive integer")

.run(
NAMEOF_RAW(forfun::first_missing_positive::lowest_missing).c_str(),
NAMEOF_RAW(
forfun::first_missing_positive::lowest_missing<ContainerType>)
.c_str(),
[]() {
auto r{forfun::first_missing_positive::lowest_missing({
ContainerType a{
// clang-format off
9, 8, 7, 6, 5, 4, 3, 2, 1, -1,
9, 8, 7, 6, 5, 4, 3, 2, 1, -1,
Expand All @@ -36,7 +42,9 @@ TEST_CASE("forfun::first_missing_positive benchmarking") {
9, 8, 7, 6, 5, 4, 3, 2, 1, -1,
0, 0, 0, 0, 0, 0, 0, 0,
// clang-format on
})};
};

auto r{forfun::first_missing_positive::lowest_missing(a)};
ankerl::nanobench::doNotOptimizeAway(r);
})

Expand Down
6 changes: 3 additions & 3 deletions include/forfun/first_missing_positive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#include <algorithm>
#include <cstddef>
#include <vector>

namespace forfun::first_missing_positive {

Expand All @@ -43,10 +42,11 @@ constexpr inline void quasi_sort(RandomIt first, RandomIt const src) noexcept {

} // namespace

[[nodiscard]] constexpr int lowest_missing(std::vector<int> numbers) noexcept {
auto max{numbers.size()};
template <typename T>
[[nodiscard]] constexpr inline int lowest_missing(T& numbers) noexcept {
auto begin{numbers.begin()};
auto end{numbers.end()};
auto max{numbers.size()};

for (auto it{begin}; it != end; ++it) {
int const current{*it};
Expand Down
120 changes: 82 additions & 38 deletions test/first_missing_positive_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,104 @@

// SPDX-License-Identifier: MIT

#include <array>
#include <vector>

#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include <catch2/generators/catch_generators.hpp>

#include "forfun/first_missing_positive.hpp"

TEST_CASE("first_missing_positive") {
using forfun::first_missing_positive::lowest_missing;

SECTION("Basic") {
REQUIRE(lowest_missing({}) == 1);
REQUIRE(lowest_missing({0}) == 1);
REQUIRE(lowest_missing({1}) == 2);
REQUIRE(lowest_missing({2}) == 1);
}
SECTION("Empty container") {
std::array<int, 0> test_input{};

SECTION("Two elements") {
REQUIRE(lowest_missing({-1, 0}) == 1);
REQUIRE(lowest_missing({0, 1}) == 2);
REQUIRE(lowest_missing({1, 0}) == 2);
REQUIRE(lowest_missing({1, 2}) == 3);
REQUIRE(lowest_missing({2, 1}) == 3);
}
CAPTURE(test_input);
CHECK(test_input.size() == 0);

SECTION("Duplicates") {
REQUIRE(lowest_missing({0, 0, 0, 0}) == 1);
REQUIRE(lowest_missing({1, 1, 1, 1}) == 2);
REQUIRE(lowest_missing({6, 6, 6, 6, 6}) == 1);
REQUIRE(lowest_missing({6, 6, 6, 6, 1}) == 2);
REQUIRE(lowest_missing(test_input) == 1);
}

SECTION("Negative numbers") {
REQUIRE(lowest_missing({-2}) == 1);
REQUIRE(lowest_missing({-1}) == 1);
REQUIRE(lowest_missing({-1, -1, -1, -1}) == 1);
REQUIRE(lowest_missing({-6, -5, -4, 1, 2}) == 3);
SECTION("One number") {
auto [test_input, expected_output]
= GENERATE(table<std::array<int, 1>, int>({
{{-2}, 1},
{{-1}, 1},
{{0}, 1},
{{1}, 2},
{{2}, 1},
{{11}, 1},
}));

CAPTURE(test_input);
CHECK(test_input.size() == 1);

REQUIRE(lowest_missing(test_input) == expected_output);
}

SECTION("Misc") {
REQUIRE(lowest_missing({1, 2, 3, 4, 5, 6, 7, 8, 9}) == 10);
REQUIRE(lowest_missing({9, 8, 7, 6, 5, 4, 3, 2, 1}) == 10);
REQUIRE(lowest_missing({1, 2, 3, 4, 5, 4, 3, 2, 1}) == 6);
REQUIRE(lowest_missing({9, 7, 5, 4, 3, 2, 1}) == 6);
REQUIRE(lowest_missing({8, 20, 10, 5, 4, 3, 2, 1}) == 6);
REQUIRE(lowest_missing({7, 11, 6, 6, -1, 4, 1, 2}) == 3);
SECTION("Two numbers") {
auto [test_input, expected_output]
= GENERATE(table<std::vector<int>, int>({
{{-2, -2}, 1},
{{-1, -2}, 1},
{{0, -2}, 1},
{{0, 0}, 1},
{{-1, 0}, 1},
{{0, 1}, 2},
{{1, 0}, 2},
{{1, 2}, 3},
{{2, 1}, 3},
{{2, 2}, 1},
}));

CAPTURE(test_input);
CHECK(test_input.size() == 2);

REQUIRE(lowest_missing(test_input) == expected_output);
}

SECTION("Test cases copied from Simon Toth)") {
REQUIRE(lowest_missing({9, 8, 7, 4, 3, 2, 1}) == 5);
REQUIRE(lowest_missing({1, 1}) == 2);
SECTION("Three numbers") {
auto [test_input, expected_output]
= GENERATE(table<std::vector<int>, int>({
{{-1, -1, -1}, 1},
{{-1, 0, 0}, 1},
{{0, 0, 0}, 1},
{{0, 0, -1}, 1},
{{0, 1, 2}, 3},
{{2, 1, 0}, 3},
{{11, 2, 1}, 3},
{{5, 8, 17}, 1},
{{1, 1, 1}, 2},
{{3, 3, 3}, 1},
{{-8, -1, -3}, 1},
}));

CAPTURE(test_input);
CHECK(test_input.size() == 3);

REQUIRE(lowest_missing(test_input) == expected_output);
}

SECTION("Test cases copied from LeetCode") {
REQUIRE(lowest_missing({1, 2, 0}) == 3);
REQUIRE(lowest_missing({3, 4, -1, 1}) == 2);
REQUIRE(lowest_missing({7, 8, 9, 11, 12}) == 1);
SECTION("Ten numbers") {
auto [test_input, expected_output]
= GENERATE(table<std::vector<int>, int>({
{{-1, -1, -1, -1, -1, -1, -1, -1, -1, 10}, 1},
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1},
{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 2},
{{6, 6, 6, 6, 1, 6, 6, 2, 3, 4}, 5},
{{1, 2, 3, 4, 5, 6, 7, 8, 9, 9}, 10},
{{9, 8, 7, 6, 5, 4, 3, 3, 2, 1}, 10},
{{1, 2, 3, 4, 5, 5, 4, 3, 2, 1}, 6},
{{9, 7, 5, 4, 3, 2, 1, 1, 1, 0}, 6},
{{8, 20, 10, 6, 4, 3, 2, 1, -1, 0}, 5},
{{7, 11, 6, 6, -1, 4, 1, 2, 7, 2}, 3},
}));

CAPTURE(test_input);
CHECK(test_input.size() == 10);

REQUIRE(lowest_missing(test_input) == expected_output);
}
}

0 comments on commit d708d90

Please sign in to comment.