Do something with last value in loop in C++ - c++

Lets say I have a loop and an if statement in the loop. If i is true in the loop it prints with a space or comma and it does this for the rest of the i's that are true, but I want to do something else with the last i that that is true. How would I do this?
for (i = 0; i <= somenum; i++){
if (i % 2 != 0)
{
cout << i;
}
}
I want to figure out the last value that follows the condition and do something else with it.

There are really three ways to approach this problem. To illustrate this I'm going to use the example that you want to have a for loop print the numbers 0-9 separated by comas and spaces.
(1) Make the loop do the same thing every time, but modify your result after the loop. An example of how to do this is:
#include <iostream>
#include <sstream>
int main(int, char**) {
std::stringstream ss;
for (int i = 0; i < 10; ++i) {
ss << i << ", ";
}
ss.seekp(-2, std::ios_base::end);
ss << '\0';
std::cout << ss.str();
}
(2) Exit your loop before your last iteration and handle the last case outside the loop:
#include <iostream>
int main(int, char**) {
for (int i = 0; i < 9; ++i) {
std::cout << i << ", ";
}
std::cout << 9;
}
(3) Special case your last iteration in the loop. This option is bad, and you probably only want to do this in cases where you can't make 1 or 2 apply. The reason this is bad is because your conditional in the loop will be executed every time, and it will only be true once.
#include <iostream>
int main(int, char**) {
std::stringstream ss;
for (int i = 0; i < 10; ++i) {
if (i == 9) {
std::cout << i;
break;
}
std::cout << i << ", ";
}
}
In most cases option 2 is your best bet from a performance standpoint, but sometimes option 1 provides cleaner code which can be valuable.

If you have a "sequence" then you have no way of knowing if an element is the last or not. If you're using a for loop with a known length then it's trivial:
for(size_t i = 0; i < length; i++ ) {
if( i == length - 1 ) {
// do something for the last element
}
}
Reading your question, it sounds like you want to print a comma between elements but obviously don't want a trailing comma. The solution is not to test on the last, but to actually test on the first, like so:
bool isFirst = true;
iterator it;
for( it = sequence.begin(); it != sequence.end(); it++ ) {
if( !isFirst ) print(", ");
isFirst = false;
print( element );
}

Related

Function to randomly convert chars toupper case

Am revisiting an exercise from an online course where we created a 'Whale translator' which checks through each character that the user inputs and extracts / returns only the vowels.
I thought it would be fun to have the returned values capitalized at random so the whole thing would feel a little like Dory speaking whale (finding Nemo) so I created a function to take each character and convert them to caps based on whether a random number is odd or even. Thing is that I cannot get the program to acknowledge or use my function. Runs fine otherwise.
Could somebody give me a pointer as to where I'm going wrong?
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
char converter(char);
int main() {
std::cout << "WeELCooOmE ToOOoO the WHaALe translaAtoOor \n";
std::cout << "\n PlEaAsE EnntEer yoOur text tOo beEE trAanslaAateEd \n\n";
std::string input;
std::getline(std::cin, input);
std::cout << "\n";
std::vector<char> vowels;
vowels.push_back('a');
vowels.push_back('e');
vowels.push_back('i');
vowels.push_back('o');
vowels.push_back('u');
std::vector<char> whale_talk;
for (int i = 0; i < input.size(); i++) {
for (int j = 0; j < vowels.size(); j++) {
if (input[i] == vowels[j]) {
whale_talk.push_back(input[i]);
}
}
}
std::cout << "HeEre iS yOoUr translaAtiOn..\n\n";
for (int k = 0; k < whale_talk.size(); k++) {
converter(whale_talk[k]);
std::cout << whale_talk[k];
}
std::cout << "\n";
}
char converter(char x) { //function to convert characters toupper based on random number generation.
int rando = rand() % 100;
if (rando % 2 == 0) {
x = toupper(x);
return x;
}
else {
return x;
}
}
You converter function is returning the modified char but you never use the returned value in the for loop:
converter(whale_talk[k]);
You need to do:
whale_talk[k] = converter(whale_talk[k]);
Here's a demo.
Alternatively, you can leave the call site as it is, but pass the char to be converted by reference, like this:
void converter(char &x) { // << pass by reference
// and modify x, but don't return it
}
Here's a demo.
You ignore the retun value of converter, so it has no effect.
This
converter(whale_talk[k]);
std::cout << whale_talk[k];
should be
std::cout << converter(whale_talk[k]);

Recursive generation of all “words” of arbitrary length

