Function to print all elements of stack? - c++

I want to print all the elements of a character stack. This is my function:
void print_stack(stack<char> c)
{
stack<char> a = c;
for (unsigned int i = 0; i < a.size(); i++) {
std::cout<<a.top();
a.pop();
}
}
Currently, it is printing only the first a.size() - 1 elements and not the last element. I am having trouble figuring out why this is the case.

Your loop is wrong, consider what happens to a when you do a.pop() if a.size() was 3, it is now 2, so your loop will iterate one less time. You should do this:
while (!a.empty()) {
std::cout<<a.top();
a.pop();
}
Also you dont need to copy c, since your function signiture is void print_stack(stack<char> c) not void print_stack(stack<char> &c) you are creating a copy of c for the scope of this function anyway. Which means this would be sufficient:
void print_stack(stack<char> c) {
while (!c.empty()) {
std::cout<<c.top();
c.pop();
}
}
Here is a live example.

for (unsigned int i = 0; i < c.size(); i++)
or
while(a.size() > 0)

You could also simply do
std::stack<int> c;
std::cout << c; //[a, b, c]
Though you can't format it, you'll be able to get the representation of it.

Related

Find a combination of elements from different arrays

I recently started learning C++ and ran into problems with this task:
I am given 4 arrays of different lengths with different values.
vector<int> A = {1,2,3,4};
vector<int> B = {1,3,44};
vector<int> C = {1,23};
vector<int> D = {0,2,5,4};
I need to implement a function that goes through all possible variations of the elements of these vectors and checks if there are such values a from array A, b from array B, c from array C and d from array D that their sum would be 0(a+b+c+d=0)
I wrote such a program, but it outputs 1, although the desired combination does not exist.
using namespace std;
vector<int> test;
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <= A.size(); ai++){
test[0] = A[ai];
for ( int bi = 0; bi <= B.size(); bi++){
test[1] = B[bi];
for ( int ci = 0; ci <= C.size(); ci++){
test[2] = C[ci];
for ( int di = 0; di <= D.size(); di++){
test[3] = D[di];
if (sum (test) == 0){
return true;
}
}
}
}
}
}
I would be happy if you could explain what the problem is
Vectors don't increase their size by themself. You either need to construct with right size, resize it, or push_back elements (you can also insert, but vectors arent very efficient at that). In your code you never add any element to test and accessing any element, eg test[0] = A[ai]; causes undefined behavior.
Further, valid indices are [0, size()) (ie size() excluded, it is not a valid index). Hence your loops are accessing the input vectors out-of-bounds, causing undefined behavior again. The loops conditions should be for ( int ai = 0; ai < A.size(); ai++){.
Not returning something from a non-void function is again undefined behavior. When your abcd0 does not find a combination that adds up to 0 it does not return anything.
After fixing those issues your code does produce the expected output: https://godbolt.org/z/KvW1nePMh.
However, I suggest you to...
not use global variables. It makes the code difficult to reason about. For example we need to see all your code to know if you actually do resize test. If test was local to abcd0 we would only need to consider that function to know what happens to test.
read about Why is “using namespace std;” considered bad practice?
not pass parameters by value when you can pass them by const reference to avoid unnecessary copies.
using range based for loops helps to avoid making mistakes with the bounds.
Trying to change not more than necessary, your code could look like this:
#include <vector>
#include <iostream>
int sum (const std::vector<int>& v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(const std::vector<int>& A,
const std::vector<int>& B,
const std::vector<int>& C,
const std::vector<int>& D){
for (const auto& a : A){
for (const auto& b : B){
for (const auto& c : C){
for (const auto& d : D){
if (sum ({a,b,c,d}) == 0){
return true;
}
}
}
}
}
return false;
}
int main() {
std::vector<int> A = {1,2,3,4};
std::vector<int> B = {1,3,44};
std::vector<int> C = {1,23};
std::vector<int> D = {0,2,5,4};
std::cout << abcd0(A,B,C,D);
}
Note that I removed the vector test completely. You don't need to construct it explicitly, but you can pass a temporary to sum. sum could use std::accumulate, or you could simply add the four numbers directly in abcd0. I suppose this is for exercise, so let's leave it at that.
Edit : The answer written by #463035818_is_not_a_number is the answer you should refer to.
As mentioned in the comments by #Alan Birtles, there's nothing in that code that adds elements to test. Also, as mentioned in comments by #PaulMcKenzie, the condition in loops should be modified. Currently, it is looping all the way up to the size of the vector which is invalid(since the index runs from 0 to the size of vector-1). For implementing the algorithm that you've in mind (as I inferred from your code), you can declare and initialise the vector all the way down in the 4th loop.
Here's the modified code,
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <A.size(); ai++){
for ( int bi = 0; bi <B.size(); bi++){
for ( int ci = 0; ci <C.size(); ci++){
for ( int di = 0; di <D.size(); di++){
vector<int> test = {A[ai], B[bi], C[ci], D[di]};
if (sum (test) == 0){
return true;
}
}
}
}
}
return false;
}
The algorithm is inefficient though. You can try sorting the vectors first. Loop through the first two of them while using the 2 pointer technique to check if desired sum is available from the remaining two vectors
It looks to me, like you're calling the function every time you want to check an array. Within the function you're initiating int sum_of_elements = 0;.
So at the first run, you're starting with int sum_of_elements = 0;.
It finds the element and increases sum_of_elements up to 1.
Second run you're calling the function and it initiates again with int sum_of_elements = 0;.
This is repeated every time you're checking the next array for the element.
Let me know if I understood that correctly (didn't run it, just skimmed a bit).

Vector Subscript out of Range. Comparing Elements of Vectors

So I have a vector like this
All_Pos={0,10,15,24,30,33,66}
And three smaller vectors that contain the numbers from the previous vector, let's say
Vec_Lin={0,15}
Vec_Circ={24,33,66}
Vec_Arc={10,30}
I want to make something like this:
All_Pos[0]=Vec_Lin[0]? YES -> Do something
All_Pos[1]=Vec_Lin[1]?No
All_Pos[1]=Vec_Circ[0]?No
All_Pos[1]=Vec_Arc[0]?Yes -> Do Something
Ans so on, until i finish my All_Pos. The problem is that i get vector out of range and i don't know how to fix that.
int counter_linie=0;
int counter_cerc=0;
int counter_arc=0;
for (int p = 0; p < All_pos.size(); p++)
{
if(All_pos[p] == Vec_Lin[counter_linie])
{
//Do something
counter_linie++;
}
if (All_pos[p] == Vec_circ[counter_cerc])
{
//Do something
counter_cerc++;
}
if (All_pos[p] == Vec_Arc[counter_arc])
{
/Do something
counter_arc++;
}
}
You should check for out of range. [] operator works ,when indexing is in limits from '0' to vector.size().
void process_vector(void)
{
std::vector<int> All_Pos = { 0,10,15,24,30,33,66 };
std::vector<int> Vec_Lin = { 0,15 };
std::vector<int> Vec_Circ = { 24,33,66 };
std::vector<int> Vec_Arc = { 10,30 };
int counter_linie = 0;
int counter_cerc = 0;
int counter_arc = 0;
for (int p = 0; p < All_Pos.size(); p++) {
if (counter_linie< Vec_Lin .size() && All_Pos[p] == Vec_Lin[counter_linie])
{
//Do something
counter_linie++;
}
if (counter_cerc < Vec_Circ.size() && All_Pos[p] == Vec_Circ[counter_cerc])
{
//Do something
counter_cerc++;
}
if (counter_arc < Vec_Arc.size() && All_Pos[p] == Vec_Arc[counter_arc])
{
// Do something
counter_arc++;
}
}
std::cout << counter_linie << " " << counter_cerc << " " << counter_arc << std::endl;
}
You are trying to access elements that don't exist in your smaller vectors.
Vec_circ can only be accessed with indices 0, 1 and 2, but after three successful checks for Vec_circ in your loop counter_cerc will be 3.
Trying to access Vec_circ[3] then leads to the error.
You need a mechanism that prevents this case.
You should step through your code with a debugger to see the problem.
Initially the values are:
int counter_linie=0;
int counter_cerc=0;
int counter_arc=0;
After the first iteration the values are:
counter_linie=1;
counter_cerc=0;
counter_arc=0;
After the second iteration the values are:
counter_linie=1;
counter_cerc=0;
counter_arc=1;
After the third iteration the values are:
counter_linie=2;
counter_cerc=0;
counter_arc=1;
And now you try to read
Vec_Lin[2]
in
if(All_pos[p] == Vec_Lin[counter_linie])
That's your problem. Add a check into the if conditions.
if(counter_linie < Vec_Lin.size() && All_pos[p] == Vec_Lin[counter_linie])

Problems with vectors, how to remove the arrays in my vectors?

I have created a function that creates all the possible solutions for a game that I am creating... Maybe some of you know the bullcow game.
First I created a function that creates a combination of numbers of max four integers and the combination can't have any repeating number in it... like...
'1234' is a solution but not '1223' because the '2' is repeating in the number. In total there is 5040 numbers between '0123' and '9999' that haven't repeating numbers.
Here is my function:
std::vector <std::array<unsigned, 4>> HittaAllaLosningar(){
std::vector <std::array<unsigned, 4>> Losningar;
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
for (unsigned k = 0; k < 10; k++) {
for (unsigned l = 0; l < 10; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
Losningar.push_back({i,j,k,l});
}
}
}
}
}
return Losningar;
}
Now let's say I have the number '1234' and that is not the solution I am trying to find, I want to remove the solution '1234' from the array since that isn't a solution... how do I do that? have been trying to find for hours and can't find it. I have tried vector.erase but I get errors about unsigned and stuff... also its worth to mention the guesses are in strings.
What I am trying to do is, to take a string that I get from my program and if it isn't a solution I want to remove it from the vector if it exists in the vector.
Here is the code that creates the guess:
std::string Gissning(){
int random = RandomGen();
int a = 0;
int b = 0;
int c = 0;
int d = 0;
for (unsigned i = random-1; i < random; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j == 0) {
a = v[i][j];
}
if (j == 1) {
b = v[i][j];
}
if (j == 2) {
c = v[i][j];
}
if (j == 3) {
d = v[i][j];
}
}
std::cout << std::endl;
AntalTry++;
}
std::ostringstream test;
test << a << b << c << d;
funka = test.str();
return funka;
}
The randomgen function is just a function so I can get a random number and then I go in the loop so I can take the element of the vector and then I get the integers of the array.
Thank you very much for taking your time to help me, I am very grateful!
You need to find the position of the element to erase.
std::array<unsigned, 4> needle{1, 2, 3, 4};
auto it = std::find(Losningar.begin(), Losningar.end(), needle);
if (it != Losningar.end()) { Losningar.erase(it); }
If you want to remove all the values that match, or you don't like checking against end, you can use std::remove and the two iterator overload of erase. This is known as the "erase-remove" idiom.
std::array<unsigned, 4> needle{1, 2, 3, 4};
Losningar.erase(std::remove(Losningar.begin(), Losningar.end(), needle), Losningar.end());
To erase from a vector you just need to use erase and give it an iterator, like so:
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
auto it = vec.begin(); //Get an iterator to first elements
it++; //Increment iterator, it now points at second element
it = vec.erase(it); // This erases the {4,3,2,1} array
After you erase the element, it is invalid because the element it was pointing to has been deleted. Ti continue to use the iterator you can take the return value from the erase function, a valid iterator to the next element after the one erased, in this the case end iterator.
It is however not very efficient to remove elements in the middle of a vector, due to how it works internally. If it's not important in what order the different solution are stored, a small trick can simplify and make your code faster. Let's say we have this.
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
vec.push_back({3,2,1,4});
To remove the middle one we then do
vec[1] = vec.back(); // Replace the value we want to delete
// with the value in the last element of the vector.
vec.pop_back(); //Remove the last element
This is quite simple if you have ready other functions:
using TestNumber = std::array<unsigned, 4>;
struct TestResult {
int bulls;
int cows;
}
// function which is used to calculate bulls and cows for given secred and guess
TestResult TestSecretGuess(const TestNumber& secret,
const TestNumber& guess)
{
// do it your self
… … …
return result;
}
void RemoveNotMatchingSolutions(const TestNumber& guess, TestResult result)
{
auto iter =
std::remove_if(possibleSolutions.begin(),
possibleSolutions.end(),
[&guess, result](const TestNumber& possibility)
{
return result == TestSecretGuess(possibility, guess);
});
possibleSolutions.erase(iter, possibleSolutions.end());
}
Disclaimer: it is possible to improve performance (you do not care about order of elements).

