Can anyone Simplify this program related to calculating train fare? - c++

Take the input of kilometers, and the class of journey(1, 2 or 3 for first, second and third class respectively), for a train journey. The program should then calculate the fare of the journey based on the following criteria:
I Could not do the program in one single equation, so I did it using if else statements. Can this program be made shorter and can the logic be designed without the need of the if else statements? Can the logic of the program be represented as a single mathematical equation(using only arithmetic operators)?
My Code:
//
// main.cpp
// c++
//
// Created by Aniansh Raj on 14/08/16.
// Copyright © 2016 Aniansh Raj. All rights reserved.
//
#include <iostream>
using namespace std;
int main()
{
unsigned int km, cl, amt;float r1, r2, r3;
cout<<"Enter distance in kilometer\n";
cin>>km;
cout<<"Enter Class(1, 2 or 3)\n";
cin>>cl;
switch(cl)
{
case 1:
r1=3;r2=2.5;r3=2;break;
case 2:
r1=2;r2=1.5;r3=1;break;
case 3:
r1=1.5;r2=1;r3=0.5;break;
default:
cout<<"Error!\n";
return 0;
}
if(km>=100&&km<=250)
amt=(100*r1)+(km-100)*r2;
else if(km>250)
amt=(100*r1)+(150*r2)+(amt-250)*r3;
else
amt=km*r1;
cout<<endl<<amt;
}

You can reorganize your code in many ways, but I don't think you could obtain exactly what you want.
For example you can store the prices in an array:
unsigned int price[3][3] = {
{300, 250, 200}, // first class, Rupee cents per km
{200, 150, 100}, // second class
{150, 100, 50}, // third class
};
Ask for the distance and the class, then calculate and print the amuont like this:
unsigned int amount;
if ( d <= 100 )
amount = d * price[c][0]; // c = cl - 1; considering your code
else if ( d <= 250 )
amount = 100 * price[c][0] + (d - 100) * price[c][1];
else
amount = 100 * price[c][0] + 150 * price[c][1] + (d - 250) * price[c][2];
std::cout << "distance: " << d << " price: " << amount / 100.0 << '\n';
Now, we can simplify those (linear) equations noticing that are of the form:
amount = constant + d * price
And precalculate the first part, which happens to be the same for all classes and depends only on the range. So, given this array:
unsigned int p0[] = {0, 5000, 17500};
The previous snippet can be rewritten (and "simplified") like this:
unsigned int index = d < 250 ? ( d < 100 ? 0 : 1 ) : 2;
unsigned int amount = p0[index] + d * price[cl - 1][index];
std::cout << "distance: " << d << " price: " << amount / 100.0 << '\n';
One other option, which only hides the conditional part inside a library function, can be:
unsigned int amount = std::min({
p0[0] + d * price[cl - 1][0],
p0[1] + d * price[cl - 1][1],
p0[2] + d * price[cl - 1][2]
});
std::cout << "distance: " << d << " price: " << amount / 100.0 << '\n';

Strictly speaking there's an equivalent ternary statement of
if(km>=100&&km<=250)
amt=(100*r1)+(km-100)*r2;
else if(km>250)
amt=(100*r1)+(150*r2)+(amt-250)*r3;
else
amt=km*r1;
in the form of
amt = (km>=100&&km<=250) ? (100*r1)+(km-100)*r2 : (km>250) ? (100*r1)+(150*r2)+(amt-250)*r3 : km*r1;
Which isn't really as readable as the prior block. If what you're looking for is to have it in a formula, then this should be a bit cleaner than the above:
amt = km * r1 +
( km > 100 ?
km > 250 ?
150 * r2 + (km - 250) * r3 - (km - 100) * r1 :
(km - 100) * (r2 - r1) :
0 ); /* readblity */
Although I don't understand why if statements are bad. It's more readable and has the same performance.

Related

Modeling velocity and height of rocket c++

Hi We are supposed to model the height and velocity of a rocket in c++ for our final project. Having user input the total flight time and delta time for the points during flight that they wish to measure. The following is the code I have written for this project. The velocity is supposed to start positive and after 60 seconds at which point there is no fuel left and thus no thrust the velocity should start becoming negative. However both my height and velocity are coming out as negative from the start and reaching negative infinite by the end.
#include <iostream>
using namespace std;
int main()
{
float *v;
float *h;
float a;
double mass=0.0, thrust, time, dt;
double g = 32.2;
double K = 0.008;
cout << "enter time";
cin >> time;
cout << "enter dt";
cin >> dt;
a = (time/dt);
v = new float[a];
h = new float[a];
v[0] = 0;
h[0] = 0;
float tt = 0;
// for loop to calculate velocity and time
for(int i = 0; i <= (time/dt) ; i++)
{
tt = dt + tt;
if( tt <= 60)
{
mass = (3000-(40*tt)/g);
thrust = 7000;
}
if ( tt > 60)
{
mass = 3000/g;
thrust = 0;
}
// these are the formulas for velocity and height position our prof gave us
v[i+1] = v[i] - (K/mass)*v[i]*v[i-1] * dt + (thrust/mass - g)*dt;
h[i+1] = v[i+1] * dt + h[i];
}
// for loop to output
for(int i = 0; i <= (time/dt); i++)
{
cout << i << " - " << "Velocity:" << v[i+1] << " Position:" << h[i+1] <<endl;
}
return 0;
}
sample output:
enter time120
enter dt.01
0 - Velocity:-0.298667 Position:-0.00298667
1 - Velocity:-0.597333 Position:-0.00896
2 - Velocity:-0.895999 Position:-0.01792
3 - Velocity:-1.19467 Position:-0.0298666
4 - Velocity:-1.49333 Position:-0.0448
5 - Velocity:-1.792 Position:-0.0627199
6 - Velocity:-2.09066 Position:-0.0836266
7 - Velocity:-2.38933 Position:-0.10752
<...i left out a lot of numbers in the middle to not make this post too long...>
11994 - Velocity:-inf Position:-inf
11995 - Velocity:-inf Position:-inf
11996 - Velocity:-inf Position:-inf
11997 - Velocity:-inf Position:-inf
11998 - Velocity:-inf Position:-inf
11999 - Velocity:-inf Position:-inf
12000 - Velocity:-inf Position:-inf
Program ended with exit code: 0
I have compared with my friends who are getting good results and we can not determine a difference between their code and mine. I have the rest of my program complete and working fine I just cannot figure out why my calculations are wrong
Ignoring the out-of-bounds access to v[-1] when i is zero, there is something wrong with your thrust, mass, or g.
thrust is 7000, mass is 3000 at time = 0. That means thrust/mass is just over 2. With g=32 (really? you are doing rocketry calculations in imperial units?), that means the rocket never has enough thrust to counter gravity, and just sits on the pad.
Edit: That would be reality. Because this is a fairly simple simulation, and doesn't include a "pad", in the model the rocket starts free-falling to the centre of the earth.
You are using v[i-1] but i starts out at 0, therefore this calculation is going to use whatever happens to be at v[-1]. I suggest you initialize i to 1 (and then check all the uses of i to ensure that the correct array elements will be used).
I am not 100% convinced about the forumla, I dont understand why it contains a v[i] and a v[i-1] term. Anyhow, even if correct, in the first iteration (i==0) you are accesing out of bounds of the velocity array: v[i-1]. That is undefined behaviour.
To fix this, either review the formula, does it really contain a v[i-1] term? ..or start the iteration at i=1 (and initialize v[0] and v[1]).
Thank you guys for your help I was able to solve it.
#include <iostream>
using namespace std;
int main()
{
double *v;
double *h;
double g = 32.2;
double K = .008;
double mass;
double t;
double dt;
double tt = 0;
double thrust;
cout << "t \n";
cin >> t;
cout << "dt \n";
cin >> dt;
double a = t/dt;
v = new double[a];
h = new double[a];
v[0] = 0;
h[0] = 0;
for (int i = 0; i <= a; i++)
{
tt = tt+dt;
if( tt == 0)
{
thrust = 7000;
mass = (3000 -40*dt)/g;
v[i+1] = v[i] + ((thrust/mass)-g)*dt;
}
else if( tt > 0 && tt < 60)
{
thrust = 7000;
mass = (3000 - 40 *tt)/g;
v[i+1] = v[i] - ((K/mass)*v[i]*v[i-1] * dt) + ((thrust/mass) - g)*dt;
}
else if (tt > 60)
{
thrust = 0;
mass = 600/g;
v[i+1] = v[i] - ((K/mass)*v[i]*v[i-1] * dt) + ((thrust/mass) - g)*dt;
}
h[i+1] = v[i+1] * dt + h[i];
}
cout << " end results \n";
for(int i = 0; i <= a; i++)
{
cout << i << " v - " << v[i] << " h - " << h[i] <<endl;
}
return 0;
}
New results:
t
120
dt
.01
end results
0 v - 0 h - 0
1 v - 0.429434 h - 0.00429434
2 v - 0.858967 h - 0.012884
3 v - 1.2886 h - 0.02577
4 v - 1.71833 h - 0.0429534
5 v - 2.14817 h - 0.064435
6 v - 2.5781 h - 0.090216
7 v - 3.00813 h - 0.120297
You can see below at 60s where the velocity changes due to no more thrust
5997 - Velocity:890.361
5998 - Velocity:890.392
5999 - Velocity:890.422
6000 - Velocity:886.697
6001 - Velocity:882.985
6002 - Velocity:879.302

I used both the Leibniz and the Wallis formulas for estimating π but am getting wrong output numbers, I couldn't figure out where did I go wrong

#include <cmath> \\not sure if I need cmath
#include <iostream>
using namespace std;
this while loop serves to loop the " enter number of terms to approximate.
while (a != 0)
{
here is the Leibniz formula:
double c = 0.00, d = 0.00;
for (int i = 1; i <= a)
{
if (i % 2 != 0)
{
d = 1 / (1 + 2 * (i - 1));
}
else
{
d = -1 / (1 + 2 * (i - 1));
}
c = c + d;
i = i + 1
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(5);
cout << "The approximation for Leibniz's Formula is " << c << "
using "<< a <<" terms." << endl;
here is the Wallis formula:
double e = 1.00;
for (int u = 0; u<a; u++)
{
e = e * (2 * a / (2 * a - 1))*(2 * a / (2 * a + 1));
}
cout << "The approximation for Wallis' Formula is " << e << " using
"<< a <<" terms." << endl;
cout << endl;
cout << "Enter the number of terms to approximate (or zero to
quit):" << endl;
cin >> a;
}
For a=1 I am getting 1.0000 in the first formula output and 0.00000 in the second formula output
A line like this
d = 1 / (1 + 2 * (i - 1));
will use integer arithmetics to calculate the result, and then convert the int result to a double.
Change it to
d = 1.0 / (1 + 2 * (i - 1));
or even
d = 1.0 / (1.0 + 2.0 * (i - 1.0));
There are many mistakes in this code. First, comments in c++ use //, not \\.
#include <cmath> //not sure if I need cmath
You have to have two semicolons in for statements, even if you don't need loop-expression.
for (int i = 1; i <= a;)
The d will evaluate to 0 for every i that is greater than 1. You are using integer division, when you clearly want floating point division. You have to tell that to the compiler like this.
d = 1.0 / (1 + 2 * (i - 1));
When the left argument of division operator is double compiler will know, that you want to perform a floating point division. If it would be int as in your code, integer division would be performed and result converted to double.
Also in the Wallis formula you misplaced a for u, and also u parameter should start at 1, not 0. Also the integer division problem persists here.
double e = 1.00;
for (int u = 1; u<a; u++)
{
e = e * (2.0 * u / (2.0 * u - 1))*(2.0 * u / (2.0 * u + 1));
}
If you fix this all, the program starts to output valid results.

C++ Simple Calculator (no if, Switch, Case, and its kind)

I tried to make Simple calculator. There are 3 inputs :
number 1
number 2
operators
The operator is selected using number :
1 = '+'
2 = '-'
3 = '*'
4 = '/'
Example :
Number1 = 1, number 2 = 1, operator = 1, then the equation goes 1 + 1 = 2.
I didn't know how to make this equation possible. Any help will be appreciated. Thanks!
*note : not using array or string, not using case, not using switch, not using if, while, for.
Here's my code, but it's not yet completed and I need to change the operator selector.
#include <iostream>
using namespace std;
int main (){
int a, b, c, hasil;
cout << "Masukkan Bilangan 1 : ";
cin >> a;
cout << "Masukkan Bilangan 2 : ";
cin >> b;
cout << "Masukkan Operator ['(0 = +)' , '(1 = -)' , '(2 = *)', '(3 = /)' ] : ";
cin >> c;
hasil = a + (c * -2 + 1 )* b;
cout << "Hasilnya = " << hasil;
}
You can use different functions for the different operators and then select them by using the "c" value as the index to a table of functions.
#include <iostream>
using namespace std;
typedef int (*OperatorFunction)(int a, int b);
static int OperatorPlus(int a, int b)
{
return a + b;
}
static int OperatorMinus(int a, int b)
{
return a - b;
}
static int OperatorMultiply(int a, int b)
{
return a * b;
}
static int OperatorDivide(int a, int b)
{
return a / b;
}
OperatorFunction operators[] = { OperatorPlus, OperatorMinus, OperatorMultiply, OperatorDivide };
int main()
{
int a, b, c, hasil;
cout << "Masukkan Bilangan 1 : ";
cin >> a;
cout << "Masukkan Bilangan 2 : ";
cin >> b;
cout << "Masukkan Operator ['(0 = +)' , '(1 = -)' , '(2 = *)', '(3 = /)' ] : ";
cin >> c;
hasil = operators[c](a, b);
cout << "Hasilnya = " << hasil << "\n";
}
you basically have to calculate all four of them at the same time (warning, "1+0" will then crash, because it will divide by zero during calculation, even if "+" operation was chosen), and filter out the unneeded ones.
To filter out unneeded ones you need to turn c into one of the four value sets:
c==1: [1, 0, 0, 0]
c==2: [0, 1, 0, 0]
c==3: [0, 0, 1, 0]
c==4: [0, 0, 0, 1]
Let's call those inner four values ci, i=1..4
c1 = ((c-2) * (c-3) * (c-4)) / -6;
c2 = ((c-1) * (c-3) * (c-4)) / 2;
c3 = ((c-1) * (c-2) * (c-4)) / -2;
c4 = ((c-1) * (c-2) * (c-3)) / 6;
Then:
result = c1 * (a+b) + c2 * (a-b) + c3 * (a*b) + c4 * (a/b);
This is "pure math" solution, without exploiting C++ bool implicit conversion to 0/1, which would be better in production code, but I think it's a bit "cheating" in this exercise, that's why I'm calculating the 0/1 coefficients without the bool conversions in such complex manner by using the polynomials.
Few updates, to steer away from "pure math" a bit toward something more practical.
unwanted division by zero solution: instead of (a/b) you can calculate (a/(b|(c4-1))) (for c4 being 0 or 1). This will make the divisor equal to -1 whenever the c4 is zero, so it will neutralise "division by zero" for inputs like "a = 1, b = 0, c = 1" (i.e. "1+0"), and the division by zero may happen only when operation "division" is selected and b == 0.
if you will flip ci values from [0, 1] to [0, -1] (just change sign of the fixed constants at the final normalizing division), and everything is int, then you can replace the ci multiplications in final formula with bitwise AND like: result = (c1 & (a+b)) + (c2 & (a-b)) + (c3 & (a*b)) + (c4 & (a/b)); - which will be marginally faster on modern CPU (and considerably faster on historic CPU). {then of course the division by zero fix has to be flipped too => b|(-1-c4)}
note: uh, I aimed for -1 for the division fix, thinking about making whole division going to 0 in unsigned math for most of the inputs, then I figured out this is signed int and overall it makes little sense, but I kept -1 as target value, while anything non-zero will work, even simple 1. And the bitwise AND works only on platforms where negative integers are implemented by two's complement logic, so -1 is full bitmask then (as you didn't specify platform, this may break on some weird ones... the original answer with multiplication will work even on those).
The only thing I can think of with this assignment is to make use of that in C++ there's an implicit conversion between boolean type and integer. To take advantage of it you can do :
#include <iostream>
using namespace std;
int main (){
int a, b, c, hasil;
cout << "Masukkan Bilangan 1 : ";
cin >> a;
cout << "Masukkan Bilangan 2 : ";
cin >> b;
cout << "Masukkan Operator ['(0 = +)' , '(1 = -)' , '(2 = *)', '(3 = /)' ] : ";
cin >> c;
// if your input is a=10, b=5, c=0 :
// a + b == 15
// !c == 1
// 15 * 1 == 15
// a - b == 5
// !(c - 1) == !(0 - 1) == 0
// 5 * 0 == 0
// and so on...
hasil = ((a + b) * !c) + ((a - b) * !(c - 1)) + ((a * b) * !(c - 2)) + ((a / b) * !(c - 3));
cout << "Hasilnya = " << hasil;
}
explanation :
If your c input is 0 and you're doing !c it will return 1 as a int representation of TRUE but then for each other value eg. 3 it will return 0 as a int representation of FALSE. This is then multiplied by the calculated value of each possible operator and return either calculated value or 0 ( because 0 * 99 == 0 ).
Try this online

