Decreasing value in vectors with SFML - c++

I created 5 numbers using vector with SFML, but I want the second one to fall one by one at intervals of 1 second. But, they first three falling as one by one. I don't understand why something like this is happening. Can you help me?
if (second == 1)
{
random.at(2)-=1;
cout << random[2] << endl;
text.setString(to_string(random[2]));
text.setPosition(numbers[2].getPosition().x, numbers[2].getPosition().y);
numbers.push_back(text);
numbers.erase(numbers.begin() + 2);
clock.restart();
}
The program gif
Full code

I'll give you a hand.
Here's what's happening:
You create 5 numbers in the random array. You may not have noticed it, but they are numbered 0 to 4 (SFML is sitting on C++, and then it means that arrays starts at zero here).
Every second, you update the number stocked in the 3rd place of your random array.
Then it goes wrong: instead of updating the corresponding number in the numbers array, you cycle it with push_back and erase.
Understand me here: push_back create a new element at the end of the vector, while erase removes an element from the vector and then "sort out things" so there's not number gap in the index of the vector.
Effectively, you're handling random right, but when you try to update number you cycle through it. Like this:
seconds: 1 2 3 4 5 6
array content: 0 0 0 0 0 0
(vertical) 1 1 1 1 1 1
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9
I'm not sure how clear I'm making this, but if you look at the array content, you'll see that by erasing and creating a new value at the end, you're cycling through the positions [2-4] of the array. That's why in your gif not all numbers are updated wrong, only 3 of them.
The obvious solutions would be to stop erasing and pushing back in the numbers array. You can update it the same way you updated the random array. It'll be fine.
Like this:
if (second == 1)
{
random.at(2)-=1;
cout << random[2] << endl;
numbers[2].setString(to_string(random[2]));
clock.restart();
}
Have fun.

Related

Populating a vector with numbers and conditions in C++

Working on a business class assignment where we're using Excel to solve a problem with the following setup and conditions, but I wanted to find solutions by writing some code in C++ which is what I'm most familiar from some school courses.
We have 4 stores where we need to invest 10 million dollars. The main conditions are:
It is necessary to invest at least 1mil per store.
The investments in the 4 stores must total 10 million.
Following the rules above, the most one can invest in a single store is 7 million
Each store has its own unique return of investment percentages based off the amount of money invested per store.
In other words, there is a large number of combinations that can be obtained by investing in each store. Repetition of numbers does not matter as long as the total is 10 per combination, but the order of the numbers does matter.
If my math is right, the total number of combinations is 7^4 = 2401, but the number of working solutions
is lesser due to the condition that each combination must equal 10 as a sum.
What I'm trying to do in C++ is use loops to populate each row with 4 numbers such that their sum equals 10 (millions), for example:
7 1 1 1
1 7 1 1
1 1 7 1
1 1 1 7
6 2 1 1
6 1 2 1
6 1 1 2
5 3 1 1
5 1 3 1
5 1 1 3
5 1 2 2
5 2 1 2
5 2 2 1
I'd appreciate advice on how to tackle this. Still not quite sure if using loops is a good idea whilst using an array (2D Array/Vector perhaps?) I've a vague idea that maybe recursive functions would facilitate a solution.
Thanks for taking some time to read, I appreciate any and all advice for coming up with solutions.
Edit:
Here's some code I worked on to just get 50 rows of numbers randomized. Still have to implement the conditions where valid row combinations must be the sum total of 10 between the 4;
int main(){
const int rows = 50;
int values[rows][4];
for (int i = 0; i < 50; i++) {
for (int j = 0; j <= 3; j++){
values[i][j]= (rand() % 7 + 1);
cout << values[i][j] << " ";
}
cout << endl;
}
}
You can calculate this recursively. For each level, you have:
A target sum
The number of elements in that level
The minimum value each individual element can have
First, we determine our return type. What's your final output? Looks like a vector of vectors to me. So our recursive function will return a the same.
Second, we determine the result of our degenerate case (at the "bottom" of the recursion), when the number of elements in this level is 1.
std::vector<std::vector<std::size_t>> recursive_combinations(std::size_t sum, std::size_t min_val, std::size_t num_elements)
{
std::vector<std::vector<std::size_t>> result {};
if (num_elements == 1)
{
result.push_back(std::vector<std::size_t>{sum});
return result;
}
...non-degenerate case goes here...
return result;
}
Next, we determine what happens when this level has more than 1 element in it. Split the sum into all possible pairs of the "first" element and the "remaining" group. e.g., if we have a target sum of 5, 3 num_elements, and a min_val of 1, we'd generate the pairs {1,4}, {2,3}, and {3,2}, where the first number in each pair is for the first element, and the second number in each pair is the remaining sum left over for the remaining group.
Recursively call the recursive_combinations function using this second number as the new sum, and num_elements - 1 as the new num_elements to find the vector of vectors for the remaining group, and for each vector in the return vector, append the first element from the above set.

