diff --git a/README.rst b/README.rst index b2f1ec28..af4c1b47 100644 --- a/README.rst +++ b/README.rst @@ -69,7 +69,7 @@ Olivia's Project Euler Solutions | | C11+ in: |msvc| [1]_ | | |CodeQL| |br| | | | |br| Browser [2]_ | | |C-lint| | +------------+----------------------------+--------+-------------------+ - | C++ | C++98+ in: |br| |clang|, & | 19 | |Cpi| |br| | + | C++ | C++98+ in: |br| |clang|, & | 20 | |Cpi| |br| | | | |gcc| |br| | | |Cp-Cov| |br| | | | C++14+ in: |msvc| [1]_ | | |CodeQL| |br| | | | |br| Browser [3]_ | | |Cp-lint| | diff --git a/cplusplus/README.rst b/cplusplus/README.rst index 7776f70d..e8df89d8 100644 --- a/cplusplus/README.rst +++ b/cplusplus/README.rst @@ -167,6 +167,7 @@ Problems Solved - ☒ `1 <./src/p0001.cpp>`__ - ☒ `2 <./src/p0002.cpp>`__ +- ☒ `3 <./src/p0003.cpp>`__ - ☒ `4 <./src/p0004.cpp>`__ - ☒ `6 <./src/p0006.cpp>`__ - ☒ `7 <./src/p0007.cpp>`__ diff --git a/cplusplus/src/include/primes.hpp b/cplusplus/src/include/primes.hpp index 30108f97..bb5bb0a2 100644 --- a/cplusplus/src/include/primes.hpp +++ b/cplusplus/src/include/primes.hpp @@ -4,6 +4,7 @@ #include #include #include +#include template class PrimeGenerator { @@ -17,7 +18,7 @@ class PrimeGenerator { T next() { if (has_limit && prime >= limit) { sieve.clear(); - return T(-1); + throw new std::runtime_error("Tried to exceed given limit (or limit of data type)."); } prime = next_prime(candidate); candidate = prime + T(1); @@ -71,3 +72,40 @@ template PrimeGenerator primes_until(T x) { return PrimeGenerator(x); } + +template +class PrimeFactors { +public: + PrimeFactors(T target) + : target(target), last_prime(T(std::numeric_limits::max())), prime_gen(primes()) {} + + T next() { + if (!has_next()) + throw new std::runtime_error("No more factors available."); + if (std::numeric_limits::min() < 0 && target < 0) { + target = -target; + return T(-1); + } + while (true) { + if (target % last_prime == 0) { + target /= last_prime; + return last_prime; + } + last_prime = prime_gen.next(); + } + } + + bool has_next() const { + return target != 1 && target != 0; + } + +private: + T target; + T last_prime; + PrimeGenerator prime_gen; +}; + +template +PrimeFactors prime_factors(T target) { + return PrimeFactors(target); +} diff --git a/cplusplus/src/p0003.cpp b/cplusplus/src/p0003.cpp new file mode 100644 index 00000000..457dc53f --- /dev/null +++ b/cplusplus/src/p0003.cpp @@ -0,0 +1,30 @@ +/* +Project Euler Problem 3 + +More lazy functions this time. + +Problem: + +The prime factors of 13195 are 5, 7, 13 and 29. + +What is the largest prime factor of the number 600851475143 ? +*/ + +#ifndef EULER_P0003 +#define EULER_P0003 +#include +#include +#include "include/macros.hpp" +#include "include/primes.hpp" + +uint16_t EMSCRIPTEN_KEEPALIVE p0003() { + uint16_t answer = 0; + PrimeFactors pfs = prime_factors(600851475143); + while (pfs.has_next()) + answer = (uint16_t) pfs.next(); + return answer; +} + + +PROGRAM_TAIL(p0003) +#endif diff --git a/cplusplus/test.cpp b/cplusplus/test.cpp index cf83aed5..9d176bd8 100644 --- a/cplusplus/test.cpp +++ b/cplusplus/test.cpp @@ -5,7 +5,7 @@ #include #include "src/p0001.cpp" #include "src/p0002.cpp" -// #include "src/p0003.cpp" +#include "src/p0003.cpp" #include "src/p0004.cpp" // #include "src/p0005.cpp" #include "src/p0006.cpp" @@ -37,7 +37,7 @@ typedef struct { ProblemRef answers[] = { { 1, (void *(*)())p0001 }, { 2, (void *(*)())p0002 }, - // { 3, (void *(*)())p0003 }, + { 3, (void *(*)())p0003 }, { 4, (void *(*)())p0004 }, // { 5, (void *(*)())p0005 }, { 6, (void *(*)())p0006 }, diff --git a/cplusplus/test_euler.py b/cplusplus/test_euler.py index 9880db9e..bb82c982 100644 --- a/cplusplus/test_euler.py +++ b/cplusplus/test_euler.py @@ -22,9 +22,7 @@ answers = { x: get_answer(x) for x in ( - 1, - 2, - 4, + *range(1, 5), *range(6, 10), 11, *range(13, 18), diff --git a/docs/index.rst b/docs/index.rst index 4ca13236..a5a0a6e7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -80,7 +80,7 @@ Problems Solved +-----------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`002`|:c-d:`0002` |:cp-d:`0002`|:cs-d:`0002`|:ja-d:`0002`|:js-d:`0002`|:py-d:`0002`|:rs-d:`0002`| +-----------+------------+------------+------------+------------+------------+------------+------------+ - |:prob:`003`|:c-d:`0003` | |:cs-d:`0003`| |:js-d:`0003`|:py-d:`0003`|:rs-d:`0003`| + |:prob:`003`|:c-d:`0003` |:cp-d:`0003`|:cs-d:`0003`| |:js-d:`0003`|:py-d:`0003`|:rs-d:`0003`| +-----------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`004`|:c-d:`0004` |:cp-d:`0004`|:cs-d:`0004`|:ja-d:`0004`|:js-d:`0004`|:py-d:`0004`|:rs-d:`0004`| +-----------+------------+------------+------------+------------+------------+------------+------------+ diff --git a/docs/src/cplusplus/lib/primes.rst b/docs/src/cplusplus/lib/primes.rst index 70624e01..887b3a54 100644 --- a/docs/src/cplusplus/lib/primes.rst +++ b/docs/src/cplusplus/lib/primes.rst @@ -10,9 +10,10 @@ Includes - :external:cpp:type:`vector` - :external:cpp:type:`map` - :external:cpp:type:`limits` +- :external:cpp:type:`stdexcept` .. cpp:namespace-push:: primes - + .. cpp:class:: PrimeGenerator .. cpp:function:: PrimeGenerator PrimeGenerator() @@ -26,9 +27,24 @@ Includes These constructors will return a finite generator of prime numbers, going to ``upper_limit``. - .. cpp:function:: bool next() + .. cpp:function:: T next() + + Returns the next prime, or ``0`` if it is above the defined limit. + + .. cpp:function:: bool has_next() + + Returns ``true`` if there is a next value to generate. + +.. cpp:class:: PrimeFactors + + .. cpp:function:: PrimeFactors PrimeFactors(T upper_limit) + .. cpp:function:: PrimeFactors prime_factors(T upper_limit) + + These constructors will return a finite generator of prime factors of ``target``. + + .. cpp:function:: T next() - Returns the next prime, or ``-1`` if it is above the defined limit. + Returns the next prime factor, or ``0`` if it is above the defined limit. .. cpp:function:: bool has_next() diff --git a/docs/src/cplusplus/p0003.rst b/docs/src/cplusplus/p0003.rst new file mode 100644 index 00000000..2b51ab56 --- /dev/null +++ b/docs/src/cplusplus/p0003.rst @@ -0,0 +1,30 @@ +C++ Implementation of Problem 3 +=============================== + +View source code :source:`cplusplus/src/p0003.cpp` + +Includes +-------- + +- `"primes.hpp" <./lib/primes.html>`__ +- :external:c:type:`stdint` +- :external:cpp:type:`iostream` + +Solution +-------- + +.. cpp:namespace-push:: p0003 + +.. cpp:function:: uint16_t p0003() + +.. cpp:function:: int main(int argc, char const *argv[]) + + .. note:: + + This function is only present in the Python test runner, or when compiling as a standalone program. + +.. literalinclude:: ../../../cplusplus/src/p0003.cpp + :language: C++ + :linenos: + +.. tags:: fibonacci-number, divisibility