Greedy algorithm for Egyptian fractions: Difference between revisions
Content added Content deleted
(Added Wren) |
m (C++ code modified to use a fraction type) |
||
Line 460: | Line 460: | ||
The C++ standard library does not have a "big integer" type, so this solution uses the Boost library. |
The C++ standard library does not have a "big integer" type, so this solution uses the Boost library. |
||
<lang cpp>#include <iostream> |
<lang cpp>#include <iostream> |
||
#include <optional> |
|||
#include <vector> |
#include <vector> |
||
#include <string> |
#include <string> |
||
Line 466: | Line 467: | ||
typedef boost::multiprecision::cpp_int integer; |
typedef boost::multiprecision::cpp_int integer; |
||
struct fraction { |
|||
fraction(const integer& n, const integer& d) : numerator(n), denominator(d) {} |
|||
integer numerator; |
|||
integer denominator; |
|||
}; |
|||
integer mod(const integer& x, const integer& y) { |
integer mod(const integer& x, const integer& y) { |
||
Line 477: | Line 484: | ||
} |
} |
||
std::string |
std::string to_string(const integer& i) { |
||
const int max_digits = 20; |
const int max_digits = 20; |
||
std::ostringstream os; |
std::ostringstream os; |
||
Line 488: | Line 495: | ||
} |
} |
||
std::ostream& operator<<(std::ostream& out, const fraction& f) { |
|||
⚫ | |||
return out << to_string(f.numerator) << '/' << to_string(f.denominator); |
|||
} |
|||
⚫ | |||
result.clear(); |
result.clear(); |
||
integer x = f.numerator, y = f.denominator; |
|||
while (x > 0) { |
while (x > 0) { |
||
integer z = (y + x - 1)/x; |
integer z = (y + x - 1)/x; |
||
result. |
result.emplace_back(1, z); |
||
x = mod(-y, x); |
x = mod(-y, x); |
||
y = y * z; |
y = y * z; |
||
Line 498: | Line 510: | ||
} |
} |
||
void print_egyptian(const std::vector< |
void print_egyptian(const std::vector<fraction>& result) { |
||
if (result.empty()) |
if (result.empty()) |
||
return; |
return; |
||
auto i = result.begin(); |
auto i = result.begin(); |
||
std::cout << |
std::cout << *i++; |
||
for (; i != result.end(); ++i) |
for (; i != result.end(); ++i) |
||
std::cout << " + |
std::cout << " + " << *i; |
||
std::cout << |
std::cout << '\n'; |
||
} |
} |
||
void print_egyptian( |
void print_egyptian(const fraction& f) { |
||
std::cout << "Egyptian fraction for " << |
std::cout << "Egyptian fraction for " << f << ": "; |
||
integer x = f.numerator, y = f.denominator; |
|||
if (x > y) { |
if (x > y) { |
||
std::cout << "[" << x/y << "] "; |
std::cout << "[" << x/y << "] "; |
||
x = x % y; |
x = x % y; |
||
} |
} |
||
std::vector< |
std::vector<fraction> result; |
||
egyptian(x, y, result); |
egyptian(fraction(x, y), result); |
||
print_egyptian(result); |
print_egyptian(result); |
||
std::cout << '\n'; |
|||
} |
} |
||
void show_max_terms_and_max_denominator(const integer& limit) { |
void show_max_terms_and_max_denominator(const integer& limit) { |
||
size_t max_terms = 0; |
size_t max_terms = 0; |
||
std::optional<fraction> max_terms_fraction, max_denominator_fraction; |
|||
integer max_terms_numerator, max_terms_denominator; |
|||
⚫ | |||
integer max_denominator_numerator, max_denominator_denominator; |
|||
⚫ | |||
integer max_denominator = 0; |
integer max_denominator = 0; |
||
std::vector< |
std::vector<fraction> max_denominator_result; |
||
std::vector< |
std::vector<fraction> result; |
||
for (integer b = 2; b < limit; ++b) { |
for (integer b = 2; b < limit; ++b) { |
||
for (integer a = 1; a < b; ++a) { |
for (integer a = 1; a < b; ++a) { |
||
fraction f(a, b); |
|||
egyptian(f, result); |
|||
if (result.size() > max_terms) { |
if (result.size() > max_terms) { |
||
max_terms = result.size(); |
max_terms = result.size(); |
||
max_terms_result = result; |
max_terms_result = result; |
||
max_terms_fraction = f; |
|||
max_terms_denominator = b; |
|||
} |
} |
||
integer |
const integer& denominator = result.back().denominator; |
||
if ( |
if (denominator > max_denominator) { |
||
max_denominator = |
max_denominator = denominator; |
||
max_denominator_result = result; |
max_denominator_result = result; |
||
max_denominator_fraction = f; |
|||
max_denominator_denominator = b; |
|||
} |
} |
||
} |
} |
||
} |
} |
||
std::cout << "Proper fractions with most terms and largest denominator, limit = " << limit << ":\n\n"; |
std::cout << "Proper fractions with most terms and largest denominator, limit = " << limit << ":\n\n"; |
||
std::cout << "Most terms (" << max_terms << "): " << |
std::cout << "Most terms (" << max_terms << "): " << max_terms_fraction.value() << " = "; |
||
<< '/' << max_terms_denominator << " = "; |
|||
print_egyptian(max_terms_result); |
print_egyptian(max_terms_result); |
||
std::cout << " |
std::cout << "\nLargest denominator (" << count_digits(max_denominator_result.back().denominator) |
||
<< |
<< " digits): " << max_denominator_fraction.value() << " = "; |
||
print_egyptian(max_denominator_result); |
print_egyptian(max_denominator_result); |
||
} |
} |
||
int main() { |
int main() { |
||
print_egyptian(43, 48); |
print_egyptian(fraction(43, 48)); |
||
print_egyptian(5, 121); |
print_egyptian(fraction(5, 121)); |
||
print_egyptian(2014, 59); |
print_egyptian(fraction(2014, 59)); |
||
show_max_terms_and_max_denominator(100); |
show_max_terms_and_max_denominator(100); |
||
show_max_terms_and_max_denominator(1000); |
show_max_terms_and_max_denominator(1000); |
||
Line 576: | Line 587: | ||
Largest denominator (150 digits): 8/97 = 1/13 + 1/181 + 1/38041 + 1/1736503177 + 1/3769304102927363485 + 1/1894353789...8154430149 + 1/5382864419...4225813153 + 1/5795045870...3909789665 |
Largest denominator (150 digits): 8/97 = 1/13 + 1/181 + 1/38041 + 1/1736503177 + 1/3769304102927363485 + 1/1894353789...8154430149 + 1/5382864419...4225813153 + 1/5795045870...3909789665 |
||
Proper fractions with most terms and largest denominator, limit = 1000: |
Proper fractions with most terms and largest denominator, limit = 1000: |
||
Line 582: | Line 592: | ||
Largest denominator (2847 digits): 36/457 = 1/13 + 1/541 + 1/321409 + 1/114781617793 + 1/1482167225...0844346913 + 1/2510651068...4290086881 + 1/7353930250...3326272641 + 1/6489634815...7391865217 + 1/5264420004...5476206145 + 1/3695215730...1238141889 + 1/2048192894...4706590593 + 1/8390188268...5525592705 |
Largest denominator (2847 digits): 36/457 = 1/13 + 1/541 + 1/321409 + 1/114781617793 + 1/1482167225...0844346913 + 1/2510651068...4290086881 + 1/7353930250...3326272641 + 1/6489634815...7391865217 + 1/5264420004...5476206145 + 1/3695215730...1238141889 + 1/2048192894...4706590593 + 1/8390188268...5525592705 |
||
</pre> |
</pre> |
||