How do I convert this function into a loop? - c++

I have an array of letters of an unknown number of elements which contains lower case letters. I have written a function for converting a lower case number to its ASCII value
int returnVal (char x)
{
return (int) x;
}
I am trying to combine all of these values into one number. Subtracting 87 from each of these means that the value is always a 2 digit number. I am able to combine an array made up if two elements by:
returnVal (foo[0]) - 87) + returnVal (foo[1] - 87) * 100
an array made up of three elements by
returnVal (foo[0]) - 87) + returnVal (foo[1] -87) * 100 + returnVal (foo[2] - 87) * 100 * 100
I am multiplying each element by 100^its position in the array and summing them. This means that [a,b,c] would become 121110 (yes, the 'flip' having the value for 'c' first and 'a' last is intentional). Could anybody programme this (for an array of an unknown number of elements)?
EDIT: I have received no form of schooling at programming/computer science at any pojnt in my life, this is not homework. I am trying to teach myself and I have got stuck; I don't know anybody in person who I could go to for help so I asked here, apologies to those of you who are offended.
EDIT2: I know that this opinion is going to annoy a lot of people; what is the purpose of stackoverflow.com if it is not to exchange information? If I were a child who was stuck with my homework (I'm not) surely that is a valid reason for using stack overflow? Many people on this website seem to have the mindset that if a problem is asked by a beginner then it is not worth answering, which is completely fine because your time is your own. However, what genuinely bugs me is the people who see a question which they deem trivial and say "homework" and vote it down immediately. I think that this website would be far better if there wasn't an "minimum-level" knowledge required in order to ask questions, the "elitist" mindset is just childish in my opinion.

Since this is a learning exercise, here are some hints for you to complete the task yourself:
Prepare a value that will server as the "running total" for your number so far.
Start the running total at zero.
When you convert a number, say, "1234", to an int, this value would first become 1, then 12, then 123, and finally 1234
The final value of the running total is your end result
To go from a previous value to the next, multiply the prior value by ten, and add the value of the current digit to it
Your returnVal does not make sense, because in C you can very often avoid an explicit conversion of char to int. You can definitely avoid it in this case.
Making a function int digit(char c) that returns a value of decimal digit, i.e. c-'a', would be a lot more useful, because it would let you get rid of your c-87 in multiple spots.

char array[SIZE];
long factor=1;
long result=0;
for(int i=0; i<SIZE; i++)
{
result+=returnVal(foo[i])-87)*factor;
factor*=100;
}
This should work for as long as long is large enough to hold the value of 100^the position and, of course, as long as the result does not overflow.

Related

Collecting remainders while converting a number to ternary base ( C++ )