I have a working function that generates all possible “words” of a specific length, i.e.
AAAAA
BAAAA
CAAAA
...
ZZZZX
ZZZZY
ZZZZZ
I want to generalize this function to work for arbitrary lengths.
In the compilable C++ code below
iterative_generation() is the working function and
recursive_generation() is the WIP replacement.
Keep in mind that the output of the two functions not only differs slightly, but is also mirrored (which doesn’t really make a difference for my implementation).
#include <iostream>
using namespace std;
const int alfLen = 26; // alphabet length
const int strLen = 5; // string length
char word[strLen]; // the word that we generate using either of the
// functions
void iterative_generation() { // all loops in this function are
for (int f=0; f<alfLen; f++) { // essentially the same
word[0] = f+'A';
for (int g=0; g<alfLen; g++) {
word[1] = g+'A';
for (int h=0; h<alfLen; h++) {
word[2] = h+'A';
for (int i=0; i<alfLen; i++) {
word[3] = i+'A';
for (int j=0; j<alfLen; j++) {
word[4] = j+'A';
cout << word << endl;
}
}
}
}
}
}
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++) { // the i variable should be accessible
if (0 < a) { // in every recursion of the function
recursive_generation(a-1); // will run for a == 0
}
word[a] = i+'A';
cout << word << endl;
}
}
int main() {
for (int i=0; i<strLen; i++) {
word[i] = 'A';
}
// uncomment the function you want to run
//recursive_generation(strLen-1); // this produces duplicate words
//iterative_generation(); // this yields is the desired result
}
I think the problem might be that I use the same i variable in all the recursions. In the iterative function every for loop has its own variable.
What the exact consequences of this are, I can’t say, but the recursive function sometimes produces duplicate words (e.g. ZAAAA shows up twice in a row, and **AAA gets generated twice).
Can you help me change the recursive function so that its result is the same as that of the iterative function?
EDIT
I realised I only had to print the results of the innermost function. Here’s what I changed it to:
#include <iostream>
using namespace std;
const int alfLen = 26;
const int strLen = 5;
char word[strLen];
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++) {
word[a] = i+'A';
if (0 < a) {
recursive_generation(a-1);
}
if (a == 0) {
cout << word << endl;
}
}
}
int main() {
for (int i=0; i<strLen; i++) {
word[i] = 'A';
}
recursive_generation(strLen-1);
}
It turns out you don't need recursion after all to generalize your algorithm to words of arbitrary length.
All you need to do is "count" through the possible words. Given an arbitrary word, how would you go to the next word?
Remember how counting works for natural numbers. If you want to go from 123999 to its successor 124000, you replace the trailing nines with zeros and then increment the next digit:
123999
|
123990
|
123900
|
123000
|
124000
Note how we treated a number as a string of digits from 0 to 9. We can use exactly the same idea for strings over other alphabets, for example the alphabet of characters from A to Z:
ABCZZZ
|
ABCZZA
|
ABCZAA
|
ABCAAA
|
ABDAAA
All we did was replace the trailing Zs with As and then increment the next character. Nothing magic.
I suggest you now go implement this idea yourself in C++. For comparison, here is my solution:
#include <iostream>
#include <string>
void generate_words(char first, char last, int n)
{
std::string word(n, first);
while (true)
{
std::cout << word << '\n';
std::string::reverse_iterator it = word.rbegin();
while (*it == last)
{
*it = first;
++it;
if (it == word.rend()) return;
}
++*it;
}
}
int main()
{
generate_words('A', 'Z', 5);
}
If you want to count from left to right instead (as your example seems to suggest), simply replace reverse_iterator with iterator, rbegin with begin and rend with end.
You recursive solution have 2 errors:
If you need to print in alphabetic order,'a' need to go from 0 up, not the other way around
You only need to print at the last level, otherwise you have duplicates
void recursive_generation(int a) {
for (int i=0; i<alfLen; i++)
{ // the i variable should be accessible
word[a] = i+'A';
if (a<strLen-1)
// in every recursion of the function
recursive_generation(a+1); // will run for a == 0
else
cout << word << '\n';
}
}
As I am inspired from #fredoverflow 's answer, I created the following code which can do the same thing at a higher speed relatively.
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
void printAllPossibleWordsOfLength(char firstChar, char lastChar, int length) {
char *word = new char[length];
memset(word, firstChar, length);
char *lastWord = new char[length];
memset(lastWord, lastChar, length);
int count = 0;
std::cout << word << " -> " << lastWord << std::endl;
while(true) {
std::cout << word << std::endl;
count += 1;
if(memcmp(word, lastWord, length) == 0) {
break;
}
if(word[length - 1] != lastChar) {
word[length - 1] += 1;
} else {
for(int i=1; i<length; i++) {
int index = length - i - 1;
if(word[index] != lastChar) {
word[index] += 1;
memset(word+index+1, firstChar, length - index - 1);
break;
}
}
}
}
std::cout << "count: " << count << std::endl;
delete[] word;
delete[] lastWord;
}
int main(int argc, char* argv[]) {
int length;
if(argc > 1) {
length = std::atoi(argv[1]);
if(length == 0) {
std::cout << "Please enter a valid length (i.e., greater than zero)" << std::endl;
return 1;
}
} else {
std::cout << "Usage: go <length>" << std::endl;
return 1;
}
clock_t t = clock();
printAllPossibleWordsOfLength('A', 'Z', length);
t = clock() - t;
std:: cout << "Duration: " << t << " clicks (" << ((float)t)/CLOCKS_PER_SEC << " seconds)" << std::endl;
return 0;
}

