Skip to content

Commit 666c35e

Browse files
committed
Added factorial.
1 parent 522eec3 commit 666c35e

File tree

6 files changed

+244
-0
lines changed

6 files changed

+244
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ SET(COMPONENTS
9898
power
9999
division
100100
root
101+
factorial
101102
)
102103
# NEW_COMPONENT: PATCH Do NOT remove the previous comment.
103104

include/fn/basicArithm.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,16 @@ namespace steppable::__internals::arithmetic
212212
*/
213213
std::string rootIntPart(const std::string& _number, const std::string& base);
214214

215+
/**
216+
* @brief Calculates the factorial of a number.
217+
*
218+
* @param _number The number to calculate the factorial of.
219+
* @param steps The number of steps to calculate the factorial.
220+
*
221+
* @return The factorial of the number.
222+
*/
223+
std::string factorial(const std::string& _number, int steps = 2);
224+
215225
/**
216226
* @brief Executes a given predicate function a specified number of times.
217227
*

src/factorial/factorial.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/**************************************************************************************************
2+
* Copyright (c) 2023-2024 NWSOFT *
3+
* *
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy *
5+
* of this software and associated documentation files (the "Software"), to deal *
6+
* in the Software without restriction, including without limitation the rights *
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8+
* copies of the Software, and to permit persons to whom the Software is *
9+
* furnished to do so, subject to the following conditions: *
10+
* *
11+
* The above copyright notice and this permission notice shall be included in all *
12+
* copies or substantial portions of the Software. *
13+
* *
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20+
* SOFTWARE. *
21+
**************************************************************************************************/
22+
23+
/**
24+
* @file add.cpp
25+
* @brief This file contains the implementation of the add function, which add two number strings together.
26+
*
27+
* @author Andy Zhang
28+
* @date 9th October 2023
29+
*/
30+
31+
#include "argParse.hpp"
32+
#include "factorialReport.hpp"
33+
#include "fn/basicArithm.hpp"
34+
#include "output.hpp"
35+
#include "util.hpp"
36+
37+
#include <algorithm>
38+
#include <iostream>
39+
#include <string_view>
40+
#include <vector>
41+
42+
using namespace steppable::__internals::numUtils;
43+
using namespace steppable::__internals::utils;
44+
using namespace steppable::__internals::arithmetic;
45+
using namespace steppable::__internals::symbols;
46+
using namespace steppable::output;
47+
using namespace std::literals;
48+
49+
namespace steppable::__internals::arithmetic
50+
{
51+
std::string factorial(const std::string& _number, const int steps)
52+
{
53+
auto number = standardizeNumber(_number);
54+
if (not isInteger(number))
55+
{
56+
// We cannot evaluate integrals yet, so this has to be returned.
57+
// Correct implementation of the gamma function should be
58+
// / +inf
59+
// | z-1 -s
60+
// G(z) = | s e ds ,where z is a non-zero decimal ............ (1)
61+
// |
62+
// / 0
63+
// and factorial is defined as
64+
// n! = n * G(n) ,where n is a non-zero decimal ............ (2)
65+
error("factorial"s, "%s is not an integer."s, number.c_str());
66+
return "0";
67+
}
68+
if (isZeroString(number))
69+
{
70+
if (steps == 2)
71+
return "By definition, 0! = 1";
72+
return "1"; // By definition, 0! = 1
73+
}
74+
// Negative numbers do not have a factorial.
75+
if (number.front() == '-')
76+
{
77+
error("factorial"s, "%s is negative."s, number.c_str());
78+
return "0";
79+
}
80+
81+
// Calculate the factorial of the number
82+
std::string result = "1";
83+
loop(_number, [&](const std::string& i) { result = multiply(result, add(i, "1", 0), 0); });
84+
85+
return reportFactorial(_number, result, steps);
86+
}
87+
} // namespace steppable::__internals::arithmetic
88+
89+
#ifndef NO_MAIN
90+
int main(const int _argc, const char* _argv[])
91+
{
92+
Utf8CodePage _;
93+
ProgramArgs program(_argc, _argv);
94+
program.addPosArg('a', "Number");
95+
program.addKeywordArg("steps", 2, "Amount of steps while calculating the factorial. 0 = No steps, 2 = All steps.");
96+
program.addSwitch("profile", false, "profiling the program");
97+
program.parseArgs();
98+
99+
const int steps = program.getKeywordArgument("steps");
100+
const bool profile = program.getSwitch("profile");
101+
const auto& number = static_cast<std::string>(program.getPosArg(0));
102+
103+
if (profile)
104+
{
105+
TIC(Factorial)
106+
std::cout << "Factorial :\n" << factorial(number, steps) << '\n';
107+
TOC()
108+
}
109+
else
110+
std::cout << factorial(number, steps) << '\n';
111+
}
112+
#endif