what is the recursive form of this code?

I was trying to locate vector a in vector b. So it's like if vector a is in vector b then return true else false. And vector a should be like {1,2,3} and b should like {4,1,2,3,5,5,7}. The output of this code is coming like true 1 and false 0. So my problem is I don't want 1 and 0 to show up in the output.
Also I want to write this code in recursive form so could anyone help me with this problem?
bool x(vector<int>& a, vector<int> b)
{
vector<int> index ( b.size(),0 );
int counter = 0;
if ( a.size() <= b.size() ) {
for ( int i = 0; i < a.size(); i++ ) {
for ( int j = 0; j < b.size(); j++ ) {
if ( a[i]== b[j]) {
index[j] = 1;
}
}
}
for ( int i = 0; i < index.size(); i++ ) {
if ( index[i] == 1 ) {
for ( int j = i; j < index.size(); j++ ) {
if ( index[j] == 1 ) {
counter++;
}
}
if(counter == a.size()){
cout<<"true"<<endl;
return true;
break;
}
else{
counter = 0;
cout<<"false"<<endl;
return false;
// continue;
}
}
}
}
return 0;
}
if you just don't like the output: true 1 and false 0. the simplest way to solve it is:
if(x(a, b)){
cout<<"true"<<endl;
} else {
cout<<"false"<<endl;
}
BUT, before you try to convert you algorithm to a recursive one, I afraid that your algorithm is wrong. try this:
vector<int> a;
vector<int> b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
b.push_back(1);
b.push_back(1);
b.push_back(1);
cout<<x(a,b)<<endl;
you will get true ,and the correct answer is false.
check your algorithm !
The reason you're seeing "true 1" and "false 0" is probably because while you print "true" and "false" as strings in your function, you return a bool, which if you print outside the function will be default print as "1" and "0". To overcome that, you can use std::boolalpha as discussed here: Converting bool to text in C++
As for converting your algorithm to a recursive one, I'm afraid that's off topic for Stack Overflow until you try it yourself.
Like John said, you're printing the cout (standard out) Strings, not integers (1/0). Also agree with the off-topic, you need to suggest a solution and ask for help/recommendations/feedback. There's a heap of tutorials on the net about how to it.
But if you want to recurse, you should create an array3 whose length is the same size array1, whereas you'll recurse over array2 to check if any elements of array2 exist (either as objects or as values) in array1. You'll need a function that produces an array and takes in arrays (why are you using vectors?) and then iterates over the 2nd array, passing array1, array3 and current index value as arguments.
Fibonacci recursive problem is taught in just about every programming course in Uni (or at least it should be), so it's a good starting point to look at.
Recursion function of this :
// it will return true if vector is present
// i is pointer for a
// j is pointer for b
bool subVector(vector<int>& a, vector<int> b,i,j)
{
if( i<a.size() && j<b.size()
{
if(a[i]==b[i])
{
return subVector(a,b,i+1,j+1)
}
else
{
return subVector(a,b,0,j+1)
}
}
else
{
if(i>a.size())
{
return true;
}
else{
return false;
}
}
}
// Calling
subVector(a,b,0,0);
Note : Not Compiled.

conditionally testing for equality of vector's elements

Although it seems pretty simple, I'm not sure of the most efficient way of doing this.
I have two vectors:
std::vector<bool> a;
std::vector<int> b;
a.size() necessarily equals b.size().
each bool in a corresponds to an int in b. I want to create a function:
bool test(std::vector<bool> a, std::vector<int> b);
This function returns true if the values in a are equal. However, it only considers values in a that correspond to true values in b.
I could do this:
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned int i;
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
x = a.at(i);
break;
}
}
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
if(a.at(i) != x){
return false;
}
}
}
return true;
}
But then I have to create two loops. Although the first loop will stop at the first true value, is there a better way?
Your solution looks good enough to me:
Each loop does a different thing anyway (so you shouldn't worry about duplication)
You don't use extranious variables or flags that complicate the code.
The only problems I see are:
You start the second loop at 0 instead of where you left off.
Doing if(condition == true) is very ugly. Just do if(condition) instead.
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned i;
for(i = 0; i < a.size(); i++){
if(b.at(i)){
x = a.at(i);
break;
}
}
for(i++; i < a.size(); i++){
if(b.at(i)){
if(a.at(i) != x){
return false;
}
}
return true;
}
You can do it in one loop if you remember if you have seen the first true element in b or not. Also, you should take the a and b parameters by reference to avoid unnecessary copying. And finally, if you know that the indices into a vector are always within valid range (i.e. between 0 and vector.size() - 1, inclusive), you can use operator[] instead of at, and achieve better peformance (at does a range check, while operator[] does not). Heres a modified version of your test function considering all the above points:
bool test(std::vector<int> const& a, std::vector<bool> const& b){
int x;
bool first = true;
for(unsigned i = 0, n = a.size(); i != n; ++i){
if( b[i] ){
if( first ) {
x = a[i];
first = false;
}
else if( x != a[i] ) {
return false;
}
}
}
return true;
}
Provided you know a.size() == b.size() just create a single loop that compares an 'a' element to a 'b' element at the same time at each iteration. Once you see that a[i] != b[i] then you know the containers don't match and you can break out.
I am not 100% certain I know what you want to do but a straight compare once you know you have equal size
std::equal(a.begin(), a.end(), b.begin(), std::equal_to<bool>())