Unexpected vector behavior using set intersection

I am trying to compare a 2 dimensional vector against another 2 dimensional vector.
vector<vector<int> >::iterator rowit1;
for(rowit1 = aboveaveperms.begin(); rowit1 != aboveaveperms.end();rowit1++)
{
vector<vector<int> >::iterator row2it;
int s = 0;
for(row2it = afterave.begin(); row2it != afterave.end();row2it++)
{
vector<int> matches (9);
vector<int>::iterator itset;
itset = set_intersection(rowit1->begin(),rowit1->end(),row2it->begin() + 1,row2it->end(),matches.begin());
matches.resize(itset-matches.begin());
s = matches.size();
matches.erase(matches.begin(),matches.end()); // my attempt at trying to correct it
}
}
In the second loop on the first pass matches is created correctly holding 9 zeros. But once it begins the second loop, as soon as it hits the curly bracket, it comes out with 101 million instead of 9. Once it actually hits it's declaration it goes back to the 9 which is proper. I have noticed while debugging that it is holding all of the 2 dimensional vector I am checking against before the declaration corrects it to only holding 9 ints.
idzireit
APPENDUM:
As it has been pointed out I forgot to ask my question. The above code does work as I want the number of matches (between 5 and 9) but because of the erratic behaviour of the vector will it cause a memory leak or sigseg if the other vectors get too big?
Also, as whozcraig asked, I have row2it->begin() + 1 because the first element is the game number which is much bigger then the rest of the numbers. The rest of the numbers are sorted though.
Example of what I am trying to do is as follows:
perm vector 1
1 3 5 6 7
compare against 4 vectors and count for number of matches in each
5 8 9 10 11
3 7 11 14 18
1 5 6 7 8
so in running through the loop the first match should be 1 second should be 2 and third should be 4. Hope this helps to clarify what I am trying to do.
ADDENDUM 2:
Now that I have my windoze machine up and running and have reinstalled qt creator on it I have run the above code and works fine on windows. I do not get the 101 million elements like I did when running under ubuntu. Why does it work correctly on windoze and not ubuntu ?
idzireit
Firstly, according to https://en.cppreference.com/w/cpp/algorithm/set_intersection, both vectors be intersected must be sorted.
Secondly, you set an initial size of 9 to vector matches, but if the number of intersected elements is greater than 9, then std::set_intersection is writing out of bounds of matches, which may cause an undefined behaviour.
You can execute your code using a memory analyzer as Valgrind in order to detect a possible memory leak. You could use std::back_inserter to avoid this problem:
#include <iterator> // std::back_inserter
vector<int> matches;
std::back_insert_iterator<std::vector<int> > itset(matches);
itset = set_intersection(rowit1->begin(),rowit1->end(),row2it->begin() + 1,row2it->end(), std::back_inserter(matches));

cant find error in my applied logic

