-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #114 from tcbrindle/pr/top10_examples
Add "Top 10 Algorithms" examples
- Loading branch information
Showing
12 changed files
with
478 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* Given n non-negative integers representing an elevation map where the width | ||
* of each bar is 1, compute how much water it can trap after raining. | ||
* | ||
* https://leetcode.com/problems/trapping-rain-water/ | ||
* | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <algorithm> | ||
|
||
auto const rain_water = [](std::initializer_list<int> heights) | ||
{ | ||
// Find the index of the maximum height | ||
flux::cursor auto max_idx = flux::find_max(heights); | ||
|
||
// Split the input sequence into two at the max position | ||
auto left = flux::slice(heights, flux::first(heights), max_idx); | ||
auto right = flux::slice(heights, max_idx, flux::last(heights)); | ||
|
||
// To calculate the trapped rain water for each half, we sum up the | ||
// difference between each element and the maximum seen up to that point | ||
auto trapped = [](flux::sequence auto seq) { | ||
return flux::zip(flux::scan(seq, flux::cmp::max), seq) | ||
.map(flux::unpack(std::minus{})) | ||
.sum(); | ||
}; | ||
|
||
// The final answer is the total of the trapped rain water reading | ||
// left-to-right for the left half, and right-to-left for the right half | ||
return trapped(left) + trapped(flux::reverse(right)); | ||
}; | ||
|
||
static_assert(rain_water({0,1,0,2,1,0,1,3,2,1,2,1}) == 6); | ||
static_assert(rain_water({4,2,0,3,2,5}) == 9); | ||
|
||
int main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* Given a binary array nums, return the maximum number of consecutive 1's in the array. | ||
* | ||
* https://leetcode.com/problems/max-consecutive-ones/ | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
namespace version1 { | ||
|
||
auto const mco = [](std::initializer_list<int> nums) | ||
{ | ||
return flux::ref(nums) | ||
.chunk_by(std::equal_to{}) | ||
.map(flux::sum) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
static_assert(mco({1,1,0,1,1,1}) == 3); | ||
static_assert(mco({1,0,1,1,0,1}) == 2); | ||
|
||
} | ||
|
||
namespace version2 { | ||
|
||
auto const mco = [](std::initializer_list<int> nums) | ||
{ | ||
return flux::ref(nums) | ||
.scan([](int count, int i) { return i * (count + i); }) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
static_assert(mco({1,1,0,1,1,1}) == 3); | ||
static_assert(mco({1,0,1,1,0,1}) == 2); | ||
|
||
} | ||
|
||
int main() {} |
29 changes: 29 additions & 0 deletions
29
example/top10/03_longest_continuous_increasing_subsequence.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* Given an unsorted array of integers nums, return the length of the longest | ||
* continuous increasing subsequence (i.e. subarray). The subsequence must be | ||
* strictly increasing. | ||
* | ||
* https://leetcode.com/problems/longest-continuous-increasing-subsequence/ | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
auto const lcis = [](std::initializer_list<int> nums) | ||
{ | ||
return flux::ref(nums) | ||
.chunk_by(std::less{}) | ||
.map(flux::count) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
static_assert(lcis({}) == 0); | ||
static_assert(lcis({1, 3, 5, 4, 7}) == 3); // [1, 3, 5] | ||
static_assert(lcis({2, 2, 2, 2, 2}) == 1); // [2] (must be strictly increasing) | ||
|
||
int main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* Given an integer array nums, find the subarray with the largest sum, and | ||
* return its sum. | ||
* | ||
* https://leetcode.com/problems/maximum-subarray/ | ||
* | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
auto const kadanes = [](std::initializer_list<int> nums) | ||
{ | ||
return flux::ref(nums) | ||
.scan([](int sum, int i) { return std::max(i, sum + i); }) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
static_assert(kadanes({-2, 1, -3, 4, -1, 2, 1, -5, 4}) == 6); | ||
static_assert(kadanes({1}) == 1); | ||
static_assert(kadanes({5, 4, -1, 7, 8}) == 23); | ||
|
||
int main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* https://codeforces.com/contest/1138/problem/A | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
auto const sushi_for_two = [](std::initializer_list<int> sushi) | ||
{ | ||
return 2 * flux::ref(sushi) | ||
.chunk_by(std::equal_to{}) | ||
.map(flux::count) | ||
.pairwise_map(flux::cmp::min) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
static_assert(sushi_for_two({}) == 0); | ||
static_assert(sushi_for_two({2, 2, 2, 1, 1, 2, 2}) == 4); | ||
static_assert(sushi_for_two({1, 2, 1, 2, 1, 2}) == 2); | ||
static_assert(sushi_for_two({2, 2, 1, 1, 1, 2, 2, 2, 2}) == 6); | ||
|
||
int main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* https://leetcode.com/problems/maximum-gap/ | ||
* | ||
* Note that the original problem specifies that the solution should have O(N) | ||
* runtime and use O(N) extra space. We instead use an O(NlogN) solution as | ||
* discussed on ADSP episode 115 (https://adspthepodcast.com/2023/02/03/Episode-115.html) | ||
* The NlogN version still passes the time limit constraints on leetcode, however. | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <cassert> | ||
|
||
namespace { | ||
|
||
// std::abs is not constexpr in C++20 | ||
auto const abs = [](std::signed_integral auto i) { return i < 0 ? -i : i; }; | ||
|
||
auto const max_gap = [](std::vector<int> nums) | ||
{ | ||
flux::sort(nums); | ||
return flux::ref(nums) | ||
.pairwise_map([](int a, int b) { return abs(a - b); }) | ||
.max() | ||
.value_or(0); | ||
}; | ||
|
||
} | ||
|
||
int main() | ||
{ | ||
assert(max_gap({3, 6, 9, 1}) == 3); | ||
assert(max_gap({10}) == 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
/* | ||
* https://theweeklychallenge.org/blog/perl-weekly-challenge-198/ | ||
* | ||
* Also discussed on ADSP episode 116 (https://adspthepodcast.com/2023/02/03/Episode-116.html) | ||
*/ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <cassert> | ||
|
||
// GCC 11 doesn't support constexpr std::vector | ||
#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 12 | ||
#define COMPILER_IS_GCC11 | ||
#endif | ||
|
||
// std::abs is not constexpr in C++20 | ||
auto const c_abs = [](std::signed_integral auto i) { return i < 0 ? -i : i; }; | ||
|
||
namespace version1 { | ||
|
||
// Sort + two passes | ||
auto const max_gap_count = [](std::vector<int> nums) | ||
{ | ||
flux::sort(nums); | ||
|
||
auto diffs = flux::ref(nums).pairwise_map([](int a, int b) { return c_abs(a - b); }); | ||
|
||
return diffs.count_eq(diffs.max().value_or(0)); | ||
}; | ||
|
||
#ifndef COMPILER_IS_GCC11 | ||
static_assert(max_gap_count({2, 5, 8, 1}) == 2); | ||
static_assert(max_gap_count({3, 6, 9, 1}) == 2); | ||
static_assert(max_gap_count({10}) == 0); | ||
#endif | ||
|
||
} | ||
|
||
namespace version2 { | ||
|
||
// Sort + one pass | ||
auto const max_gap_count = [](std::vector<int> nums) | ||
{ | ||
struct max_count { | ||
int value; | ||
int count; | ||
}; | ||
|
||
flux::sort(nums); | ||
return flux::ref(nums) | ||
.pairwise_map([](int a, int b) { return c_abs(a - b); }) | ||
.fold([](max_count max, int i) { | ||
if (i > max.value) { | ||
max = max_count{i, 1}; | ||
} else if (i == max.value ){ | ||
++max.count; | ||
} | ||
return max; | ||
}, max_count{}) | ||
.count; | ||
}; | ||
|
||
#ifndef COMPILER_IS_GCC11 | ||
static_assert(max_gap_count({2, 5, 8, 1}) == 2); | ||
static_assert(max_gap_count({3, 6, 9, 1}) == 2); | ||
static_assert(max_gap_count({10}) == 0); | ||
#endif | ||
|
||
} | ||
|
||
int main() | ||
{ | ||
{ | ||
using namespace version1; | ||
assert(max_gap_count({2, 5, 8, 1}) == 2); | ||
assert(max_gap_count({3, 6, 9, 1}) == 2); | ||
assert(max_gap_count({10}) == 0); | ||
} | ||
|
||
{ | ||
using namespace version2; | ||
assert(max_gap_count({2, 5, 8, 1}) == 2); | ||
assert(max_gap_count({3, 6, 9, 1}) == 2); | ||
assert(max_gap_count({10}) == 0); | ||
} | ||
} |
Oops, something went wrong.