I am trying to write a program in C++. It's a much longer program, but I need help regarding just one of the functions in it.
Basically, this function should get a number, and then return that same number but in ternary base. Now, my idea is to basically divide that number by 3 and collect remainders ( if my number is "n", I'd use n%3) and then I would just divide that number with 3 ( n/3 ) and go again until that number "n" by repeated division becomes 0.
This should work and convert the number to ternary base, but my problem is the fact that I do not know how to collect these remainders. This is probably a stupid question, but I am still a begginer in programming.
Basically, if I make a while loop , something like this :
while(n>0)
{
int digitofternary=n%3;
n/=3;
}
In every iteration of while loop, digitofternary is just going to change. How can I adjust this loop so digits get remembered/collected and I can return a new normal ternary base number from function?
Sorry if this sounded confusing, hope it didn't ( I am not a native english speaker ).
int sample_fn (int n)
{
std::string str_ret;
while(n>0)
{
int digitofternary=n%3;
n/=3;
std::string str= std::to_string(digitofternary);
str_ret.append(str);
}
return std::stoi(str_ret);
}

C++ program crashes at delete only when character array gets the input of "1000!"

I wrote a quick and dirty factorial program using the GMP library in C++, which allocates some memory for a character array. The program works fine for all input values that I've tested, except 1000.
I've tried different ways to allocate the memory, and different ways to deallocate it, but none have worked so far and almost always crash on 1000.
This is everything that happens between creating the character array and deleting it. factor is the calculated factorial and mpz_sizeinbase returns the number of digits in the number in the specified base. gmp_sprintf just transforms the number into the character array.
int count = mpz_sizeinbase(factor, 10);
char* zeroes = new char[count];
gmp_sprintf(zeroes, "%Zd", factor);
printf("After conversion: %s\n", zeroes);
int trailingzeroes = 0;
for(int i = strlen(zeroes)-1; i > 0; i--){
if(zeroes[i] == '0')
trailingzeroes++;
else
break;
}
printf("Trailing zeroes: %i\n", trailingzeroes);
delete [] zeroes;
When the input is 1000, meaning that I want to calculate 1000!, I get the error
double free or corruption (!prev)
Aborted
at delete [].
All other inputs work, as far as I can tell.
What could I be doing wrong?
From the mpz_sizeinbase documentation: "The right amount of allocation is normally two more than the value returned by mpz_sizeinbase, one extra for a minus sign and one for the null-terminator." You probably don't have a negative factorial, but you are certainly not allocating enough space for including the terminating null character.
It would be instructive to check the return value of gmp_sprintf because it tells you how many characters it actually wrote. I would wager that in your case it returns count+1, which would mean it wrote past the end of the buffer (which is Undefined Behavior).
The fact that it sometimes might work is probably related to the fact that "the result will be either exact or 1 too big" (for bases other than 2). That and of course the unpredictable nature of UB.

How to use a string or a char vector (containing any chemical composition respectively formula) and calculate its molar mass?

I try to write a simple console application in C++ which can read any chemical formula and afterwards compute its molar mass, for example:
Na2CO3, or something like:
La0.6Sr0.4CoO3, or with brackets:
Fe(NO3)3
The problem is that I don't know in detail how I can deal with the input stream. I think that reading the input and storing it into a char vector may be in this case a better idea than utilizing a common string.
My very first idea was to check all elements (stored in a char vector), step by step: When there's no lowercase after a capital letter, then I have found e.g. an element like Carbon 'C' instead of "Co" (Cobalt) or "Cu" (Copper). Basically, I've tried with the methods isupper(...), islower(...) or isalpha(...).
// first idea, but it seems to be definitely the wrong way
// read input characters from char vector
// check if element contains only one or two letters
// ... and convert them to a string, store them into a new vector
// ... finally, compute the molar mass elsewhere
// but how to deal with the numbers... ?
for (unsigned int i = 0; i < char_vec.size()-1; i++)
{
if (islower(char_vec[i]))
{
char arr[] = { char_vec[i - 1], char_vec[i] };
string temp_arr(arr, sizeof(arr));
element.push_back(temp_arr);
}
else if (isupper(char_vec[i]) && !islower(char_vec[i+1]))
{
char arrSec[] = { char_vec[i] };
string temp_arrSec(arrSec, sizeof(arrSec));
element.push_back(temp_arrSec);
}
else if (!isalpha(char_vec[i]) || char_vec[i] == '.')
{
char arrNum[] = { char_vec[i] };
string temp_arrNum(arrNum, sizeof(arrNum));
stoechiometr_num.push_back(temp_arrNum);
}
}
I need a simple algorithm which can handle with letters and numbers. There also may be the possibility working with pointer, but currently I am not so familiar with this technique. Anyway I am open to that understanding in case someone would like to explain to me how I could use them here.
I would highly appreciate any support and of course some code snippets concerning this problem, since I am thinking for many days about it without progress… Please keep in mind that I am rather a beginner than an intermediate.
This problem is surely not for a beginner but I will try to give you some idea about how you can do that.
Assumption: I am not considering Isotopes case in which atomic mass can be different with same atomic number.
Model it to real world.
How will you solve that in real life?
Say, if I give you Chemical formula: Fe(NO3)3, What you will do is:
Convert this to something like this:
Total Mass => [1 of Fe] + [3 of NO3] => [1 of Fe] + [ 3 of [1 of N + 3 of O ] ]
=> 1 * Fe + 3 * (1 * N + 3 * O)
Then, you will search for individual masses of elements and then substitute them.
Total Mass => 1 * 56 + 3 * (1 * 14 + 3 * 16)
=> 242
Now, come to programming.
Trust me, you have to do the same in programming also.
Convert your chemical formula to the form discussed above i.e. Convert Fe(NO3)3 to Fe*1+(N*1+O*3)*3. I think this is the hardest part in this problem. But it can be done also by breaking down into steps.
Check if all the elements have number after it. If not, then add "1" after it. For example, in this case, O has a number after it which is 3. But Fe and N doesn't have it.
After this step, your formula should change to Fe1(N1O3)3.
Now, Convert each number, say num of above formula to:
*num+ If there is some element after current number.
*num If you encountered ')' or end of formula after it.
After this, your formula should change to Fe*1+(N*1+O*3)*3.
Now, your problem is to solve the above formula. There is a very easy algorithm for this. Please refer to: https://www.geeksforgeeks.org/expression-evaluation/. In your case, your operands can be either a number (say 2) or an element (say Fe). Your operators can be * and +. Parentheses can also be present.
For finding individual masses, you may maintain a std::map<std::string, int> containing element name as key and its mass as value.
Hope this helps a bit.

SPOJ SCUBADIV - Recursive DP Approach [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been trying to solve http://www.spoj.com/problems/SCUBADIV/ question at SPOJ. I have come up with a recursive DP solution.
I am using knapsack approach with a 3 dimensional array to store the number of cylinders, required oxygen weight, and nitrogen weight. At each recursive step I'm checking for the amount of oxygen and nitrogen yet to be filled. If it is negative, it's as good as zero.
#include<bits/stdc++.h>
using namespace std;
#define inf 99999999
int n;
vector<int> o;
vector<int> ni;
vector<int> w;
int ow;
int nw;
int knapsack(int n,int ow,int nw); // n - number of cylinders,ow-wt. of oxygen
// nw-wt. of nitogen.
int main(){
int t;
scanf("%d",&t);
while(t--){
int i;
scanf("%d %d",&ow,&nw);
scanf("%d",&n);
o.resize(n);
ni.resize(n);
w.resize(n);
for(i=0;i<n;i++)
scanf("%d%d%d",&o[i],&ni[i],&w[i]); // o[i] storing wt. of oxygen cylinders
int res = knapsack(n,ow,nw); //ni[i] storing wt. of nitrogen cylinders
printf("%d",res);
}
return 0;
}
int knapsack(int n,int ow,int nw){
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp)); //setting value of array to inf to get minimum weight
int i;
for(i=0;i<n;i++)
dp[i][0][0]=0;
if(dp[n][ow][nw]!= inf)
return dp[n][ow][nw];
else if (ow - o[n-1]>=0 && nw - ni[n-1]>=0)
return dp[n][ow][nw]= min(knapsack(n-1,ow,nw),w[n-1]+knapsack(n-1,ow-o[n-1],nw-ni[n-1]));
else if(ow -o[n-1]<0 && nw - ni[n-1] >=0)
return dp[n][ow][nw]=min(knapsack(n-1,0,nw),w[n-1]+knapsack(n-1,0,nw-ni[n-1]));
else if(ow-o[n-1]>=0 && nw-ni[n-1]<0)
return dp[n][ow][nw]=min(knapsack(n-1,ow,0),w[n-1]+knapsack(n-1,ow-o[n-1],0));
else if(ow-o[n-1]<0 && nw-ni[n-1]<0)
return dp[n][ow][nw]= knapsack(n-1,0,0);
}
This code is not giving the desired result (it's giving -1). Is the approach correct ?
There is a problem with this code:
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp));
The memset() function sets a byte pattern, not a value. Since inf is a larger-than-a-byte value, it is essentially doing inf % 256 and initializing all the bytes in dp[][][] to that value. This is further complicated by dp[][][] being of base type int, so 4 bytes set to the same byte value is something unexpected.
In the case of your value for inf, of 99999999, the byte value will be 0xff, and so all the ints in dp[][][] will be set to -1.
I don't know if this is expected, but it looks like it could be a mistake.
Let M(x, O, N) be the minimum weight of cylinders that will provide O liters of oxygen and N liters of nitrogen by choosing from only cylinders 1 to x. Let O(x), N(x), and W(x) be the amount of oxygen and nitrogen available in the x'th cylinder and the cylinder's weight respectively. Then either we choose to use the x'th cylinder or we don't:
M(x, O, N) = min( W(x) + M(x - 1, O - O(x), N - N(x)), M(x - 1, O, N) )
The base case occurs when we have no cylinders at all.
M(0, O, N) = 0 if O <= 0 and N <= 0, infinity otherwise
I won't be reading your unformatted, cryptically written code to figure out whether it implements this correctly. I will say memset can only be used to set bytes to a given value. Your call is not doing what you think. Additionally, your recursive procedure returns junk if execution reaches the end of the if chain.
Work a small example by hand. Run your code either in a debugger or with printfs inserted to show what's going on. Figure out where its actual execution diverges from your hand calculation.
Yes, it is possible to solve this problem with a recursive approach, but this is not how to do it. There are multiple problems with the code, and 'obviously' it will return -1. The question is I shall try to answer is: tell me some of the things wrong with this code.
Variable names like dp obscure the meaning of the code. Give them meaningful names!
Don't resize a vector and read into a pointer. Read values and push them onto the vector.
Print out the data to ensure you read it right.
The memset function fills with bytes, in this case -1. Use a loop to initialise ints.
The first if statement can only ever return 0 or -1 (or inf once you fix the init). As it is the other code will not be executed.
Assigning a value into dp is of no effect, since it is in automatic storage (on the stack).
I don't understand the chain of if statements. Explain them.
There is no else so the function can fall off the end.
Best to rewrite, debug, and if it still doesn't work come back with something we can read.