Vector equilibrium point(s) function in C++

So I wanted to clean the rust off my C++ skills and thought I'd start with something fairly simple. An equilibrium point in a vector A of size N is a point K, such that: A[0] + A[1] + ... + A[K−1] = A[K+1] + ... + A[N−2] + A[N−1]. The rationale behind the function algorithm is simple: Check each consecutive element of the vector and compare the sum of the elements before said element with the sum of the elements after it and if they are equal, output the index of that element. While it sounds simple (and I imagine that it is) it turned out to be harder to implement in reality. Here's what the code looks like:
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
void EquilibriumPoint(std::vector<int> &A);
void VectorPrint(std::vector<int> &V);
void main()
{
int input;
std::vector<int> Vect1;
cout << "Input the vector elements" << endl;
while (cin >> input)
Vect1.push_back(input);
VectorPrint(Vect1);
EquilibriumPoint(Vect1);
}
void EquilibriumPoint(std::vector<int> &A)
{
for (int it = 0; it != A.size(); ++it)
{
int lowersum = 0;
int uppersum = 0;
for (int beg = 0; beg != it; ++beg) lowersum += A[beg];
for (int end = it + 1; end != A.size(); ++end) uppersum += A[end];
if (uppersum == lowersum) cout << it;
}
}
void VectorPrint(std::vector<int> &V)
{
for (int i = 0; i != V.size(); ++i)
cout << V[i] << endl;
}
As you can see I threw in a print function also for good measure. The problem is that the program doesn't seem to execute the EquilibriumPoint function. There must be a problem with the logic of the implementation but I can't find it. Do you guys have any suggestions?
cin >> input
always returns true for you - so IMHO you have an endless loop. You need to stop collecting elements at some point, for instance
int input = 1
while (input)
{
cin >> input;
Vect1.push_back(input);
}
Will accept all elements that are not zero, when zero arrives, it will end the vector and run your function.
Or you can first input the number of elements (if you want to include zeros), example:
int count;
cin >> count
for (int i = 0; i < count; ++i)
{
cin >> input;
Vect1.push_back(input);
}
I didn't check the rest of the code, though. One problem at a time.

Check something once in nested loop / loop-invariants

whats the smartest way to do something only once per iteration in a nested loop? i can't pull out the invariant part because the outer loop is very complex.
Here is my C++ example:
void foo::bar() {
if(oldCycle == tree.cycle) {
doSomething();
oldCycle++;
}
}
this method is called very often until tree.cycle is incremented. oldCycle is a private member variable of foo
claas foo {
public: ...
private:
int oldCycle;
};
Does the compiler optimize this code or will the if check run every iteration?
Edit: Here like requested the code with the loops:
the first loop is in the mexFunction() method, the algorithm is started in matlab and calls the mexFunction.
void mexFunction(...) {
for( tree.cycle = 0; tree.cycle<maxIt; tree.cycle++ ) {
foo->startfoo();
}
}
and here is the other loop:
void foo::startfoo() {
for(tree.cur_it = 0; tree.cur_it <=39; tree.cur_it++ ) {
bar();
}
}
For a general condition, you can't really optimize this out, since you would need to remove the special case from the collection one way or another.
However, for the special case of treating the first element specially (e.g. when printing a range with de­li­mit­ers as "1, 2, 3"), you can use Knuth's "loop-and-a-half":
Naive loop:
for (unsigned int i = 0; i != values.size(); ++i)
{
if (i != 0) { std::cout << ", "; }
std::cout << values[i];
}
Loop-and-a-half:
if (!values.empty())
{
for (unsigned int i = 0; ; )
{
std::cout << values[i];
++i;
if (i == values.size()) { break; }
std::cout << ", ";
}
}
The latter construction is more involved, but saves you the mostly false check i != 0.
That said, it's quite plausible that a good compiler will do the partial unrolling even if you write the code the naive way.
For simple cases I prefer this method.
if ( ! values.empty())
{
std::cout << values[0];
for (size_t z = 1; z < values.size(); z++)
{
std::cout << ", " << values[z];
}
}

