Transform iterative function to recursive function - c++

I was having a discussion with a coworker about how to transform the following iterative function into a strictly recursive function. We know that all iterative functions can be transformed into recursive functions; however, my coworker remembered that this particular implementation used only three parameters. We can't re-solve this problem. Are we remembering incorrectly? Or are we missing something simple?
void iterative_function (char a, char b, int width) {
int i = width;
while (i > 0) {
cout << string(i, a) << string(width-i, b) << endl;
i -= 2;
}
i = width % 2;
while (i <= width) {
cout << string(i, a) << string(width-i, b) << endl;
i += 2;
}
}
Where the output looks something like below when called like iterative_function('X', '-', 5).
XXXXX
XXX--
X----
XXX--
XXXXX
EDIT: Here is a small skeleton of what the recursive version might look like:
void recursive_function (char a, char b, int width) {
if (width > -1) {
cout << string(width, a) << endl;
recursive(a, b, width - 2);
cout << string(width, a) << endl;
}
}
Except the problem here is filling the right side out with, say, hyphens.

Here is the recursive function, I just add another len to your function you can see in here, that its output is exactly like the output of your code here.
#include <iostream>
using namespace std;
void i_f(char a, char b, int width,int len) {
if(len <0 || width < 0)
return;
cout <<string(width, a) << string(len, b) << endl;
i_f(a,b,width-2,len+2);
cout <<string(width, a) << string(len, b) << endl;
}
int main() {
i_f('X', '-', 5,0);
return 0;
}
your code output:
XXXXX
XXX--
X----
X----
XXX--
XXXXX
my code output:
XXXXX
XXX--
X----
X----
XXX--
XXXXX
P.S After I posted my answer I saw your edit, although you edited your question 10 minutes before my answer, and I can see that you choose a path like my answer yourself.

Related

How to use MPIR Prime testers mpz_likely_prime_p and mpz_probable_prime_p?