src/factorial/factorialReport.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**************************************************************************************************
2+
* Copyright (c) 2023-2024 NWSOFT *
3+
* *
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy *
5+
* of this software and associated documentation files (the "Software"), to deal *
6+
* in the Software without restriction, including without limitation the rights *
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8+
* copies of the Software, and to permit persons to whom the Software is *
9+
* furnished to do so, subject to the following conditions: *
10+
* *
11+
* The above copyright notice and this permission notice shall be included in all *
12+
* copies or substantial portions of the Software. *
13+
* *
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20+
* SOFTWARE. *
21+
**************************************************************************************************/
22+
23+
#include "factorialReport.hpp"
24+
25+
#include "fn/basicArithm.hpp"
26+
#include "symbols.hpp"
27+
28+
#include <sstream>
29+
#include <string>
30+
31+
using namespace steppable::__internals::arithmetic;
32+
using namespace steppable::__internals::symbols;
33+
34+
std::string reportFactorial(const std::string& number, const std::string& result, int steps)
35+
{
36+
if (steps == 0)
37+
return result;
38+
39+
// In this case, steps == 2 is equivalent to steps == 1.
40+
std::stringstream ss;
41+
loop(number, [&](const auto& item) { ss << add(item, "1", 0) << " " << MULTIPLY << " "; });
42+
auto out = ss.str();
43+
44+
out.erase(out.end() - 3, out.end()); // Remove the last " * "
45+
out += " = " + result;
46+
47+
return out;
48+
}

src/factorial/factorialReport.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**************************************************************************************************
2+
* Copyright (c) 2023-2024 NWSOFT *
3+
* *
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy *
5+
* of this software and associated documentation files (the "Software"), to deal *
6+
* in the Software without restriction, including without limitation the rights *
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8+
* copies of the Software, and to permit persons to whom the Software is *
9+
* furnished to do so, subject to the following conditions: *
10+
* *
11+
* The above copyright notice and this permission notice shall be included in all *
12+
* copies or substantial portions of the Software. *
13+
* *
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20+
* SOFTWARE. *
21+
**************************************************************************************************/
22+
23+
#pragma once
24+
25+
#include <string>
26+
27+
/**
28+
* @brief Report the factorial calculation.
29+
*
30+
* @param number The number to calculate the factorial of.
31+
* @param result The result of the factorial calculation.
32+
* @param steps The number of steps taken to calculate the factorial.
33+
* @return std::string The report of the factorial calculation.
34+
*/
35+
std::string reportFactorial(const std::string& number, const std::string& result, int steps);

tests/testFactorial.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**************************************************************************************************
2+
* Copyright (c) 2023-2024 NWSOFT *
3+
* *
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy *
5+
* of this software and associated documentation files (the "Software"), to deal *
6+
* in the Software without restriction, including without limitation the rights *
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8+
* copies of the Software, and to permit persons to whom the Software is *
9+
* furnished to do so, subject to the following conditions: *
10+
* *
11+
* The above copyright notice and this permission notice shall be included in all *
12+
* copies or substantial portions of the Software. *
13+
* *
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20+
* SOFTWARE. *
21+
**************************************************************************************************/
22+
23+
#include "colors.hpp"
24+
#include "fn/basicArithm.hpp"
25+
#include "output.hpp"
26+
#include "testing.hpp"
27+
#include "util.hpp"
28+
29+
#include <iomanip>
30+
#include <iostream>
31+
32+
using namespace steppable::__internals::arithmetic;
33+
34+
TEST_START()
35+
SECTION(Factorial)
36+
_.assertIsEqual(factorial("5", 0), "120");
37+
SECTION_END()
38+
TEST_END()

0 commit comments

Comments
 (0)