a lot of decimal value storage in C++

I wanted to write a program that returns how many months we could survive when we're given
our monthly expenditure, amount of disposable income, and interest rate (all in integers).
For instance, if we start with disposable income = 1000, interest rate = 5%, monthly expenditure = 100, then
after first month: 1000*1.05 - 100 = 950, we have 950 dollars left
after second month: = 950*1.05 - 100 = 897.5
and so on, and in the end, we can survive 14 months.
I wrote the following code in C++:
int main(){
int i=0;
int initialValue;
int interest;
int monthly;
double value=1.0*initialValue;
double r=1+1.0*interest/100;
while(value > 0){
if(value < monthly){
break;
}
else
{
value=value*r-monthly;
i++;
}
};
cout<<i;
return 0;
}
but for sufficiently large values of initialValue and small values of monthly, the program I wrote runs very slowly to the degree that it's unusable. Is there a problem with the code that makes it run not well (or very slow)?
Any help would be greatly appreciated.
double cannot store numbers precisely. One consequence of this is when you subtract a very small number from a very large number, the result is not changed from the original large value.
One solution to this problem is to use an int to do your calculations. Think of the values as the number of pennies, rather than the number of dollars.
A few notes:
The *1.0's are pointless. Instead, take advantage of implicit and explicit casts:
double value=initialValue;
double r=1+(double)interest/100;
++i is faster than i++.
value=value* can be rewritten as value*=.
You can mix the first two conditionals. Remove the if...break and change the while loop to while (value > 0 && value < monthly).
On the face of it, the reason this runs slowly is the large number of iterations. However, you didn't specify any specific numbers and I would expect this code to be able to execute at least a million iterations per second on any reasonably fast processor. Did you really expect to need to calculate more than 1 million months?
Apart from the novice style of the code, the underlying problem is the algorithm. There are very simple formulae for making these calculations, which you can find here: https://en.wikipedia.org/wiki/Compound_interest. Your situation is akin to paying off a loan, where running out of money equals loan paid off.