question:
Given an array of elements of length N, ranging from 0 to N-1, your task is to write a program that rearranges the elements of the array. All elements may not be present in the array, if element is not present then there will be -1 present in the array. Rearrange the array such that A[i] = i and if i is not present, display -1 at that place.
my code:
#include <iostream>
using namespace std;
int main()
{
long int n;
cin>>n;
long int a[n];
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for (int i=1;i<=n;i++)
{
while(a[i]==i&&a[i]==-1)
{
int temp=a[i];
a[i]=a[temp];
a[temp]=temp;
}
}
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
return 1;
}
output:
6
-1 4 2 3 -1 5
-1 4 2 3 -1 5
can anyone please help me in finding out my error in the logic apllied?
Thanks in advance.
for(int i=1;i<=n;i++)
Wrong, elements go from 0 to N-1, not 1 to N
while(a[i]==i&&a[i]==-1)
This will never happen, you are asking for a[i] to be equal to both i and -1, which means asking i to be equal to -1, which won´t happen in your loop.
For a simple answer, you need to sort the list and then process that. For an efficient answer, you will want to make a boolean array of size N and then iterate the array and check which values are present. Then you iterate the boolean array to write the number when it is present or -1 when its not.
The easiest way to solve this kind of problem is to get a pack of playing cards and lay them out on your desk, and then solve the problem by hand. Write down every step you take, and then write code that performs those steps.
Because cards start at 1, rather than 0, I use the 10 as a 0. Use the joker to indicate an empty space (-1 in your problem description).
Take five cards and lay them out in six spaces
2 10 4 J 3 1
Starting with position 0. Pull the 2 out and replace it with -1, so your cards look like this:
J 10 4 J 3 1
And you're holding the 2 in your hand.
Then, go to position 2, pull out the 4 and put the 2 there. Now you have
J 10 2 J 3 1
And you're holding 4 in your hand. Go to position 4 (where the 3 is). Replace the 3 with 4, you have:
J 10 2 J 4 1
And 3 in the hand. Position 3 contains a joker. So you put the 3 in that position and put the joker aside. You now have:
J 10 2 3 4 1
So you move to the next position, 1. Pick up the 10 and put a joker in that spot. The 10 goes to position 0, so take the joker from position 0, place the 10 there, and you have:
10 J 2 3 4 1
You don't have anything in your hand now, so you move forward, checking positions 2, 3, and 4, which already have a[i] == i. But position 5 contains a 1. So you pick it up, place a joker in that position, and then replacing the joker in position 1 with the value 1 that you just pulled from position 5. Your array now looks like this:
10 1 2 3 4 J
And you're done.
Do that a few times with different arrangements of cards, writing down the steps you took. After a few practice runs, you should be able to write down the general algorithm for solving the problem. Then you write a program to implement that solution.
The idea of this kind of problem is to help you develop these problem solving steps. Over time, you'll be able to go straight to code with the simpler problems, but you'll find that building a physical model is very useful with more complex problems. If you step away from the computer, you're not tempted to start programming before you've solved the problem. You'll find that doing things way will save you a lot of frustration.

Recursion Part explanation

