I am trying to create a program that can take many numbers as I want in C++ language.
Then it find what operators can make the equation true and show all correct possible operation.
Example: If I put 3 5 15
Then it output 3x5 = 15
If I put 1 2 3 4 4
Then it outputs 1+2-3+4 =4
The following code is my written program:
The problem about it is that when I want to reduce the number of input or increase the number of input I need to add/reduce nested loops EVERYTIME. I want to know what is a more effective way of a more flexible nested loops or recursion method.
#include <iostream>
#include <cmath>
using namespace std;
char getOperator(int);
double operate(int, double, double);
int main() {
double a, b, c, d, e, result;
short noOfAnswers = 0;
cout << "Input first 5 numbers to make it equal to another 1 number.\n" <<
"I'll find what are the operators needed to make 2 sides of the equation equal.\n";
cin >> a >> b >> c >> d >> e >> result;
int noOfOperators = 5;
for (int i = 0; i <= noOfOperators; i++) {
double firstTwo = operate(i, a, b);
for (int j = 0; j <= noOfOperators; j++) {
double firstThree = operate(j, firstTwo, c);
for (int k = 0; k <= noOfOperators; k++) {
double firstFour = operate(k, firstThree, d);
for (int l = 0; l <= noOfOperators; l++) {
double firstFive = operate(l, firstFour, e);
if (firstFive == result) {
cout << ++noOfAnswers << ')' << a << getOperator(i) << b << getOperator(j) << c
<< getOperator(k) << d << getOperator(l) << e << '=' << result << endl;
}
}
}
}
}
if (noOfAnswers) cout << "I have found " << noOfAnswers << " solutions for this extremely hard problem for humanity \nin less than a second." << endl;
else cout << "I cannot find any solutions to this problem.\n"
<<"They're just a bunch of random numbers & That is UNSOLVABLE!" << endl;
cout << "Do not doubt my judgment. I am always right!" << endl << "(Please note that all calculations are done from the left side first.)" << endl;
return 0;
}
double operate(int iteration, double num1, double num2) {
switch (iteration) {
case 0: return num1+num2;
case 1: return num1-num2;
case 2: return num1*num2;
case 3: return num1/num2;
case 4: return pow(num1, num2);
case 5: return fmod(num1, num2);
}
return 0;
}
char getOperator(int pos) {
switch (pos) {
case 0: return '+';
case 1: return '-';
case 2: return 'x';
case 3: return '/';
case 4: return '^';
case 5: return '%';
}
return ' ';
}
You might want to use while() loops, cause you dont know when the loop terminates.
int main() {
double numbers[] = {3,5,15};//consider storing the number as an array
//the last element is the result
double result;
int arr_len = sizeof(numbers)/sizeof(double);
int i,j;
while(1)
{
j = 0;
while(j++ < 5)//over all operators
{i = 0;
result = numbers[0];//start with first element
while(i < arrlen - 2)//over all numbers, exclude the result
{
result = operate(j, result, numbers[++i]);
//something like this...this does not work correctly
//it might give you a hint in the right direction
if(result == numbers[arr_len - 1])//compare to last element
return 0;
}
}
}
return 0;
}
Following may help:
// increment v where each value is a digit with maximal value maxSize
// so {0,1,2}, 3 lead to {0,2,0}
// return false on overflow.
bool increment(std::vector<int>& v, int maxSize)
{
for (auto it = v.rbegin(); it != v.rend(); ++it) {
++*it;
if (*it != maxSize) {
return true;
}
*it = 0;
}
return false;
}
// display something like 1 + 2 * 3 = 9 // with the following meaning ((1 + 2) * 3) = 9
void display(const std::vector<double>& operands, const std::vector<int>& operators, double total)
{
const char operators_string[] = "+-*/^%";
std::cout << operands[0];
for (std::size_t i = 0; i != operators.size(); ++i) {
std::cout << " " << operators_string[operators[i]] << " " << operands[i + 1];
}
std::cout << " = " << total << std::endl;
}
// Compute something like {1 2 3 4}, {+ * /} as (((1 + 2) * 3) / 4)
double compute(const std::vector<double>& operands, const std::vector<int>& operators)
{
std::function<double(double, double)> fs[] = {
[](double a, double b) { return a + b; },
[](double a, double b) { return a - b; },
[](double a, double b) { return a * b; },
[](double a, double b) { return a / b; },
[](double a, double b) { return pow(a, b); },
[](double a, double b) { return fmod(a, b); },
};
double res = operands[0];
for (std::size_t i = 0; i != operators.size(); ++i) {
res = fs[operators[i]](res, operands[i + 1]);
}
return res;
}
void display_combinaison(const std::vector<double>& operands, double total)
{
std::vector<int> operators(operands.size() - 1);
do {
if (compute(operands, operators) == total) {
display(operands, operators, total);
}
} while (increment(operators, 6));
}
Live example
Related
So for my assignment I have to create a calculator that works with big integers up to 256 characters in length. The current part of the assignment I'm up to is getting it work with multiplication of larger numbers. DIGITS is the limit of digits per Bigint class, currently set to 20 for debug sake, but will go up to 256
When doing a calculation like 25 * 137, I get the answer 3285 when it should be 3425. When I look through the couts that I put in place for debug, the first iteration of the i loop works perfectly and adds 685 to sum which is 5 * 137, so that works perfect. However when it gets to the bit where it's having to do the second iteration of the i loop where it is 20 * 137, it's getting the answer wrong and I cannot work out why. I have an inkling that it's something to do with the carry being two digits (14), but I still can't really work out how I can fix it.
The main implementation that obviously has something wrong with it is in the * operator of the bigint class. I know it's not to do with the << or >> operators as they work perfectly for addition and subtraction.
Full code of the bigint class is below:
#include <iostream>
#include <string>
#include "Bigint.h"
#include <cmath>
using namespace std;
Bigint::Bigint()
{
for (int i = DIGITS-1; i >= 0; --i) {
digits_[i] = 0;
}
}
ostream& operator<< (ostream& out, const Bigint& n)
{
string s = "";
bool found = false;
for (int i = DIGITS - 1; i >= 0; --i) {
if(n.digits_[i] > 0) {
found = true;
}
if(n.digits_[i] != 0 || found == true) {
s += char(n.digits_[i] + '0');
}
}
if (s == "") {
s = "0";
}
return out << s;
}
istream& operator>> (istream& in, Bigint& n)
{
// Extracts full-length number (does not work for any other length).
// All characters are assumed to be valid digits.
//
string s;
if (in >> s) {
for (int i = 0; i < DIGITS; ++i) {
n.digits_[i] = i < s.length() ? s[s.length() - 1 - i] - '0' : 0;
}
}
return in;
}
Bigint operator+ (const Bigint& n1, const Bigint& n2)
{
Bigint ret;
int cur_carry = 0;
for(int i = 0; i < DIGITS; ++i) {
int n1_digit = n1.get(i);
int n2_digit = n2.get(i);
if(n1_digit < 0 || n1_digit > 9) {
n1_digit = 0;
}
if(n2_digit < 0 || n2_digit > 9) {
n2_digit = 0;
}
//printf("n1 : %d\n", n1_digit);
//printf("n2 : %d\n", n2_digit);
int sum = n1_digit + n2_digit + cur_carry;
//cout << "sum : " << sum << endl;
cur_carry = Bigint::getCarry(sum);
//cout << "new carry : " << cur_carry << endl;
ret.set(i, Bigint::getDigitValue(sum));
//cout << "Set : " << i << "," << Bigint::getDigitValue(sum) << endl;
}
return ret;
}
Bigint operator* (const Bigint& n1, const Bigint& n2)
{
Bigint ret;
//int borrowed = 0;
Bigint sum;
for(int i = 0; i < DIGITS ; i++){
int n1_digit = n1.get(i);
//cout << "n2: " << n2_digit << endl;
Bigint temp;
if(n1_digit < 0 || n1_digit > 9) {
n1_digit = 0;
}
int carry = 0;
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j);
cout << "n1: " << n1_digit << endl;
cout << "n2: " << n2.get(j) << endl;
if(carry != 0){
temp.set(j, (Bigint::getDigitValue(val)) + carry);
cout << "Carry was " << carry << ", now set 0" << endl;
cout << "value to set: " << (Bigint::getDigitValue(val)) + carry << endl;
carry = 0;
}
else if(carry == 0){
temp.set(j, Bigint::getDigitValue(val));
cout << "value to set: " << (Bigint::getDigitValue(val))<< endl;
}
carry = (Bigint::getCarry(val) + carry);
cout << "carry: " << carry << endl;
}
cout << "Sum before adding temp: " << sum << endl;
sum = sum + temp;
cout << "Sum after adding temp: " << sum << endl;
}
ret = sum;
return ret; // Only correct when n2 equals 1.
}
int Bigint::get(int pos) const {
//Return address of digit for reading
int ret = digits_[pos];
return ret;
}
void Bigint::set(int pos, int val) {
this->digits_[pos] = val;
}
int Bigint::getCarry(int val) {
//Integer division, always floors
return val/10;
}
int Bigint::getDigitValue(int val) {
return val % 10;
}
Header file:
#ifndef BIGINT_H_
#define BIGINT_H_
#define DIGITS 20
class Bigint
{
public:
/**
* Creates a Bigint initialised to 0.
*/
Bigint();
/**
* Inserts n into stream or extracts n from stream.
*/
friend std::ostream& operator<< (std::ostream &out, const Bigint& n);
friend std::istream& operator>> (std::istream &in, Bigint& n);
/**
* Returns the sum, difference, product, or quotient of n1 and n2.
*/
friend Bigint operator* (const Bigint& n1, const Bigint& n2);
friend Bigint operator+ (const Bigint& n1, const Bigint& n2);
int get(int pos) const;
void set(int pos, int val);
static int getCarry(int val);
static int getDigitValue(int val);
private:
int digits_[DIGITS];
};
#endif // BIGINT_H_
Main:
#include <iostream>
#include "Bigint.h"
using namespace std;
int main(int argc, char *argv[])
{
Bigint n1, n2;
char op;
while (cin >> n1 >> op >> n2) {
switch (op) {
case '+' :
cout << n1 + n2 << endl;
break;
case '*' :
cout << n1 * n2 << endl;
break;
}
}
return 0;
}
}
you should not use this lineint val = n1_digit * (pow(10, i)) * n2.get(j);
because it will give integer overflow since you are working with bigintger
instead use the digits in the multiplier and add zeros behind the result.
the number of zeros to add will depend on the position of the multiplier digit which you can find the variable i from this loop for(int i = 0; i < DIGITS ; i++) in the overloaded * function
There are a few potential problems
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j); // val % 10 == 0 for i > 0
// You should also be adding the carry to val
cout << "n1: " << n1_digit << endl;
cout << "n2: " << n2.get(j) << endl;
if(carry != 0){
temp.set(j, (Bigint::getDigitValue(val)) + carry);
// This can set temp[j] to values above 9 depending on the carry
cout << "Carry was " << carry << ", now set 0" << endl;
cout << "value to set: " << (Bigint::getDigitValue(val)) + carry << endl;
carry = 0;
}
else if(carry == 0){
temp.set(j, Bigint::getDigitValue(val));
cout << "value to set: " << (Bigint::getDigitValue(val))<< endl;
}
carry = (Bigint::getCarry(val) + carry);
cout << "carry: " << carry << endl;
}
Because you multiply by a power of 10, getDigitValue and getCarry aren't acting the way you expect them to. It might be better to shift the index for temp.set up by i instead of multiplying by pow(10, i).
I would also recommend cleaning up the cases. Both the if and the else if are actually doing the same work in this case, and resetting the carry doesn't do anything. So this would have the exact same behavior:
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * (pow(10, i)) * n2.get(j);
temp.set(j, (Bigint::getDigitValue(val)) + carry);
// If the carry is 0, the addition doesn't do anything
// You don't need to reset the carry to 0, since it's assigned here anyway
carry = (Bigint::getCarry(val) + carry);
}
Without the cases and without the print statements, it's much easier to read, but here the use of methods (getCarry and getDigitValue) still makes it hard to see the problem by moving the relevant operations to the bottom of the class. Making the changes gives:
for (int j = 0; j < DIGITS ; j++){
int val = n1_digit * n2.get(j) + carry;
temp.set(i + j, Bigint::getDigitValue(val));
carry = Bigint::getCarry(val);
// The carry just gets added to the value at the beginning
// Everything else just works that way
}
You also need to change the get and set functions so that they don't work out of bounds:
int Bigint::get(int pos) const {
//Return address of digit for reading
if (pos >= DIGITS)
return 0;
int ret = digits_[pos];
return ret;
}
void Bigint::set(int pos, int val) {
if (pos >= DIGITS)
return ;
this->digits_[pos] = val;
}
With this code, I get 3425 for 25 * 137.
The program has to do with arithmetic sequence. I have my program arranged with these constants that are used for indexing
F = (First term in arithmetic series),
I = ( increment / common difference between terms),
L = (Last term in arithmetic series),
N = (Number of terms in series),
and T = (Total number by adding all terms in series).
The user should enter 3 of the five 5 characters mentioned above followed by a double value that makes sense for each character.
For example:
If the user inputs:
t 3.6 f 1.1 l 1.3
or
T 3.6 F 1.1 L 1.3
The user should receive output of
I 0.1 N 3
This is because the user has given 3 of 5 options defined as constants
I have defined functions to answer all cases required on user input. I have labeled each function name by first 3 letters being the given and last two letters being the unknown. For the example above, calling void fltin(vector<double> & v, vector<bool> & k) would output I and N. (2 cases have been exempt and I have created a function to let the user know should those cases arise below)
Another example:
Calling filnt(vector<double> & v, vector<bool> & k) says the user is giving the values of F, I, and L. Output should be N and T.
My problem:
I am having trouble at the final steps where given user input (not case sensitive) I can call the correct vector element in TABLE. I want to use a vector of type booleans to also control this.
All help is appreciated.
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <string>
using namespace std;
const unsigned F = 0, I = 1, L = 2, N = 3, T = 4;
bool die(const string & msg);
void filnt(vector<double> & v, vector<bool> & k) {
v[T] = v[F];
for (double i = (v[F] + v[I]); i <= (v[L] + v[I]); i += v[I]) {
v[T] += i;
}
cout << "T:" << v[T] << " ";
v[N] = (2 * v[T]) / (v[F] + v[L]);
cout << "N:" << v[N] << endl;
}
void finlt(vector<double> & v, vector<bool> & k) {
v[L] = v[F];
for (double i = 1; i < v[N]; i++) {
v[L] += v[I];
}
cout << "L:" << v[L] << " ";
v[T] = v[F];
for (double i = (v[F] + v[I]); i <= (v[L]); i += v[I]) {
v[T] += i;
}
cout << "T:" << v[T] << endl;
}
void fitln(vector<double> & v, vector<bool> & k) {
bool die("not checking this condition");
}
void flnit(vector<double> & v, vector<bool> & k) {
v[I] = (v[L] - v[F]) / (v[N] - 1);
cout << "I:" << v[I] << " ";
v[T] = v[F];
for (double i = (v[F] + v[I]); i <= (v[L] + v[I]); i += v[I]) {
v[T] += i;
}
cout << "T:" << v[T] << endl;
}
void fltin(vector<double> & v, vector<bool> & k) {
v[N] = (2 * v[T]) / (v[F] + v[L]);
cout << "N:" << v[N] << " ";
v[I] = (v[L] - v[F]) / (v[N] - 1);
cout << "I:" << v[I] << endl;
}
void ftnil(vector<double> & v, vector<bool> & k) {
v[L] = ((2 * v[T]) / v[N]) - v[F];
cout << "L:" << v[L] << " ";
v[I] = (v[L] - v[F]) / (v[N] - 1);
cout << "I:" << v[I] << endl;
}
void iltfn(vector<double> & v, vector<bool> & k) {
bool die("not checking this condition");
}
void ilnft(vector<double> & v, vector<bool> & k) {
v[F] = v[L];
for (double i = 1; i < v[N]; i++) {
v[F] -= v[I];
}
cout << "F:" << v[F] << " ";
v[T] = v[F];
for (double i = (v[F] + v[I]); i <= (v[L]); i += v[I]) {
v[T] += i;
}
cout << "T:" << v[T] << endl;
}
void itnfl(vector<double> & v, vector<bool> & k) {
v[F] = ((v[T] * (2 / v[N])) - ((v[N] - 1)*v[I])) / 2;
cout << "F:" << v[F] << " ";
v[L] = ((2 * v[T]) / v[N]) - v[F];
cout << "L:" << v[L] << endl;
}
void lntfi(vector<double> & v, vector<bool> & k) {
v[F] = ((2 * v[T]) / v[N]) - v[L];
cout << "F:" << v[F] << " ";
v[I] = (v[L] - v[F]) / (v[N] - 1);
cout << "I:" << v[I] << endl;
}
struct FD {
double k1;
double k2;
double k3;
double uk1;
double uk2;
void(*f)(vector<double> &, vector<bool> &);
};
const vector<FD> TABLE = {
{F,I,L,N,T,filnt},
{F,I,N,L,T,finlt},
{F,L,N,I,T,flnit},
{F,L,T,I,N,fltin},
{F,T,N,I,L,ftnil},
{I,L,N,F,T,ilnft},
{I,T,N,F,L,itnfl},
{L,N,T,F,I,lntfi}
};
int main() {
vector<double> v(5);
vector<bool> k = { false, false, false, false, false };
char cone;
char ctwo;
char cthree;
double one;
double two;
double three;
cin >> cone;
cin >> one;
cin >> ctwo;
cin >> two;
cin >> cthree;
cin >> three;
// for loop I am having trouble constructing
/*
*/
}
bool die(const string & msg) {
cout << "Fatal Error:" << msg << endl;
exit(EXIT_FAILURE);
}
You might create a map
void assign(std::vector<double>& v, std::vector<bool>& flags, char c, double value)
{
switch (c)
{
case 'F': case 'f': v[F] = value; flags[F] = true; break;
case 'I': case 'i': v[I] = value; flags[I] = true; break;
case 'L': case 'l': v[L] = value; flags[L] = true; break;
case 'N': case 'n': v[N] = value; flags[N] = true; break;
case 'T': case 't': v[T] = value; flags[T] = true; break;
}
}
int main()
{
vector<double> v(5);
vector<bool> flags = { false, false, false, false, false };
for (int i = 0; i != 3; ++i) {
char c;
double value;
std::cin >> c >> value;
assign(v, flags, c, value);
}
const std::map<std::vector<bool>, void(*)(std::vector<double> &)> m = {
{{true, true, true, false, false}, filnt},
{{true, true, false, true, false}, finlt},
{{true, false, true, true, false}, flnit},
{{true, false, true, false, true}, fltin},
{{true, false, false, true, true}, ftnil},
{{false, true, true, true, false}, ilnft},
{{false, true, false, true, true}, itnfl},
{{false, false, true, true, true}, lntfi}
};
auto it = m.find(flags);
if (it == m.end()) {
std::cout << "Fatal Error: not checking this condition\n";
return EXIT_FAILURE;
}
it->second(v);
}
Demo
So, to sum up, your problem is that you want to call a function based on three characters entered by the user.
There's no super clever way to do this. In particular you can't somehow work the function names you've chosen into the logic of which function to call. So you should drop the coded function names, and choose names that actually describe what the functions do.
Probably the best way is to have a map from the three letter codes to the function (and maybe to the vector<bool>, I didn't really understand that bit).
#include <string>
#include <vector>
#include <map>
typedef void (*function)(std::vector<double>&, std::vector<bool>&);
std::map<std::string, function> table{{"fil", filnt}, {"fin", finlt}, ... };
Then you just lookup the function to call based in the three letter code.
std::string code{cone, ctwo, cthree}; // make three letter code
table[code](v, k); // call appropriate function
Untested code, also you should add some error checking for invalid input.
I have written the code for RSA in C++ on Ubuntu. It was working fine on that, it's working fine on Windows Dev C++ as well, but it doesn't show the character properly.
Here is the code :
#include<iostream>
#include<stdlib.h> // for rand()
#include<math.h> // for floor function
#include<string.h>
using namespace std;
//function to check whether a number is prime or not
int check_prime(int number)
{
int count = 0;
for(int i = 2; i<number + 1; i++)
{
if(number%i == 0)
{
count++;
}
}
if(count>2)
{
return 0;
}
else
{
return 1;
}
}
//function to generate a random prime number
int generate_random_prime()
{
int temp;
while(1)
{
temp = rand() % 50;
if(check_prime(temp) == 1)
{
return temp;
}
}
}
int gcd(int a, int b)
{
int temp;
while(b != 0)
{
temp = b;
b = a%b;
a = temp;
}
return a;
}
// Extended Euclid GCD to find d such de congruent to 1
int extended_gcd(int a, int b)
{
int d, x, y, r, q;
if(b == 0)
{
d = a;
x = 1;
y = 0;
cout << "\n d= " << d << " x= " << x << " y= " << y << "\n";
}
int x2, x1, y2, y1;
x2 = 1;
x1 = 0;
y2 = 0;
y1 = 1;
while(b > 0)
{
q = floor(a / b);
r = a - q*b;
x = x2 - q*x1;
y = y2 - q*y1;
a = b;
b = r;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
d = a;
x = x2;
y = y2;
return x2;
}
//returns a^b mod n using square and multiply method
int modular_exponentiation(int a, int b, int n)
{
if(a == 1)
{
return 0;
}
int c = 1;
for(int i = 1; i < b + 1; i++)
{
c = (c*a) % n;
}
return c;
}
//cipher text = (message^e) %n
int cipher_text(int m, int e, int n)
{
return modular_exponentiation(m, e, n);
}
//decrypted_text= (cipher^d)%n
int decrypt_cipher(int c, int d, int n)
{
return modular_exponentiation(c, d, n);
}
int main()
{
// generating two random prime p and q
int p = generate_random_prime();
int q = generate_random_prime();
cout << "Prime p : " << p << "and q : " << q << "\n";
int n = p*q;
cout << "n=p*q = " << n << "\n";
//calculating Euler Totient for prime p and q
int euler_phi = (p - 1)*(q - 1);
cout << "Euler totient is : " << euler_phi << "\n";
int d, e;
// calculating e such that 1<e<euler_phi and gcd(n,euler_phi)=1
while(1)
{
e = rand() % (euler_phi - 1 + 1) + 1;
if(gcd(euler_phi, e) == 1)
{
break;
}
}
cout << "e value is : " << e << "\n";
//calculating d such that ed congruent 1, ed=1
d = extended_gcd(e, euler_phi);
//d=5;
cout << "d value is : " << d << "\n";
//storing the message to be encrypted as char array and encrypting each char element
char message[20];
int cipher[20];
cout << "Enter the message to be encrypted : ";
cin >> message;
cout << "Message to be encrypted is : " << message << "\n";
int size = strlen(message);
//calculating cipher text c
for(int i = 0; i < size; i++)
{
cipher[i] = cipher_text(int(message[i]), e, n);
}
cout << "Cipher text is : ";
for(int i = 0; i < size; i++)
{
cout << cipher[i] << " ";
}
char message_decrypted[size];
//decrypting cipher text
for(int i = 0; i < size; i++)
{
message_decrypted[i] = decrypt_cipher(cipher[i], d, n);
}
cout << "\nDecrypted message is : ";
for(int i = 0; i < size; i++)
{
cout << message_decrypted[i];
}
cout << "\n";
return 0;
}
I have tried the code on DevC++ and using g++.
Check the images :
Image using g++ compiler
I need a way to print the char to be displayed properly.
I think that message_decrypted[i]=decrypt_cipher(cipher[i],d,n); needs to be changed to print the character properly in Devcpp
Here is the link to the code in online IDE where it works fine https://repl.it/#shubhamjohar/RSA
When your main routine invokes
decrypt_cipher(cipher[i], d, n);
cipher[0] is 386 as matching your output above. d is -179. And n is 697
The corresponding call into modular_exponentiation(a=386, b=-179, n=697) results in this for-loop getting skipped:
for (int i = 1; i<b + 1; i++) {
c = (c*a) % n;
}
Because i < (b + 1) evaluates to (1 < -178), which evaluates to false.
Therefore, your modular_exponentiation returns 1, which is an unprintable character.
Same applies for the subsequent calls to decrypt_cipher from main.
I don't know enough about the RSA algorithm to know if your implementation is correct. But when d is negative, that for-loop isn't going to do any loops.
Maybe it is incurred by the following expression in your program:
char message_decrypted[size];
There is some standard change related to this usage. please read the following page for more details.
https://www.geeksforgeeks.org/variable-length-arrays-in-c-and-c/
Or try to use something like new char[size] to allocate memory dynamically.
I have this recursive function that decompose a number in its prime factors, and show the result standard output for example
descompon(2, 10);
Output
2 = 2
3 = 3
4 = 2^2
5 = 5
6 = 2 * 3
7 = 7
8 = 2^3
9 = 3^2
10 = 2 * 5
The code
#include <iostream>
#include <sstream>
int comprobar_primo( int* num, int e )
{
if (*num%e == 0)
{
*num /= e;
return 1 + comprobar_primo(num, e);
}
return 0;
}
std::string factor_primo(int a, int b, std::stringstream& fact)
{
unsigned exp = comprobar_primo(&a, b);
if (exp >= 1)
{
fact << b;
if (exp > 1) fact << '^' << exp;
if (a != 1) fact << " * ";
}
if (a > 1) factor_primo(a, b + 1, fact);
return fact.str();
}
void descompon(int a, int b, int ver)
{
std::stringstream fact;
//std::string result = factor_primo(a, 2, fact);
if(ver)
std::cout << a << " = " << factor_primo(a, 2, fact) << std::endl;
if(a < b)
descompon( a + 1, b, ver);
}
int main(void)
{
descompon(2, 10000, 1);
return 0;
}
The problem is that when reaches the 5922 the program remains frozen, showing:
Process returned -1073741819 <0xC0000005>
why this happens and how I can avoid?
Both your factor_primo and descompon functions can potentially cause stack overflow. Its better to convert them into iterative version. Modified code is given below:
// no need to pass b as argument since we start from b=2 and increment b by 1
std::string factor_primo(int a, std::stringstream& fact)
{
for(int b=2; a>1; b++)
{
if(a%b==0)
{
unsigned exp=comprobar_primo(&a, b);
if(exp >= 1)
{
fact << b;
if(exp > 1) fact << '^' << exp;
if(a != 1) fact << " * ";
}
}
}
return fact.str();
}
void descompon(int a, int b, int ver)
{
if(ver)
{
for(int i=a; i<=b; i++) {
std::stringstream fact;
std::cout << i << " = " << factor_primo(i, fact) << std::endl;
}
}
}
int main(void)
{
descompon(2, 10000, 1);
getchar();
return 0;
}
I wanted to practice math in c++ and I tried making a program that answered this question from math class
0 < r < 1, find the number of rational r values for which the
numerator and the denominator add to make 1000 where r is in simplest
form
After an hour or two debugging, I finally got something that makes it through all the numbers. In class, the answer was 200. I got 216. Run for yourself
#include <math.h>
#include <iostream>
bool rprime_test(int a, int b) {
int tmp = 2;
std::cout << a << "/" << b;
tmp1:
for (tmp; (tmp < a) && (a % tmp != 0); tmp++) {
}
if ((b % tmp == 0 && a % tmp == 0) || b % a == 0) {
std::cout << " == irreduced\n";
return false;
} else if (!tmp < a) {
std::cout << " == reduced\n";
return true;
} else {
//std::cout << tmp << ","<< a << std::endl;
goto tmp1;
}
}
int main() {
int r = 0, a = 1;
int b = 1000 - a;
while (a < b) {
if (rprime_test(a, b)) {
r++;
}
std::cout << "total = " << r << std::endl;
a++;
b = 1000 - a;
//std::cout << "assigned " << a << "/" << b << std::endl;
}
std::cout << "final result = " << r << std::endl;
return 0;
}
please I don't know what I did wrong for this. Also, is there any better way to optimize this?
Your main issue is with your rprime_test function. Without digging too much into your existing function, try using the gcd. Two numbers a and b are an irreducible fraction when they are "coprime," which is when their "greatest common denominator" (gcd) is 1. The way you compute the gcd of two values is with the Euclidean Algorithm:
int gcd (int a, int b) {
return b % a == 0 ? a : gcd (b % a, a);
}
And your check becomes
if (gcd (a, b) == 1) {
a++;
/* etc */
}
Following works:
#include <iostream>
int gcd(unsigned int a, unsigned int b)
{
if (b < a) {
return gcd(b, a);
}
int r = a % b;
while (r != 0) {
a = b;
b = r;
r = a % b;
}
return b;
}
int main()
{
int count = 0;
for (int i = 1; i != 500; ++i) {
if (gcd(1000 - i, i) == 1) {
++count;
}
}
std::cout << count << std::endl;
}
Live example