I'm trying to use MPIR's prime tester(s) for rapid non-sequential testing; however, I'm new to MPIR and am confused about their usage - specifically the "gmp_randstate_t" parameter used by the function. Here's what I've got so far:
#include<iostream> // used for cout
#include<mpir.h>
int main() {
mpz_t PrimeCanidate;
mpz_init(PrimeCanidate);
mpz_set_ui(PrimeCanidate, 3); // sets PrimeCanidate to unsigned int "3"
if (mpz_likely_prime_p(PrimeCanidate) == 1) {
std::cout << "Number is prime: " << std::endl;
}
}
As I'm only using one parameter inside mpz_likely_prime_p, it doesn't work - I just don't know what it's looking for with the other parameters (state, div) as shown in the documentation (http://www.mpir.org/mpir-3.0.0.pdf pg. 42):
Would anybody by chance have a simple code that uses the prime-testing functions in MPIR? Thanks a ton.
After a bunch of tinkering, I figured out how to properly initialize the "state" and div" parameters for mpz_likely_prime_p. Here's an example calculating and printing primes between 1 and 100:
#include<iostream> // used for cout
#include<mpir.h>
int main() {
mpz_t PrimeCanidate;
mpz_init(PrimeCanidate);
mpz_set_ui(PrimeCanidate, 2);
mpz_t additor;
mpz_init(additor);
mpz_set_ui(additor, 1);
gmp_randstate_t state;
gmp_randinit_default(state);
mpir_ui div = 0;
int maxbase = 100;
for (int base = 2; base < maxbase; base++) {
mpz_add(PrimeCanidate, PrimeCanidate, additor); // repeatedly adds one to PrimeCanidate
std::cout << "Tested Number: " << PrimeCanidate << std::endl;
if (mpz_likely_prime_p(PrimeCanidate, state, div) == 1) {
std::cout << PrimeCanidate << " is prime." << std::endl;
}
}
}
This is probably not optimal, but it works and might be a good place to start.

Determining if user input is palindrome with C++

First of all, I very much appreciate any help you are willing to provide. I am new to C++ and have been scouring this website as well as other resources for the solution to my problem.
Further, this was indeed a portion of a homework assignment. However, the assignment has been turned in (upsettingly, without getting this code to work). It would be great to get an explanation for what the problem in my specific code is and how to fix my current code, rather than the just rewritten code with a different way to approach to problem. I certainly found plenty of ways to solve this problem on this wonderful site!
I am getting no errors with my code, however the reversal output is not showing the reversed character array. This results in my little program here always showing "Your string is not a palindrome! :(" no matter what the input is.
#include <iostream>
#include <string>
using namespace std;
int isPalindrome(char *input, char *input2);
char reverseString(char *input);
int main ()
{
char input[50];
char input2[50];
cout << "Please enter a string of characters no larger than 50." << endl;
cin.getline(input, 50);
reverseString(input);
cout << "The reversed string is " << input2 << endl;
int result;
result = isPalindrome(input, input2);
if(result == 0)
cout << "Your string is a palindrome!" << endl;
else
cout << "Your string is not a palindrome! :( " << endl;
return 0;
}
int isPalindrome(char* first, char* second)
{
if (*first == *second)
return 0;
else
return 1;
}
char reverseString(char* input2)
{
int size = sizeof(input2);
for (int i = 0; i < (size/2); i ++)
swap(input2[i], input2[size-i-1]);
return *input2;
}
Again, I appreciate any help you can provide! I apologize if this is a simple error that I am overlooking and should have been able to find elsewhere.
Checking for a palindrome does not take this much effort.
bool isPalindrome(const char* s) // this function is self-contained.
{ // the caller does not need to provide
size_t n = strlen(s); // any pre-computed value.
if (n == 0)
return false;
const char* e = s + n - 1;
while (s < e)
if (*s++ != *e--)
return false;
return true;
}
int main ()
{
char input[50];
cout << "Please enter a string of characters no larger than 50." << endl;
cin.getline(input, 50);
bool result = isPalindrome(input);
cout << "Your string is"
<< ((result) ? " " : " not ")
<< "a palindrome!\n";
return (result) ? 1 : 0;
}
In your reverseString function:
char reverseString(char* input2)
{
int size = sizeof(input2); // <-- ?? sizeof(char*) != strlen(input2)
size_t size = strlen(input2); // <-- should read.
for (int i = 0; i < (size/2); i ++)
swap(input2[i], input2[size-i-1]);
return *input2; // what's this? returning first char? why?
}

Interval for bisection method

I've been assigned a project to determine the square root of a number without using division or the math.h library. Upon doing my own research I've decided to tackle the problem by using the bisection method. I used the pseudo code portion from the Bisection Wikipedia page:
https://en.wikipedia.org/wiki/Bisection_method#Example:_Finding_the_root_of_a_polynomial
to setup the algorithm.
My Code
#include <iostream>
#include <cmath>
#include <stdlib.h>
using namespace std;
void __attribute__((weak)) check(double alt_sqrt(double));
//default check function - definition may be changed - will not be graded
void __attribute__((weak)) check(double alt_sqrt(double))
{
if(alt_sqrt(123456789.0) == sqrt(123456789.0))cout << "PASS\n";
else cout << "FAIL\n";
return;
}
//change this definition - will be graded by a different check function
double my_sqrt(double x)
{
int i = 0;
double a = 0.0; // Lower Bound
double b = x + 1; // Upper Bound
double c = 0.0; // Guess for square root
double error = 0.00001;
double fc = 0.0;
while(i < 10000)
{
c = (a+b)*0.5;
fc = c * c - x;
if(abs(fc) < error || (b-a)*0.5 < error) // Check for solution
{
cout << "Square root is: " << c << endl;
break;
}
if(fc < 0) // Setup new interval
{
a = c;
cout << "a is: " << a << endl;
}
else b = c;
cout << "b is: " << b << endl;
i++;
}
return c;
}
//Do not change this function
int main()
{
check(my_sqrt);
return 0;
}
The output I am currently getting for my professor's test case in main is
Square root is: 1.23457e+08
FAIL
When the correct output should be
Square root is: 11,111.11106
PASS
I believe that I am going wrong in the way that I setup my new intervals. My thinking is that if the difference between the two values is negative, then I need to push the lower bound up, and if the difference is positive, then I need to bump the upper bound down.
I would appreciate any advice y'all could give me. Thank you for your time.
The condition fb - fa < 0 is wrong because ignoring floating-point errors, fa < fb, which is a * a - x < b * b < x will be always true for 0 <= a < b.
Changing the condition to fc < 0 improved the accuracy, but unfortunately this improvement coundl't make the program print "PASS". To improve the accuracy to have the program print "PASS", delete the harmful breaking part
if(abs(fc) < error || (b-a)*0.5 < error) // Check for solution
{
cout << "Square root is: " << c << endl;
break;
}
Removing this harmful breaking and adding the line
cout << "Square root is: " << c << endl;
just before
return c;
gave me
Square root is: 11111.1
PASS
but unfortunately this is not what you want.
To have what you want printed,
#include <iomanip>
should be added and the printing part should be
std::cout.imbue(std::locale(""));
cout << fixed << setprecision(5) << "Square root is: " << c << endl;

Reading into an Array Multiple Times

I'm having a little trouble with my code. It's pretty much supposed to open two files, and compare the first twenty line of the file "StudentAnswers.txt" [inputted as a char into a char array] against a char value in (each line of another file) "CorrectAnswers.txt" in another array at the same position (index). It's like a linear search, but the same position in the arrays. Then a report should be displayed, detailing which question the student missed, the given answer, the correct answer, and if the student passed (got >= 70%) or not, like the following:
Report for Student X:
2 (A/D), 3 (C/D), 5(D/A)
This student passed the exam!
Then it should clear the SAArray, and feed the next twenty lines from StudentAnswers.txt, and start the process all over again. I guess the program has to determine the number of students from (lines of 'StudentAnswers.txt' file / 20).
I'm having trouble displaying the report, and having the array clear itself after the program. I'm guessing this can be done with a while loop and an accumulator for the number of students (to be determined by above equation).
Also, Visual Studio seems to go to "Missed __ questions for a total of ___ %", and then keep looping -858993460.
Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <algorithm>
using namespace std;
void GradeReturn(char[], char[], int, int, int);
string PassFail(float);
int main()
{
ifstream SA("StudentAnswers.txt");
ifstream CA("CorrectAnswers.txt");char CAArray[20];
char SAArray[20];
// char SA2Array[20];
bool isCorrect;
int correct;
int incorrect;
int counter;
correct = 0;incorrect = 0;
counter = 0;
cout << endl;
if (!SA.fail())
{
cout << "'StudentAnswers.txt' file opened successfully." << endl;
cout << "'CorrectAnswers.txt' file opened successfully." << endl << endl;
int a = 0;
int b = 0;
while (a < 20)
{
CA >> CAArray[a];
a++;
} // while loop to feed char into the array
while (b < 20)
{
SA >> SAArray[b];
b++;
}
} // while loop to feed char into array
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
return 0;
}
void GradeReturn(char CAArray[], char SAArray[], int correct, int incorrect, int counter)
{
float percent;
float hundred;
int student;
int catcher[20];
int writeCatcher; int starter;
int catcher_size;
student = 0;
writeCatcher = 0;
catcher_size = ((sizeof catcher) / 4);
while (counter < 20)
{
if ((CAArray[counter]) == (SAArray[counter]))
{
correct++;
cout << "Good job!" << endl;
} // correct handling
else
{
incorrect++;
cout << "You got question " << counter << " wrong." << endl;
counter >> catcher[writeCatcher];
writeCatcher++;
} // incorrect handling
counter++;
} // while loop to determine if a student got a question right or wrong
static_cast <float> (incorrect); // float conversion
cout << endl; // for cleanliness
percent = ((static_cast <float> (correct)) / 20); // percentage
hundred = percent * 100;
PassFail(percent);
if (PassFail(percent) == "pass")
{
student++;
cout << "Report for Student " << student << ":" << endl;
cout << "-----------------------------" << endl;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
starter = 0;
while (starter < (sizeof catcher)
{
if(1=1)
{
catcher_size
}
else
{
cout << "";
starter++;
}
}
}
else if (PassFail(percent) == "fail")
{
student++;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
while (starter < catcher_size)
{
if ((catcher[starter]) == -858993460)
{
starter++;
}
else
{
cout << "";
starter++;
}
}
}
return;
}
string PassFail(float percent)
{
if (percent >= 0.70) // if <pass>
{
return "pass";
}
else // if <fail>
{
return "fail";
}
cout << endl;
}
To get a loop you should keep streams open instead of closing them after reading 20 lines.
As pseudo code that would be:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
a = 0; // Reset a
}
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
You would also need to pass correct, incorrect, counter by reference so that the GradeReturn can change their value and their by do the accumulation.
Like:
void GradeReturn(char CAArray[], char SAArray[], int& correct, int& incorrect, int& counter)
Further you shouldn't rely on being able to read exactly Nx20 lines from the files every time. A file could have, e.g. 108 (5x20 + 8) lines, so you code should be able to handle the with only 8 lines. In other words, don't hard code 20 in your function like while (counter < 20). Instead pass the number of lines to be handled and do while (counter < number_to_handle).
Something like this as pseudo code:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
// ^
a = 0; // Reset a
}
}
if (a != 0)
{
// Process the rest
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
One problem you have is you're trying to compare C-style strings with the == operator. This will compare them essentially as if they were pointers to char, i.e. compare whether they point at the same location in memory, not compare the contents of the string. I urge you to look up array-decay and c-string variables to understand more.
Specifically, if (PassFail(percent) == "pass") isn't going to do what you want it to. strcomp doc, strncmp doc using std::string variables instead of c-style strings would all work, but it would be better simply to compare percent to a value, i.e. if(percent >= 0.70 directly instead of calling PassFail and comparing a string.
There are many other issues here also, you at one point call PassFail but do nothing with the return value. The only side affect of PassFail is cout << endl, if that's what you intend, it's a poor decision and hard to read way to put a newline on the console.
Try asking your compiler for more warnings, that's often helpful in finding these types of issues. -Wall -Wextra work for gcc, you may have to read your compiler manual...

C++ Swapping an array of integers passed through an int& parameter

I need to swap a couple of integers in the format int i[2] using a void swap(int& x) function. As you see the function takes an argument of type int&. Here is non-working version of the function:
int i[2] = {3, 7};
void swap (int& x)
{
int temp;
temp = x[1];
x[1] = x[0];
x[0] = temp;
}
int main()
{
cout << i[0] << ", " << i[1] << "\n"; // return the original: (3, 7)
swap(i);
cout << i[0] << ", " << i[1] << "\n"; // return i swapped: (7, 3)
}
How should I do this?
Edit: The answer CANNOT use anything else for the function parameter. It MUST use a int& parameter. This is a problem from Bjarne Stroustrup's book: "The C++ programming language", third edition. It is problem #4 from chapter 5. The problem first asks to write a function taking a int* as parameter, than to modify it to accept a int& as parameter.
A reference isn't a pointer. I'd recommend changing the function signature if you can, but if you're stuck with it, you could do something like:
int *xx = &x;
int temp = xx[1];
xx[1] = xx[0];
xx[0] = temp;
That said, you should probably just use std::swap instead.
Looking at my copy, the exercise doesn't say how swap() should look like. It just says that it "swaps (exchanges the value of) two integers" and should take a) int* b) int& as the argument type.
As you tagged the question learning, the real question becomes:
Why does your swap() only take one argument?
All right, thanks to #gf's suggestions, I found a solution :) Many thanks! Please tell me if you see anything not very C++ish in there.
// Swap integers
#include<iostream>
using namespace std;
int i = 3;
int j = 7;
void swap (int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
cout << i << ", " << j << "\n"; // return the original: (3, 7)
swap(i, j);
cout << i << ", " << j << "\n"; // return i swapped: (7, 3)
}