cpp: add «2709. Greatest Common Divisor Traversal»
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
5a9d218bcb
commit
c446face87
1 changed files with 158 additions and 0 deletions
158
cpp/greatest-common-divisor-traversal.cpp
Normal file
158
cpp/greatest-common-divisor-traversal.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
struct factors_iterator {
|
||||
factors_iterator() : f(-1) {}
|
||||
factors_iterator(int f, int n) : f(f), n(n), upper(std::sqrt(n)) {}
|
||||
|
||||
auto operator!=(const factors_iterator &other) const -> bool {
|
||||
return f != other.f;
|
||||
}
|
||||
|
||||
auto operator*() const -> int { return f; }
|
||||
|
||||
auto operator++() -> factors_iterator & {
|
||||
// ‹f› yielded a prime
|
||||
if (f > upper || n == 1) {
|
||||
f = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
do {
|
||||
++f;
|
||||
} while (f <= upper && n % f != 0);
|
||||
|
||||
// ‹n› is a prime
|
||||
if (f > upper) {
|
||||
f = n;
|
||||
}
|
||||
|
||||
while (n % f == 0) {
|
||||
n /= f;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
int f;
|
||||
int n;
|
||||
int upper;
|
||||
};
|
||||
|
||||
struct factors {
|
||||
factors(int n) : n(n) {}
|
||||
auto begin() const -> factors_iterator { return ++factors_iterator(1, n); }
|
||||
auto end() const -> factors_iterator { return factors_iterator(); }
|
||||
|
||||
private:
|
||||
int n;
|
||||
};
|
||||
|
||||
void dfs(std::unordered_map<int, std::vector<int>> &graph,
|
||||
std::vector<bool> &visited, int u) {
|
||||
visited[u] = true;
|
||||
for (auto v : graph[u]) {
|
||||
if (!visited[v]) {
|
||||
dfs(graph, visited, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
bool canTraverseAllPairs(const std::vector<int> &nums) {
|
||||
auto n = nums.size();
|
||||
|
||||
std::unordered_map<int, int> gcd;
|
||||
std::unordered_map<int, std::vector<int>> neighbors;
|
||||
|
||||
for (auto i = 0u; i < n; ++i) {
|
||||
for (auto f : factors(nums[i])) {
|
||||
if (gcd.contains(f)) {
|
||||
int u = i;
|
||||
int v = gcd[f];
|
||||
neighbors[u].push_back(v);
|
||||
neighbors[v].push_back(u);
|
||||
}
|
||||
|
||||
gcd[f] = i;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bool> visited(n, false);
|
||||
dfs(neighbors, visited, 0);
|
||||
|
||||
return std::find(visited.begin(), visited.end(), false) ==
|
||||
visited.end();
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _MF_TEST
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(examples, no_1) {
|
||||
Solution s;
|
||||
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{2, 3, 6}));
|
||||
}
|
||||
TEST(examples, no_2) {
|
||||
Solution s;
|
||||
EXPECT_FALSE(s.canTraverseAllPairs(std::vector{3, 9, 5}));
|
||||
}
|
||||
TEST(examples, no_3) {
|
||||
Solution s;
|
||||
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{4, 3, 12, 8}));
|
||||
}
|
||||
|
||||
TEST(factors, prime_2) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(2)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, std::vector{2});
|
||||
}
|
||||
TEST(factors, prime_7) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(7)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, std::vector{7});
|
||||
}
|
||||
TEST(factors, prime_29) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(29)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, std::vector{29});
|
||||
}
|
||||
TEST(factors, composite_6) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(6)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, (std::vector{2, 3}));
|
||||
}
|
||||
TEST(factors, composite_15) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(15)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, (std::vector{3, 5}));
|
||||
}
|
||||
TEST(factors, composite_1024) {
|
||||
std::vector<int> fs;
|
||||
for (auto f : factors(1024)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
EXPECT_EQ(fs, std::vector{2});
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue