C++ : Coverting Loop Based Logic - c++

I was assigned a task to create a Program with the following conditions:
Write a C++ program which accepts amount in rupees as input (integer) within
Range from Rs. 100 to Rs. 100000 and then asks the user for particular currency note
preference and display the total number of Currency Notes of Rs. 500, 100, 50, 20, 10, 5 and 1.
The user can be given a maximum of 200 notes of his preferred choice.
For example: when a user enters a number, Rs. 57477 and enters 50 notes as his preferred
choice, the results would be like this.
Currency Note : Number
500 : 74
100 : 4
50 : 200
20 : 3
10 : 1
5 : 1
1 : 2
I created the above program using Modulo Operator and While Loop.
Part of my code is as Follows:
if (preference == 500)
{
notes500 = rupees/500; //This get all the 500 notes
rupees %= 500; //this will find the remaining rupees after deducting all the 500 notes
while(notes500 > 200) //this loop will make sure the obtained 500 notes are not greater that 200
{
notes500 -=1;
rupees +=500; //this re add all the 500 notes that are not needed back to main amount
}
notes100 = rupees/100; //from here we will get all the 100 notes
rupees %= 100; //from here we will substract the amount of Rs 100 notes obtained
//this process will continue to till it reaches 1 rupee notes
notes50 = rupees/50;
rupees %= 50;
notes20 = rupees/20;
rupees %= 20;
notes10 = rupees/10;
rupees %= 10;
notes5 = rupees/5;
rupees %= 5;
notes1 = rupees;
}
This same logic will continue for other preferences.
Now the following restrictions have been applied on the program:
Use of Loops or Recursions is not allowed.
Arrays are also not allowed.
Program should be made using basic knowledge of C++ (e.g. by using decision control structures, C++ operators, e.t.c.)
Now how am i supposed to create the above program without loops?
Help will be highly appreciated!
Thanks,

This code answers the question "how am i supposed to create the above program without loops?" It is achieved by Meta Programming with templates. The recursion constraint is solved as well because the compiler builds out the iterative code. However, I could not solve the preferred note constraint. I process the preferred denomination first but there are many cases like preferred note 1 and rupees total of 201. Looking forward to see the ultimate solution.
#include <iostream>
template <int denom, typename T>
class VegasCashier {
public:
static T result(T a, T b) {
int leftOver = b;
int dcount = 0;
if (denom == 0) // First time in process the favorite
{
leftOver = b;
dcount = b / a;
leftOver %= a;
// From Pete's Comment
if (dcount > 200) { leftOver += a * (dcount - 200); dcount = 200; }
if (dcount > 0)
std::cout << "\tGive " << dcount << " of Denomination "
<< a << " (Favorite) " << std::endl;
}
else if (b != 0 && a != denom) // c is the favorite
{
leftOver = b;
dcount = b / denom;
leftOver %= denom;
// From Pete's Comment
if (dcount > 200) { leftOver += denom * (dcount - 200); dcount = 200; }
if (dcount > 0)
std::cout << "\tGive " << dcount << " of Denomination "
<< denom << std::endl;
}
if (denom == 0) // Special case for desired denomination
return VegasCashier <500, T>::result(a, leftOver); // Start cashout at highest denom
else if (denom == 500)
return VegasCashier<100, T>::result(a, leftOver);
else if (denom == 100)
return VegasCashier<50, T>::result(a, leftOver);
else if (denom == 50)
return VegasCashier<20, T>::result(a, leftOver);
else if (denom == 20)
return VegasCashier<10, T>::result(a, leftOver);
else if (denom == 10)
return VegasCashier<5, T>::result(a, leftOver);
else if (denom == 5)
return VegasCashier<1, T>::result(a, leftOver);
return dcount;
}
};
// This template stops the implementation
template < typename T>
class VegasCashier<1, T> {
public:
static T result(T a, T b) {
if ( b > 0 )
std::cout << "\tGive " << b << " of Denomination " << 1 << std::endl;
return 0;
}
};
// Starting function
template <int denom, typename T>
inline T CasinoResults(T a, T b)
{
std::cout << "\nCashing out " << b << "..." << std::endl;
return VegasCashier<0, T>::result(a, b);
}
int main()
{
CasinoResults<0>(5, 5006);
CasinoResults<0>(500, 99502);
CasinoResults<0>(500, 7519);
CasinoResults<0>(1, 7509); // Fails the Preferred note constraint
}

Related

How can I add limited coins to the coin change problem? (Bottom-up - Dynamic programming)

I am new to dynamic programming (and C++ but I have more experience, some things are still unknown to me). How can I add LIMITED COINS to the coin change problem (see my code below - is a bit messy but I'm still working on it). I have a variable nr[100] that registers the number of coins (also created some conditions in my read_values() ). I don't know where can I use it in my code.
The code considers that we have an INFINITE supply of coins (which I don't want that).
It is made in the bottom-up method (dynamic programming).
My code is inspired from this video: Youtube
#include <iostream>
using namespace std;
int C[100], b[100], n, S, s[100], nr[100], i, condition=0, ok=1;
void read_values() //reads input
{
cin >> n; // coin types
cin >> S; // amount to change
for (i=1; i<=n; i++)
{
cin >> b[i]; //coin value
cin>>nr[i]; //coin amount
if(nr[i]==0)b[i]=0; //if there are no coin amount then the coin is ignored
condition+=b[i]*nr[i]; //tests to see if we have enough coins / amount of coins to create a solution
if(b[i]>S)
{
b[i]=0;
}
}
if(S>condition)
{
cout<<endl;
cout<<"Impossible!";
ok=0;
}
}
void payS()
{
int i, j;
C[0] = 0; // if amount to change is 0 then the solution is 0
for (j=1; j<=S; j++)
{
C[j] = S+1;
for (i=1; i<=n; i++)
{
if (b[i] <= j && 1 + C[j - b[i]] < C[j])
{
C[j] = 1 + C[j - b[i]];
s[j] = b[i];
}
}
}
cout << "Minimum ways to pay the amount: " << C[S] << endl;
}
void solution(int j)
{
if (j > 0)
{
solution(j - s[j]);
cout << s[j] << " ";
}
}
int main()
{
read_values();
if(ok!=0)
{
payS();
cout << "The coins that have been used are: ";
solution(S);
}
}
I'm working under the assumption that you need to generate change for a positive integer value, amount using your nbr table where nbr[n] is the number of coins available of value n. I'm also working under the assumption that nbr[0] is effectively meaningless since it would only represent coins of no value.
Most dynamic programming problems are typically recursing on a binary decision of choosing option A vs option B. Often times one option is "pick this one" and other is "don't pick this one and use the rest of the available set". This problem is really no different.
First, let's solve the recursive dynamic problem without a cache.
I'm going to replace your nbr variable with a data structure called a "cointable". This is used to keep track of both the available set of coins and the set of coins selected for any given solution path:
struct cointable
{
static const int MAX_COIN_VALUE = 100;
int table[MAX_COIN_VALUE+1]; // table[n] maps "coin of value n" to "number of coins availble at amount n"
int number; // number of coins in table
};
cointable::table is effectively the same thing as your nbr array. coinbase::number is the summation of the values in table. It's not used to keep track of available coins, but it is used to keep track of the better solution.
Now we can introduce the recursive solution without a lookup cache.
Each step of the recursion does this:
Look for the highest valuable coin that is in the set of available coins not greater than the target amount being solved for
Recurse on option A: Pick this coin selected from step 1. Now solve (recursively) for the reduced amount using the reduced set of available coins.
Recurse on option B: Don't pick this coin, but instead recurse with the first coin of lesser value than what was found in step 1.
Compare the recursion results of 2 and 3. Pick the one with lesser number of coins used
Here's the code - without using an optimal lookup cache
bool generateChange(int amount, cointable& available, cointable& solution, int maxindex)
{
if ((maxindex == 0) || (amount < 0))
{
return false;
}
if (amount == 0)
{
return true;
}
int bestcoin = 0;
// find the highest available coin that not greater than amount
if (maxindex > amount)
{
maxindex = amount;
}
// assert(maxindex <= cointable::MAX_COIN_VALUE)
for (int i = maxindex; i >= 1; i--)
{
if (available.table[i] > 0)
{
bestcoin = i;
break;
}
}
if (bestcoin == 0)
{
return false; // out of coins
}
// go down two paths - one with picking this coin. Another not picking it
// option 1
// pick this coin (clone available and result)
cointable a1 = available;
cointable r1 = solution;
a1.table[bestcoin]--;
r1.table[bestcoin]++;
r1.number++;
bool result1 = generateChange(amount - bestcoin, a1, r1, bestcoin);
// option2 - don't pick this coin and start looking for solutions with lesser
// coins (not the use of references for a2 and r2 since we haven't changed anything)
cointable& a2 = available;
cointable& r2 = solution;
bool result2 = generateChange(amount, a2, r2, bestcoin - 1);
bool isSolvable = result1 || result2;
if (!isSolvable)
{
return false;
}
// note: solution and r2 are the same object, no need to reassign solution=r2
if (
((result1 && result2) && (r1.number < r2.number))
|| (result2 == false)
)
{
solution = r1;
}
return true;
}
And then a quick demonstration for how to calculate change for 128 cents given a limited amount of coins in the larger denominations: {1:100, 5:20, 10:10, 25:1, 50:1}
int main()
{
cointable available = {}; // zero-init
cointable solution = {}; // zero-init
available.table[1] = 100;
available.table[5] = 20;
available.table[10] = 10;
available.table[25] = 1;
available.table[50] = 1;
int amount = 128;
bool result = generateChange(amount, available, solution, cointable::MAX_COIN_VALUE);
if (result == true)
{
for (int i = 1; i < 100; i++)
{
if (solution.table[i] > 0)
{
std::cout << i << " : " << solution.table[i] << "\n";
}
}
}
else
{
cout << "no solution\n";
}
}
And that should work. And it might be fast enough for most making change for anything under a dollar such that a cache is not warranted. So it's possible we can stop right here and be done.
And I am going to stop right here
I started to work on a solution that introduces a "cache" to avoid redundant recursions. But after benchmarking it and studying how the algorithm finds the best solution quickly, I'm not so sure a cache is warranted. My initial attempt to insert a cache table for both solvable and unsolvable solutions just made the code slower. I'll need to study how to make it work - if it's even warranted at all.
Maybe you wanted us to fix your code, but instead I implemented my own version of solution. Hopefully my own version will be useful somehow for you, at least educationally.
Of course I used Dynamic Programming approach for that.
I keep a vector of possible to compose changes. Each next sums is composed of previous sums by adding several coins of same value.
History of used coins is also kept, this allows us to restore each change as combination of exactly given coins.
After code you can see console output that shows example of composing change 13 out of coins 2x4, 3x3, 5x2, 10x1 (here second number is amount of coins).
Input coins and their amount is given inside coins vector at start of main() function, you can fill this vector with anything you want, for example by taking console user input. Needed to be represented change is given inside variable change.
Don't forget to see Post Scriptum (PS.) after code and console output, it has some more details about algorithm.
Full code below:
Try it online!
#include <cstdint>
#include <vector>
#include <unordered_map>
#include <set>
#include <algorithm>
#include <functional>
#include <iostream>
using u32 = uint32_t;
using u64 = uint64_t;
int main() {
std::vector<std::pair<u32, u32>> const coins =
{{2, 4}, {3, 3}, {5, 2}, {10, 1}};
u32 const change = 13;
std::vector<std::unordered_map<u32, std::pair<u64, std::set<u32>>>>
sums = {{{0, {1, {}}}}};
for (auto [coin_val, coin_cnt]: coins) {
sums.push_back({});
for (auto const & [k, v]: sums.at(sums.size() - 2))
for (size_t icnt = 0; icnt <= coin_cnt; ++icnt) {
auto & [vars, prevs] = sums.back()[k + coin_val * icnt];
vars += v.first;
prevs.insert(icnt);
}
}
std::vector<std::pair<u32, u32>> path;
std::vector<std::vector<std::pair<u32, u32>>> paths;
std::function<bool(u32, u32, u32)> Paths =
[&](u32 sum, u32 depth, u32 limit){
if (sum == 0) {
paths.push_back(path);
std::reverse(paths.back().begin(), paths.back().end());
return paths.size() < limit;
}
auto const coin = coins.at(depth - 1).first;
auto const & [_, prevs] = sums.at(depth).at(sum);
for (auto const cnt: prevs) {
if (cnt > 0)
path.push_back({coin, cnt});
if (!Paths(sum - coin * cnt, depth - 1, limit))
return false;
if (cnt > 0)
path.pop_back();
}
return true;
};
if (!sums.back().count(change)) {
std::cout << "Change " << change
<< " can NOT be represented." << std::endl;
return 0;
}
std::cout << "Change " << change << " can be composed "
<< std::get<0>(sums.back().at(change)) << " different ways." << std::endl;
Paths(change, coins.size(), 20);
std::cout << "First " << paths.size() << " variants:" << std::endl;
for (auto const & path: paths) {
std::cout << change << " = ";
for (auto [coin, cnt]: path)
std::cout << coin << "x" << cnt << " + ";
std::cout << std::endl;
}
}
Output:
Change 13 can be composed 5 different ways.
First 5 variants:
13 = 2x2 + 3x3 +
13 = 2x4 + 5x1 +
13 = 2x1 + 3x2 + 5x1 +
13 = 3x1 + 5x2 +
13 = 3x1 + 10x1 +
PS. As you may have noticed, main Dynamic Programming part of algorithm is very tiny, just following lines:
std::vector<std::unordered_map<u32, std::pair<u64, std::set<u32>>>>
sums = {{{0, {1, {}}}}};
for (auto [coin_val, coin_cnt]: coins) {
sums.push_back({});
for (auto const & [k, v]: sums.at(sums.size() - 2))
for (size_t icnt = 0; icnt <= coin_cnt; ++icnt) {
auto & [vars, prevs] = sums.back()[k + coin_val * icnt];
vars += v.first;
prevs.insert(icnt);
}
}
This part keeps all currently composable sums (changes). Algo starts from money change of 0, then incrementally adds 1-by-1 coin to all possible current changes (sums), thus forming new sums (including this new coin).
Each sum keeps a counter of all possible ways to compose it plus it keeps track of all last coins that lead to this sum. This last coins set allows to do back-tracking in order to restore concrete combinations of coins, not just amount of ways to compute this sum.

Find One to N is Prime optimization

So I was inspired by a recent Youtube video from the Numberphile Channel. This one to be exact. Cut to around the 5 minute mark for the exact question or example that I am referring to.
TLDR; A number is created with all the digits corresponding to 1 to N. Example: 1 to 10 is the number 12,345,678,910. Find out if this number is prime. According to the video, N has been checked up to 1,000,000.
From the code below, I have taken the liberty of starting this process at 1,000,000 and only going to 10,000,000. I'm hoping to increase this to a larger number later.
So my question or the assistance that I need is optimization for this problem. I'm sure each number will still take very long to check but even a minimal percentage of optimization would go a long way.
Edit 1: Optimize which division numbers are used. Ideally this divisionNumber would only be prime numbers.
Here is the code:
#include <iostream>
#include <chrono>
#include <ctime>
namespace
{
int myPow(int x, int p)
{
if (p == 0) return 1;
if (p == 1) return x;
if (p == 2) return x * x;
int tmp = myPow(x, p / 2);
if (p % 2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
int getNumDigits(unsigned int num)
{
int count = 0;
while (num != 0)
{
num /= 10;
++count;
}
return count;
}
unsigned int getDigit(unsigned int num, int position)
{
int digit = num % myPow(10, getNumDigits(num) - (position - 1));
return digit / myPow(10, getNumDigits(num) - position);
}
unsigned int getTotalDigits(int num)
{
unsigned int total = 0;
for (int i = 1; i <= num; i++)
total += getNumDigits(i);
return total;
}
// Returns the 'index'th digit of number created from 1 to num
int getIndexDigit(int num, int index)
{
if (index <= 9)
return index;
for (int i = 10; i <= num; i++)
{
if (getTotalDigits(i) >= index)
return getDigit(i, getNumDigits(i) - (getTotalDigits(i) - index));
}
}
// Can this be optimized?
int floorSqrt(int x)
{
if (x == 0 || x == 1)
return x;
int i = 1, result = 1;
while (result <= x)
{
i++;
result = i * i;
}
return i - 1;
}
void PrintTime(double num, int i)
{
constexpr double SECONDS_IN_HOUR = 3600;
constexpr double SECONDS_IN_MINUTE = 60;
double totalSeconds = num;
int hours = totalSeconds / SECONDS_IN_HOUR;
int minutes = (totalSeconds - (hours * SECONDS_IN_HOUR)) / SECONDS_IN_MINUTE;
int seconds = totalSeconds - (hours * SECONDS_IN_HOUR) - (minutes * SECONDS_IN_MINUTE);
std::cout << "Elapsed time for " << i << ": " << hours << "h, " << minutes << "m, " << seconds << "s\n";
}
}
int main()
{
constexpr unsigned int MAX_NUM_CHECK = 10000000;
for (int i = 1000000; i <= MAX_NUM_CHECK; i++)
{
auto start = std::chrono::system_clock::now();
int digitIndex = 1;
// Simplifying this to move to the next i in the loop early:
// if i % 2 then the last digit is a 0, 2, 4, 6, or 8 and is therefore divisible by 2
// if i % 5 then the last digit is 0 or 5 and is therefore divisible by 5
if (i % 2 == 0 || i % 5 == 0)
{
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
continue;
}
bool isPrime = true;
int divisionNumber = 3;
int floorNum = floorSqrt(i);
while (divisionNumber <= floorNum && isPrime)
{
if (divisionNumber % 5 == 0)
{
divisionNumber += 2;
continue;
}
int number = 0;
int totalDigits = getTotalDigits(i);
// This section does the division necessary to iterate through each digit of the 1 to N number
// Example: Think of dividing 124 into 123456 on paper and how you would iterate through that process
while (digitIndex <= totalDigits)
{
number *= 10;
number += getIndexDigit(i, digitIndex);
number %= divisionNumber;
digitIndex++;
}
if (number == 0)
{
isPrime = false;
break;
}
divisionNumber += 2;
}
if (isPrime)
std::cout << "N = " << i << " is prime." << '\n';
else
std::cout << i << " not prime" << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
PrintTime(elapsed_seconds.count(), i);
}
}
Its nice to see you are working on the same question I pondered few months ago.
Please refer to question posted in Math Stackexchange for better resources.
TL-DR,
The number you are looking for is called SmarandachePrime.
As per your code, it seems you are dividing with every number that is not a multiple of 2,5. To optimize you can actually check for n = 6k+1 ( 𝑘 ∈ ℕ ).
unfortunately, it is still not a better approach with respect to the number you are dealing with.
The better approach is to use primality test screening to find probable prime numbers in the sequence and then check whether they are prime or not. These tests take a less time ~(O(k log3n)) to check whether a number is prime or not, using mathematical fundamentals, compared to division.
there are several libraries that provide functions for primality check.
for python, you can use gmpy2 library, which uses Miller-Rabin Primality test to find probable primes.
I recommend you to further read about different Primality tests here.
I believe you are missing one very important check, and it's the division by 3:
A number can be divided by 3 is the sum of the numbers can be divided by 3, and your number consists of all numbers from 1 to N.
The sum of all numbers from 1 to N equals:
N * (N+1) / 2
This means that, if N or N+1 can be divided by 3, then your number cannot be prime.
So before you do anything, check MOD(N,3) and MOD(N+1,3). If either one of them equals zero, you can't have a prime number.

How do I stop these if else statements from compounding?

I'm trying to write a c++ program that reads input from a text file and assigns grades using a ten point grading scale then prints the results onscreen.
I think my issue may be with the if else statements in the function deriveGrade, rather than incrementing the enum, they seem to be suming up the increments. Any help would be appreciated, thanks.
#include <iostream>
#include <string>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
int deriveGrade(double avarage);
enum letter_grade { A, B, C, D, F };
namespace tenPoint
{
letter_grade deriveGrade(double avarage);
char grade;
}
using namespace tenPoint;
int main()
{
string name;
double average;
ifstream inData; // Is the variable for input data from the file.
inData.open("student_status.txt", ios::in);
while (!inData.eof())
{
getline(inData, name);
inData >> average;
inData.ignore();
grade = ::deriveGrade(average);
cout << name << " " << average << " " << char(grade) << endl;
}
inData.close();
return 0;
}
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70 && average < 80)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60 && average < 70)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else
{
cout << "Invalid entry." << endl;
}
return grade;
}
Input from file:
Doe, John K.
93.2
Andrews, Susan S.
84.7
Monroe, Marylin
75.1
Gaston, Arthur C.
62.8
Harpo, Joanie Y.
42.7
Ginger, Fred T.
95.8
Program output:
Doe, John K. 93.2 A
Andrews, Susan S. 84.7 B
Monroe, Marylin 75.1 D
Gaston, Arthur C. 62.8 G
Harpo, Joanie Y. 42.7 K
Ginger, Fred T. 95.8 î
Press any key to continue . . .
Logic of your program is quite strange, but some common remarks can be given without deepening into your task.
Pay attention, that while you use if... else statements one by one like
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
...
there is no need to check average < 90 in the else branch after average >= 90 found false. So at least code can be shorter:
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else // check here! Invalid interval is for values between 50 and 60?
{
cout << "Invalid entry." << endl;
}
return grade;
}
But this is not significant improvement.... much better to make a formula and use single statement with assignment to grade = ...
UPDATE:
And one more comment. If you know the interval of unacceptable values, check it first (before all other calculations):
int deriveGrade(double average)
{
// check the correctness of argument first
if (average > 50 && average < 60)
{
cout << "Invalid entry." << endl; // notification
return grade; // previous value
// also consider returning special value for error case
}
// calculate value for grade
grade = ...
// return updated value
return grade;
}
section "calculate value for grade" is for you, and while writing this part of code keep in mind that:
ternary operation operation is useful for one special case, e.g. grade = (average >= 90)? 65 : floor(100 - average) / 10;
using global values (like grade) in a function is bad practice as well as making logic based on the assumption that initial value of global variable is correct
The reason is because you are adding to your grade variable without clearing it, so the result of previous operations are carried over in deriveGrade.
My advice is to remove the global char grade; in your namespace, use a local variable in your deriveGrade, and a different local variable in your main.
If you look at your function code, grade will only have 65 added to it (to make an ASCII 'A') if your grade is above 90. Every subsequent addition however, pretends that this addition has happened. If you instead make sure that each else if does not rely on previous if or else if code, then your code should be more correct.
char deriveGrade( double average )
if( average > 90.0 )
{
return 'A';
}
else if( average > 80.0 )
{
return 'B';
}
...
This solution removes even the need to use a grade variable in your deriveGrade
An even better alternative that uses the enum you so nicely created is:
enum letter_grade : char
{
A = 'A', B = 'B', C = 'C', D = 'D', F = 'F'
};
Which allows you through a (char)letter_grade to swap between the enum representation and a char (your deriveGrade would then return a letter_grade instead).

Why my program is not printing string?

My program takes name and age of student and this function should find print the name of youngest,eldest student , and average age.However it does not prints name of youngest student can anyone tell me why?
void check(string *nameStudent, int *ageStudent, int num) {
int i, young = 0, old = 0, sum = 0, mov = 0;
string a, b;
double average;
for (i = 0; i < num; i++){
if (*(ageStudent + mov) < young) {
young = *(ageStudent + mov);
a = *(nameStudent + mov);
}
if (*(ageStudent + mov) > old) {
old = *(ageStudent + mov);
b = *(nameStudent + mov);
}
sum += *(ageStudent + mov);
mov++;
}
average = (double) sum / num;
cout << a << " Is youngest student and " << b << " Is oldest student " << endl << average << " is average age of students";
}
You initialize young to 0. It will only change young and a if there's a student whose age is less than 0.
Instead of hard-coding the initial values of all these variables, get them from the first elements of the arrays.
if (num > 0) {
young = old = sum = *ageStudent;
a = b = *nameStudent;
}
Then you can change your loop to start from 1 instead of 0, since you've already processed the first element of the array.
BTW, there's no need for the mov variable, since it always contains the same thing as i. Use *(ageStudent + i) instead.
void check(string *nameStudent, int *ageStudent, int num) {
int i, young = 0, old = 0, sum = 0;
string a, b;
double average;
if (num > 0) {
young = old = sum = *ageStudent;
a = b = *nameStudent;
}
for (i = 1; i < num; i++){
if (*(ageStudent + i) < young) {
young = *(ageStudent + i);
a = *(nameStudent + i);
}
if (*(ageStudent + i) > old) {
old = *(ageStudent + i);
b = *(nameStudent + i);
}
sum += *(ageStudent + i);
mov++;
}
average = num ? (double) sum / num : 0; // prevent division by 0
cout << a << " Is youngest student and " << b << " Is oldest student " << endl << average << " is average age of students";
}
You're keeping the age of the youngest student in young, but initializing it to 0, so of course none of the students in the list are going to satisfy ageStudent[i] < young. Initialize it to a large value instead. Generally, the largest value that the type in question (int) can take is preferred. If that sounds complicated to you, you can use something like 1000 in this case, as long as none of your students are going to be over a thousand years old.
Set initial young to the maximum integer to force the comparison that is setting a.
Strictly speaking the initial old should be negative maximum (signed) integer to handle all formally possible cases and also the num=0 case should be adressed.
Your problem is the variable young.
You initialize it here to 0:
int i, young = 0, old = 0, sum = 0, mov = 0;
Then you check it here:
if (*(ageStudent + mov) < young) {
But the ageStudent variable will always be greater than 0, as long as nobody of your students is under 0 years old, so the condition will always evaluate to false.
You can solve the problem by setting young to a high number at the beginning of your function.

Loop results in order

I need your help with this problem. What I want to know is how to output of a loop based on the input.
Let's say we have a program that should measure if a triangle is right or not based on the inputs of the user. The input could be something like this:
6 8 10
25 52 60
5 12 13
Using the Pythagoras formula, we can determine if a triangle is or not right
C^2=a^2+b^2
Now, with the numbers provided, the output should be:
right
wrong
right
My question is..how can I do the calculation and check if it's right or not but format the output with the same order as the input?
This is what I've tried :
#include <iostream>
#include <cmath>
using namespace std;
int rightt;
int wrong;
int main()
{
double a = 0, b = 0, c = 0;
double formula = 0;
for (int i = 0; i < 1;)
{
cin >> a >> b >> c;
formula = pow(a, 2) + pow(b, 2);
if (formula == pow(c, 2) && formula != 0)
{
//cout << "Right";
rightt = rightt + 1;
}
if (formula != pow(c, 2) && formula != 0)
{
//cout << "Wrong";
wrong = wrong + 1;
}
if (a == 0 && b == 0 && c == 0)
{
i = 1;
cout << "\n";
while (rightt > 0)
{
cout << "\n" << "Right";
rightt = rightt - 1;
}
while (wrong > 0)
{
cout << "\n" << "Wrong";
wrong = wrong - 1;
}
}
}
system("pause");
}
But my output is not as I desired. The output is first set the right, and then the wrong ones. Thanks, and I hope you understand my problem.
EDIT:
I need to have the output after the 0 0 0 is reached and not before. So If I left the commented sections , the output will be Number-output-Number-output , and what I need is to allow users to enter all numbers and tell the software that he finishes when he enters 0 0 0 , and after that give the output based on the order.
Let's imagine this input :
6 8 10 >> this is right
25 52 60 >> This is wrong
5 12 13 >> This is right
0 0 0 >> This is the values used to end the inputs
Output should be
right
wrong
right
I think that rather than counting the number of right answers and wrong answers, you can STORE all of your answers IN ORDER, in an vector. Once you are done storing all your answers, you can just loop through the answers, and print them out one by one.
If you have not learned about vectors yet, the concept is simple... you have an array like collection of data. "push_back" always tacks the data to the end of the collection of data. So if your first answer was wrong, then right, then right, first you would push_back(wrong)...resulting in a collection of [wrong]. Then you would push_back(right) resulting in a collection of [wrong, right]. Again you would push_back(right) so your final vector would be a collection in the order of [wrong, right, right]
Now you just need to loop through your collection to print out the data. The "iter" is a pointer to each spot in your list. To get the "contents of each spot" you dereference, by saying (*iter) which will provide the string result values.
#include <iostream>
#include <cmath>
#include <vector>
#include <string>
using namespace std;
int main()
{
double a = 0, b = 0, c = 0;
double formula = 0;
int numberOfResults = 0;
int currentIndex = 0;
vector<string> answers;
for (int i = 0; i < 1;)
{
cout << "Enter the number of attempts: " << "\n";
cin >> numberOfResults;
string results[numberOfResults];
cout << "Enter a b and c" << "\n";
cin >> a >> b >> c;
formula = pow(a, 2) + pow(b, 2);
if (formula == pow(c, 2) && formula != 0)
{
results[currentIndex] = "Right";
answers.push_back("Right");
}
if (formula != pow(c, 2) && formula != 0)
{
results[currentIndex] = "Wrong";
answers.push_back("Wrong");
}
if (a == 0 && b == 0 && c == 0 || currentIndex == numberOfResults-1)
{
for (int j = 0; j < numberOfResults; j++){
cout << "\n" << results[j];
}
for(auto iter = answers.begin(); iter != answers.end(); ++iter){
cout << "\n" << (*iter);
}
return 0;
}
}
system("pause");
}