From 56c5203f9f78c70a736b9c1b94ab0173b9c27b65 Mon Sep 17 00:00:00 2001 From: Olivia Appleton Date: Wed, 4 Sep 2024 22:39:38 -0500 Subject: [PATCH] Solve p3 in C++ --- README.rst | 2 +- cplusplus/README.rst | 1 + cplusplus/src/include/primes.hpp | 39 ++++++++++++++++++++++++++++++- cplusplus/src/p0003.cpp | 29 +++++++++++++++++++++++ cplusplus/test.cpp | 4 ++-- cplusplus/test_euler.py | 4 +--- docs/index.rst | 2 +- docs/src/cplusplus/lib/primes.rst | 21 ++++++++++++++--- docs/src/cplusplus/p0003.rst | 30 ++++++++++++++++++++++++ 9 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 cplusplus/src/p0003.cpp create mode 100644 docs/src/cplusplus/p0003.rst 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..5602287c 100644 --- a/cplusplus/src/include/primes.hpp +++ b/cplusplus/src/include/primes.hpp @@ -17,7 +17,7 @@ class PrimeGenerator { T next() { if (has_limit && prime >= limit) { sieve.clear(); - return T(-1); + return T(0); } prime = next_prime(candidate); candidate = prime + T(1); @@ -71,3 +71,40 @@ template PrimeGenerator primes_until(T x) { return PrimeGenerator(x); } + +template +class PrimeFactors { +public: + PrimeFactors(T target) + : target(target), primes(new PrimeGenerator()), last_prime(T(std::numeric_limits::max())) {} + + T next() { + if (!has_next()) + throw new Exception(); + if (std::numeric_limits::min() < 0 && target < 0) { + target = -target; + return T(-1); + } + while (true) { + if (target % last_prime == 0) { + target /= last_prime; + return target; + } + target = last_prime.next(); + } + } + + bool has_next() const { + return target != 1 && target != 0; + } + +private: + T target; + T last_prime; + PrimeGenerator primes; +}; + +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..2b95ddab --- /dev/null +++ b/cplusplus/src/p0003.cpp @@ -0,0 +1,29 @@ +/* +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" + +uint16_t EMSCRIPTEN_KEEPALIVE p0003() { + uint16_t answer = 0; + pfs = new PrimeFactors(600851475143); + while (pfs.has_next()) + answer = next(pfs); + 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..e5505305 100644 --- a/docs/src/cplusplus/lib/primes.rst +++ b/docs/src/cplusplus/lib/primes.rst @@ -12,7 +12,7 @@ Includes - :external:cpp:type:`limits` .. cpp:namespace-push:: primes - + .. cpp:class:: PrimeGenerator .. cpp:function:: PrimeGenerator PrimeGenerator() @@ -26,9 +26,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