I am stuck with merge sort recursion part.
void divide(int arr[], int low, int high) {
int mid;
if(low < high) {
mid = (low + high)/2;
divide (arr, low, mid);
divide (arr, mid+1, high);
numbersSort (arr, low, mid, high);
}
}
Assume array size is four. first time it will be called by divide(arr,0,4) and then divide(arr,0,2), divide(arr,0,1), divide(arr,0,0) respectively.
But one word to say when it comes to divide(arr,0,0) it should be stop in low < high condition. Then how is it work for divide and numberSort() function?
I have an another query to ask, when does numberSort() work ?
if you can give my line by line by simulation of above code, I will be grateful to you . I am in serious panic about it.
Advance thanks.
Then how is it work for divide and numberSort() function?
Execution in a given function doesn't stop when you call another function, it just pauses until that function returns. So imagine you're currently executing divide(arr,0,1). low is still less than high, so you enter the condition and call divide(arr,0,0), which does whatever it needs to do (hint: try not to worry about what it does just now), and then you call divide(arr,1,1) which again does it's thing and returns. Next, you call numbersSort(arr,0,0,1), which recombines the two sections of the array, and the result is that the array is sorted from index 0 to index 1.
Good so far? Okay, well, next you just return. And it happens that the divide(arr,0,1) call we just talked about was invoked by a divide(arr,0,2) call, so when divide(arr,0,1) returns, execution of divide(arr,0,2) continues from the point just after the divide(arr,0,1). So the next thing to happen will be a divide(arr,2,2) call, right? 2 is not less than 2, so that just returns right away as well, and then you hit the numbersSort(arr,0,1,2), which combines the two sections of the array (i.e. 0 through 1, and 2 through 2) into a properly sorted array from 0 to 2. Now the array is sorted from index 0 through index 2.
But, of course, that divide(arr,0,2) was called in the context of a divide(arr,0,4) call, so when the divide(arr,0,2) returns the next thing that happens is divide(arr,3,4). Let's assume that that does the right thing and sorts the array from index 3 to index 4. And then you get to the numbersSort(arr,0,2,4), which combines the two parts of the array and returns to whatever function called divide(arr,0,4).
It can definitely be tough to get your head around recursion at first. Keep at it -- it'll click eventually. If you can step through the code for a small-ish example in a debugger, that might help you see what's going on. Also, working through the code on paper can help. Try not to get bogged down with understanding how it works at every level all at once, but instead look for what happens at a single level and trust that calls to any functions (even recursive calls) just do the right thing.
The example top down merge sort divide() function just keeps calling itself until the sub-array size is reduced to a size of 1, in which case a sub-array of size 1 can be considered sorted. Only then does any actual merging begin, starting just after divide(arr,0,0) and divide(arr,1,1) return after doing nothing. numbersSort() then merges arr[0] and arr[1], and it returns. The next merge occurs just after divide(arr,2,2) and divide(arr,3,3), merging arr[2] and arr[3]. Then after that return, arr[0 1] and arr[2 3] are merged, resulting in a sorted array of 4 integers. Note that all divide does is generate pairs of indexes (low, high), numbersSort() is where the actual merging of data is done.
In general, top down merge sort is a depth first, left first sort. The non-iterative bottom up merge sort skips all the recursion used to generate indexes and just starts off by merging by even and odd indexes, merging [0] with [1], [2] with [3], [4] with [5], ... . Then on the next pass it merges runs of size 2, [0 1] with [2 3], [4 5] with [6 7], ... and so on until the array is merged.
Passing a temp array of the same size as the array to be sorted can be used to eliminate have to create, copy, and delete working arrays during a merge sort.
Example showing top down merge sort order of operation:
7 4 2 5 3 0 6 1
7 4 2 5|3 0 6 1
7 4|2 5
7|4
4 7
2|5
2 5
2 4 5 7
3 0|6 1
3|0
0 3
6|1
1 6
0 1 3 6
0 1 2 3 4 5 6 7
Example showing bottom up merge sort order of operation:
7 4 2 5 3 0 6 1
7|4|2|5|3|0|6|1 run size = 0
4 7|2 5|0 3|1 6 run size = 1
2 4 5 7|0 1 3 6 run size = 4
0 1 2 3 4 5 6 7 done

Position of elements in vector

I have several elements in a vector type that are read from cin and then i perfrom some calculations on the vector and it's order of elements gets changed. The problem is that I need to print the positions of the vector elements after the calculations. I don't know how to explain this well that's why i'll give an example:
10 1 100 1000
and 10 is 1st element, 1 is 2nd, 100 is 3rd etc. After the calculations the vector changes in :
100 10 1 1000
so I should print
3 1 2 4
because 100 is the 3rd element of the input, 10 is the 1st etc. etc.
I tried with an array[1000] (because there aren't numbers larger than 1000 in the input), but it won't work because there can be multiple numbers with the same value, like:
10 10 10 100
and the output can be 1 2 3 4 or 2 3 1 4 or 3 1 2 4 etc. but here i need to output 1 2 3 4 because it's the 'smallest'.
I tried with array f[1001] and f[10] = 1, f[100] = 2, f[1] = 3 - if the numbers from the input are 10 100 1. But in case there are multiple numbers with the same value like 10 10 100, then my idea's not working. Please help me in any possible way.
Sounds like you need to store both the value and the initial position. You should be able to do this with an array of structs:
struct UserInput
{
unsigned int initialPosition;
int userInputValue;
};
int main()
{
userInput theUserInput[100];
// increment a counter, starting at 1, and place it in
// "initialPosition" in the struct as user input is read
}
I'll leave the rest up to you... as it is after all homework :) good luck.
Use an associative array if you know what it is.
Use linear search to determine the index if the number of input is limited.
Consider using log10 (or strlen) to transform the 1, 10, 100, 1000, etc. into 0, 1, 2, 3, etc.
From your description of such example:
10(3) 10(2) 10(1) 100(4)
What we have to output is 1 2 3 4, instead of 3 2 1 4.
So I don't think your requirement is just print the initial position directly. You've to make the position sequences as small as possible.
Following is my solution:
Use a direct-mapping hash table to store all the initial positions for specified element. All the initial positions for the same element is sorted. So if you want output the smallest position sequence, you only need to read the initial positions for this specified element from first to last.
The detailed implementation is left to you, since it's a homework.