Counting occurrences in a vector

This program reads strings of numbers from a txt file, converts them to integers, stores them in a vector, and then tries to output them in an organized fashion like so....
If txt file says:
7 5 5 7 3 117 5
The program outputs:
3
5 3
7 2
117
so if the number occurs more than once it outputs how many times that happens. Here is the code so far.
#include "std_lib_facilities.h"
int str_to_int(string& s)
{
stringstream ss(s);
int num;
ss >> num;
return num;
}
int main()
{
cout << "Enter file name.\n";
string file;
cin >> file;
ifstream f(file.c_str(), ios::in);
string num;
vector<int> numbers;
while(f>>num)
{
int number = str_to_int(num);
numbers.push_back(number);
}
sort(numbers.begin(), numbers.end());
for(int i = 0; i < numbers.size(); ++i)
{
if(i = 0 && numbers[i]!= numbers[i+1]) cout << numbers[i] << endl;
if(i!=0 && numbers[i]!= numbers[i-1])
{
cout << numbers[i] << '\t' << counter << endl;
counter = 0;
}
else ++counter;
}
}
Edit: Program is getting stuck. Looking for an infinite loop right now.
You could use a map of numbers to counters:
typedef map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
... then iterate over the map to print results.
EDIT:
As suggested by lazypython: if you have the TR1 extensions [wikipedia.org] available, unordered_map should have better performance...
typedef std::tr1::unordered_map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
How about using a map, where the key is the number you're tracking and the value is the number of occurrences?
If you must use a vector, you've already got it sorted. So just keep track of the number you previously saw. If it is the same as the current number, increment the counter. Every time the number changes: print out the current number and the count, reset the count, set the last_seen number to the new number.
Using a map is the practical solution. What you should do is to solve this problem :)
This is called frequency counter. So, you have a sorted vector and all what you have to do is to count successive equal numbers. In other words, you have to check each number with its successor.
for(size_t i = 0; i < numbers.size(); i++)
{
size_t count = 1;
size_t limit = numbers.size() - 1;
while(i < limit && numbers[i] == numbers[i+1])
{
count++;
i++;
}
std::cout << numbers[i] << "\t" << count << std::endl;
}
This program reads strings of numbers
from a txt file, converts them to
integers, stores them in a vector, and
then tries to output them in an
organized fashion like so....(emphasis added)
What is the point of this storage step? If you are reading the numbers from a file, then you already have them in order, ready to be processed (counted) one at time, as you encounter them.
However, I would need a way for it to know when it sees a new number.
I advise you to have a look at std::set or std::map. I expect either of these containers would do what you're looking for.
Std::count() fits the bill nicely.
std::vector<int>::const_iterator cur = numbers.begin();
std::vector<int>::const_iterator last = numbers.end();
while (cur != last) {
unsigned cnt = std::count(cur, last, *cur);
std::cout << *cur;
if (cnt != 1) {
std::cout << " " << c;
}
std::cout << std::endl;
int saved = *cur;
while (*cur == saved) {
++cur;
}
}
Of course there are a bunch of other algorithms out there that will do the same job. Play with things like std::equal_range() in conjunction with std::distance() will do the job just as nicely.
That was fun:
#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
struct IncrementMap
{
IncrementMap(std::map<int,int>& m): m_map(m) {}
void operator()(int val) const
{
++m_map[val];
}
std::map<int,int>& m_map;
};
struct SpecialPrint
{
SpecialPrint(std::ostream& s): m_str(s) {}
void operator()(std::map<int,int>::value_type const& value) const
{
m_str << value.first;
if (value.second != 1)
{
m_str << "\t" << value.second;
}
m_str << "\n";
}
std::ostream& m_str;
};
int main()
{
std::fstream x("Plop");
std::map<int,int> data;
std::for_each( std::istream_iterator<int>(x),
std::istream_iterator<int>(),
IncrementMap(data)
);
std::for_each( data.begin(),
data.end(),
SpecialPrint(std::cout)
);
}