C++ - for loop not running

Have a very simple code that I'm building in C++. This is my first C++ code so I'm not entirely sure of syntax in some places. However, for the following code, my for loop isn't running at all! I can't see why not... Can anyone spot the problem?
#include <cstdlib>
#include <cmath>
using namespace std;
int main () {
/*
* Use values for wavelength (L) and wave number (k) calculated from linear
* dispersion program
*
*/
//Values to calculate
double u; //Wave velocity: d*phi/dx
double du; //Acceleration of wave: du/dt
int t;
//Temporary values for kn and L (taken from linear dispersion solution)
float L = 88.7927;
float kn = 0.0707624;
Note: I've left out variable declarations to save on space.
/*
* Velocity potential = phi = ((Area * g)/omega) * ((cosh(kn * (h + z)))/sinh(kn * h))*cos(k*x - omega * t);
* Velocity of wave, u = d(phi)/dx;
* Acceleration of wave, du = du/dt;
*/
for (t = 0; t == 5; t++) {
cout << "in this loop" << endl;
u = ((kn * A * g)/omega) * ((cosh(kn * (h + z)))/sinh(kn * h)) * cos(omega * t);
du = (A * g * kn) * ((cosh(kn * (h + z)))/sinh(kn * h)) * sin(omega * t);
cout << "u = " << u << "\tdu = " << du << endl;
}
cout << L << kn << endl;
return 0;
}
I've put the "in this loop" as a test and it doens't enter the loop (compiles fine)..
Thanks in advance for taking a look at this!
t is initialized to 0, t == 5 will always be evaluated to be false, so your for loop will never run.
update
for (t = 0; t == 5; t++) {
to
for (t = 0; t < 5; t++) {
for Statement
Executes a statement repeatedly until the condition becomes false.
for ( init-expression ; cond-expression ; loop-expression )
statement;
Should be:
for (t = 0; t < 5; t++)
The syntax of for loop in C++ is:
for ( init-expression ; cond-expression ; loop-expression )
statement;
The statement executes only while cond-expression is true and in your case it is never true.
That's simple: the condition for your for loop is t == 5 - it only loops as long as t is five, but since you set t = 0 at first, it doesn't loop even once. I think t < 5 is what you want.
Please look at the condition expression for for loop. Hint : You initialized t to 0.

Need floating point precision, GUI gui uses int

I have a flow layout. Inside it I have about 900 tables. Each table is stacked one on top of the other. I have a slider which resizes them and thus causes the flow layout to resize too.
The problem is, the tables should be linearly resizing. Their base size is 200x200. So when scale = 1.0, the w and h of the tables is 200.
I resize by a fixed amount each time making them 4% bigger each time. This means I would expect them to grow by 8 pixels each time. What happens is, every few resizes, the tables grow by 9 pixels. I use doubles everywhere. I have tried rounding, floor and ceil but the problem persists. What could I do so that they always grow by the correct amount?
void LobbyTableManager::changeTableScale( double scale )
{
setTableScale(scale);
}
void LobbyTableManager::setTableScale( double scale )
{
scale += 0.3;
scale *= 2.0;
std::cout << scale << std::endl;
agui::Gui* gotGui = getGui();
float scrollRel = m_vScroll->getRelativeValue();
setScale(scale);
rescaleTables();
resizeFlow();
...
double LobbyTableManager::getTableScale() const
{
return (getInnerWidth() / 700.0) * getScale();
}
void LobbyFilterManager::valueChanged( agui::Slider* source,int val )
{
if(source == m_magnifySlider)
{
DISPATCH_LOBBY_EVENT
{
(*it)->changeTableScale((double)val / source->getRange());
}
}
}
void LobbyTableManager::renderBG( GraphicsContext* g, agui::Rectangle& absRect, agui::Rectangle& childRect )
{
int cx, cy, cw, ch;
g->getClippingRect(cx,cy,cw,ch);
g->setClippingRect(absRect.getX(),absRect.getY(),absRect.getWidth(),absRect.getHeight());
float scale = 0.35f;
int w = m_bgSprite->getWidth() * getTableScale() * scale;
int h = m_bgSprite->getHeight() * getTableScale() * scale;
int numX = ceil(absRect.getWidth() / (float)w) + 2;
int numY = ceil(absRect.getHeight() / (float)h) + 2;
float offsetX = m_activeTables[0]->getLocation().getX() - w;
float offsetY = m_activeTables[0]->getLocation().getY() - h;
int startY = childRect.getY() + 1;
if(moo)
{
std::cout << "TS: " << getTableScale() << " Scr: " << m_vScroll->getValue() << " LOC: " << childRect.getY() << " H: " << h << std::endl;
}
if(moo)
{
std::cout << "S=" << startY << ",";
}
int numAttempts = 0;
while(startY + h < absRect.getY() && numAttempts < 1000)
{
startY += h;
if(moo)
{
std::cout << startY << ",";
}
numAttempts++;
}
if(moo)
{
std::cout << "\n";
moo = false;
}
g->holdDrawing();
for(int i = 0; i < numX; ++i)
{
for(int j = 0; j < numY; ++j)
{
g->drawScaledSprite(m_bgSprite,0,0,m_bgSprite->getWidth(),m_bgSprite->getHeight(),
absRect.getX() + (i * w) + (offsetX),absRect.getY() + (j * h) + startY,w,h,0);
}
}
g->unholdDrawing();
g->setClippingRect(cx,cy,cw,ch);
}
void LobbyTable::rescale( double scale )
{
setScale(scale);
float os = getObjectScale();
double x = m_baseHeight * os;
if((int)(x + 0.5) > (int)x)
{
x++;
}
int oldH = getHeight();
setSize(m_baseWidth * os, floor(x));
...
I added the related code. The slider sends a value changed which is multiplied to get a 4 percent increase (or 8 percent if slider moves 2 values etc...) then the tables are rescaled with this.
The first 3 are when the table size increased by 9, the 4th time it increased by 8px. But the scale factor increases by 0.04 each time.
Why is the 4th time inconsistant?
the pattern seems like 8,8,8,9,9,9,8,8,8,9,9,9...
It increases by 1 pixel more for a few and then decreases by 1 ten increases by 1 etc, thats my issue...
I still don't see the "add 4%" code there (in a form I can understand, anyway), but from your description I think I see the problem: adding 4% twice is not adding 8%. It is adding 8.16% (1.04 * 1.04 == 1.0816). Do that a few more times and you'll start getting 9 pixel jumps. Do it a lot more times and your jumps will get much bigger (they will be 16 pixel jumps when the size gets up to 400x400). Which, IMHO is how I like my scaling to happen.