Can't change a vector's element value at index i - c++

In Stroustrup's Programming: Principles and Practice Using C++, chapter 4, exercise 13, I have to write a program to find all the prime numbers in a given range using the Sieve of Erathostenes.
So far, I have come up with this:
vector<int> values;
void initialize_values()
{
for (int i{0}; i < 100; ++i)
values.push_back(1);
}
void remove_composites(vector<int> values)
{
for(int i{2}; i * i < values.size(); ++i)
{
if (values[i] == 1)
{
for (int p{i + i}; p < values.size(); p += i)
values[p] = 0; //not working
}
}
}
int main()
{
initialize_values();
remove_composites(values);
for (int i{2}; i < values.size(); ++i)
{
if (values[i] == 1)
cout << i << " ";
}
cout << '\n';
return 0;
}
I create a vector with size 100 (in this first case) and initialize elements to 1. Then I check all indexes multiples of i while i * i < 100 and change the value at those indexes to 0 and finally print the indexes whose value is 1.
The problem is that values[p] = 0 is not assigning the value 0 to the element at index p and I don't really understad why.
EDIT So after reading comments and answers I decided to move all code under main(), because I don't know how to use references.
The goal of this exercises, according to the book, is to get used to processing user input, working with loops, iterations, etc. It's not intended to be professional nor expert at this point.
To all people with many years coding and answering questions here, remember you were once learners and beginners. Have some respect and don't turn this community into a toxic one.
Updated code:
int main()
{
vector<int> values;
for (int i{0}; i < 100; ++i)
values.push_back(1);
for(int i{2}; i * i < values.size(); ++i)
{
if (values[i] == 1)
{
for (int p{i + i}; p < values.size(); p += i)
{
//cout << p << " ";
values[p] = 0;
}
//cout << '\n';
}
}
for (int i{2}; i < values.size(); ++i)
{
if (values[i] == 1)
cout << i << " ";
}
cout << '\n';
return 0;
}
And works as expected:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Thanks everyone.

The problem is that values[p] = 0 is not assigning the value 0 to the element at index p
It is assigning it.
The problem is that you are operating on a copy of the original vector, and that copy is local to remove_composites, which is why the calling code doesn’t see the changes.
Change your function signature to use a reference type parameter: std::vector<int>&.
There are also some other issues with your code (using the wrong type, i.e. int instead of bool; inconsistent signatures; mutable global variables).

Related

Bubble sort the numbers from a file in descending order for the first number

I want to sort using the "Bubble Sort" algorithm of the 2d array. My array size will be about array[100000][100000]. my input number will be n=100,000.
For now we can use a small size of the array to fix the sorting issue.
I need to sort them in descending order for the first number(first number's line).
If the first number of 2 values are the same, then I have to sort them according to their second number.
Finally I have to output the result into a txt file
Let's' understand using an example. Here, my input looks like this
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
above our input example and we have a couple of inputs. Now I need to sort them descending orders for the first number. But if the first number of 2 values are the same, then sort them according to their second number.
Example output below,
81 3
78 6
69 4
62 8
41 4
34 4
5 10
5 5
If anyone can please help me.
I am a beginner so I am trying to input the file manually to solve this sorting problem. I can solve the sorting problem then I will try to input and out the text.
Something I have tried but not worked. I am still trying to solve it.
#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
int main ()
{
int arr[100][100];
int n,j;
cin >>n;
cout << "Please enter a number: " << endl;
for(int i=0;i<n;i++)
{ for (int j=i; j<n; j++)
{
cin>>arr[i][j];
}
}
cout << "Unsorted array:" << endl;
for (int i=0; i<n; i++)
{
for (int j=i; j<n; j++)
{
cout<<arr[i][j]<<"\t";
}
}
for (int i=0; i<=n; i++)
{
for (int j=i+1; j<=n-1; j++)
{
int temp;
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
return 0;
}
Use a std::vector<std::array<int,2>>for your base container. The dynamic growth capabilities of std::vector solves your stack space issue, and the std::array use gives you tied cell comparison. I.e. you can do this:
std::array<int, 2> ar1{1,2}, ar2{1,3};
if (ar1 < ar2) ...
and it will do the right thing. The result then boils down to effectively this:
#include <iostream>
#include <array>
#include <vector>
#include <utility>
int main()
{
std::vector< std::array<int,2> > v;
std::size_t n;
if (std::cin >> n && n > 0)
{
std::array<int,2> row;
while (n-- && std::cin >> row[0] && std::cin >> row[1])
v.emplace_back(row);
// bubblesort the content
std::size_t len = v.size();
while (len-- > 0)
{
bool swapped = false;
for (std::size_t i=0; i<len; ++i)
{
// std::array support multi-cell comparison.
if (v[i] < v[i+1])
{
// use library swap to swap entire row.
std::swap(v[i], v[i+1]);
swapped = true;
}
}
// early exit if no swaps happened on the last pass
if (!swapped)
break;
}
// report final output.
for (auto const& row : v)
std::cout << row[0] << ' ' << row[1] << '\n';
}
}
Input
8
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
Output
81 3
78 6
69 4
62 8
41 11
34 4
5 10
5 5

hacker rank Mini-Max Sum

this problem
I normally erase the default code and start solving the whole thing myself. However, hackerrank test cases show a different output than the one that appears to me whenever i run against custom input. Why does it show different number?
Keep in mind I have tried different input sizes as float, long long int, int, and double;
#include <bits/stdc++.h>
using namespace std;
int main() {
long long int arr[5], neglect = 0, min = 9999999999999, max = 0, curr = 0;
for (int i = 0; i < 5; i++) {
cin >> arr[i];
}
while (neglect < 5) {
for (int i = 0; i < 5; i++) {
if (i == neglect) {i++;}
curr += arr[i];
}
if (curr < min) {min = curr;}
if (curr > max) {max = curr;}
//cout << curr << endl;
//cout << curr << " " << min << " " << max << endl;
curr = 0;
neglect++;
}
cout << min << " " << max;
}
All i wanted was to solve it in a way that tries all combinations then shows the least and maximum values. I know my code isn't the optimal way to solve it, I know i could just sort the array and exclude first and last elements, but please bear with me.
input: 1 2 3 4 5
claimed output: 11 4198826
but when i debugged it with the same custom input and the commented lines it showed:
14 14 14
13 13 14
12 12 14
11 11 14
10 10 14
10 14
Doesn't that mean that my code should be working?
When you are neglecting the last element you are doing an i++ and this will add the arr[5] to the curr value, but arr[5] is out of bound of the array, thus it can give segfault or unexpected result.
I would suggest that you should not increment the i in the for loop, instead you can use continue when you want to neglect the element.
for (int i = 0; i < 5; i++) {
if (i == neglect) {
continue;
}
curr += arr[i];
}
Also, you can replace the outer for loop with while loop so that you don't have to increment the neglect manually.

Array of Pointers getting garbage value in c++

I'm trying to create an array of pointers to a 2D (5 X 12) array in C++.
The ptr array has 5 elements. Each element should hold the address of the 1st element of the respective row of the 2D array. So 1st element should point to 1st element of 1st row, 2nd element should point to 1st element of 2nd row, and so on.
The 5th element of my array of pointers seems to point to a garbage value.
Code and output shown below. Can anyone please let me know why?
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int main( )
{
int rainMatrix[5][12] = {{0}}; //declare and initialize rain matrix
int *matrix_ptr[5] = {NULL};//declare and initialize array of pointers
int **matrix_ptr_ptr = matrix_ptr;
for (int i = 0; i < 5; ++i)
matrix_ptr[i] = &rainMatrix[i][0];
rainGen(matrix_ptr_ptr, 5, 12); //generate a random matrix
//display the matrix
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 12; ++j) {
cout << setw(2) << rainMatrix[i][j] << " ";
}
cout << endl;
}
for (int i = 0; i < 5; ++i)
cout << setw(2) << *matrix_ptr[i] << " " << rainMatrix[i][0] << endl;
return 0;
}
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
**pptr = rv;
*pptr += 1;
}
pptr++;
}
}
OUTPUT
11 1
88 11
28 88
25 28
1477892712 25
You're manipulating the wrong pointer in the innermost loop. Consider the pointer arithmetic carefully:
pptr essentially points to matrix_ptr[0];
on the first iteration, the double indirection means **pptr will set what you want, but then
*pptr += 1 will modify the contents of matrix_ptr[0], which means it no longer points to the beginning of the matrix.
Subsequent passes through the loop compound the situation drastically.
Modifying pptr won't help because it actually points to the wrong thing: it points to matrix_ptr, so incrementing it merely once moves its address from that of matrix_ptr[0], which points to rainMatrix[0][0], to that of matrix_ptr[1], which points to rainMatrix[1][0]. That is the wrong address for the next entry of the matrix, which is rainMatrix[0][1]. In essence, you've moved to the next row, instead of to the next column.
Try this for the innermost loop instead:
for (int i = 0; i < row; ++i)
{
auto qptr = *pptr;
for (int j = 0; j < col; ++j)
{
rv = rand() % 100;
*qptr = rv;
qptr += 1;
}
pptr++;
}
}
In this case, qptr is given the address of the first entry in the matrix. *qptr = rv sets the value. qptr += 1 increments the position of qptr while leaving *pptr alone - and, by extension, it leaves matrix_ptr[0] alone.
John Perry correctly identified the problem, but you have several option to deal with it. You are incorrectly incrementing *pptr += 1 Beyond using auto, you can simply index the pointer with the offset of j, e.g.
*(*pptr + j) = rv;
or
(*pptr)[j] = rv;
Either will work. Putting it together in your rainGen function, you could do:
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
// *(*pptr + j) = rv; /* or */
(*pptr)[j] = rv;
}
pptr++;
}
}
(note: seed and srand(seed) should be moved to main() if there is the potential that rainGen could be called more than once -- srand should only be called once)
Example Use/Output
Both will produce the desired output:
$ ./bin/raingen
72 71 65 94 0 13 49 17 36 49 67 51
87 68 45 15 91 72 16 80 77 35 9 81
11 88 73 59 24 22 37 48 45 54 94 45
19 44 62 56 45 81 59 32 49 4 99 92
28 16 24 5 3 34 38 14 22 12 26 98
72 72
87 87
11 11
19 19
28 28
You are modifying the pointers in the pointer-array matrix_ptr within your rainGen function, so that all of them point past the end and further accesses go to "random" memory locations, which is undefined behavior. Tools like valgrind can find such errors.

i want to show the sequence ftom 16 to 31 decimal number but its not showing :\ could anyone help me out here

#include <iostream>
using namespace std;
void bi(int a);
int main()
{
// here is the issue how do start a loop, where i want the answer from 16 to 31 numbers
int a=0;
cout<<"Baum-Sweet Sequence From 16 to 31 \n";
for(int j=a;j>16 && j<31;j++)
{
cout<<j;
}
bi(a);
system("Pause");
}
// Rest is working properly
void bi(int a)
{
int myArr[15],i=0,f=0,n=0;
for (int h = 0 ; h <= a; h++)
{
int num = h;
for (i = 0 ; i < 4 ; i++)
{
myArr[i] = num%2;
num = num/2;
}
for (int t = 0 ; t < 4 ; t++)
{
if (myArr[t]%2==0)
f++;
}
if (f%2==0)
cout << " = " << 1;
else
cout << " = " << 0;
cout <<endl;
}
}
i want to show the sequence from 16 to 31 decimal number but its not showing :\ could anyone help me out here
There is an error in the for loop.
The for loop has three parts separated by a semicolon.
for (INITIALIZATION; CONDITION; AFTERTHOUGHT)
{
// Source code for the for-loop's body
}
The first part initializes the variable (e.g. "int j = 16;" means that through the variable j you begin counting by 16);
The second part checks a condition and it quits the loop when false (e.g. j <=31 means that it quits the loop when j will have value 31);
The third one is performed once each time the loop ends and then repeats (e.g. j++ means that at each iteration of the loop j will be incremented by 1).
Each iteration will execute the code in the body of the for loop.
Considering that you want to call the bi function for each value from 16 to 31 your for loop body should include bi(j). Your main should be modified like the code below:
int main()
{
cout<<"Baum-Sweet Sequence From 16 to 31 \n";
for(int j=16;j<=31;j++)
{
cout<<j;
bi(j);
}
system("Pause");
return 0;
}
Your problem is that you set j to 0, but then make a condition for the loop that it will only execute if j (which is set to a), is bigger than 16.
Your first thing to do is to make the loop conditions this:
for (int j = 16; j <= 32; j++)

C++ - Accessing values in dynamic arrays

I have an assignment that requires the following:
-Take command line input for rows and columns and dynamically create a 2-D array filled with random numbers
-Create a function called find_greatest_product to find the largest product of four adjacent
numbers in the array. The four adjacent numbers can be any configuration of the shapes
found in the game Tetris in the array. Your function needs to return the max product, starting
position, shape, and direction of the four numbers using a struct.
Yes, it's a totally useless program purely to practice 2-D arrays.
I've got my array set up so I started with the easiest shape: the box. However, when I try to access the array full of random numbers, the product and factors all seem to be 0. Any hints as to why I'm unable to access the ints within the array of random numbers to find the product? The relevant bits of code are below. You can assume all functions not copied here work fine.
struct shape {
int highest;
int factors[4];
int startRow;
int startColumn;
} tShape, sShape, iShape, boxShape;
int main(int argc, char* argv[]) {
if(argc == 5) {
for(int i = 1; i < argc; i++) {
rows = getArg(argc, argv, i, compare1);
}
for(int i = 1; i < argc; i++) {
columns = getArg(argc, argv, i, compare2);
}
}
int ** array = new int*[rows];
int i, j;
for (i = 0; i < rows; i++) {
array[i] = new int[columns];
}
create_array(array, rows, columns);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
cout << array[i][j];
cout << " ";
}
cout << endl;
}
boxProduct(array, rows, columns, boxShape);
cout << boxShape.highest << endl;
for (int i = 0; i < 4; i++) {
cout << boxShape.factors[i];
cout << " ";
}
cout << endl;
return 0;
}
void boxProduct(int *array[], int rows, int columns, shape boxShape) {
int highest = 0;
int product = 0;
for (int i = 0; i < rows - 1; i++) {
for (int j = 0; j < columns - 1; j++) {
product = (array[i][j]*array[i][j+1]*array[i+1][j]*array[i+1][j+1]);
if (product > highest) {
boxShape.highest = product;
boxShape.factors[0] = array[i][j];
boxShape.factors[1] = array[i][j+1];
boxShape.factors[2] = array[i+1][j];
boxShape.factors[3] = array[i+1][j+1];
}
}
}
}
Here is a sample output with a matrix 10 rows x 5 columns:
27 86 4 41 44
17 6 5 40 32
42 58 14 95 53
8 28 95 27 91
63 22 27 49 2
38 37 39 37 76
9 17 14 13 10
10 30 16 67 22
49 10 33 63 5
86 71 86 34 50
0 <- product
0 0 0 0 <- the four factors
C and C++ functions are call by value by default, not call by reference. That is, the compiler makes copies of the arguments to give to functions, and if the function modifies its arguments, it modifies a copy.
Consider this example:
void foo( int x )
{
x++; // increments foo's own local copy of 'x'
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(i);
cout << i << endl; // ALSO prints 42!
return 0;
}
This will print 42 twice, because foo modifies a copy.
If you modify the code slightly, you tell the C++ compiler to pass the argument by reference. (Note: This is a C++ only feature; it does not work in C.) Now, any modification to the argument inside the function will modify the value the caller sees also:
void foo( int& x ) // The & means "pass this parameter by reference"
{
x++;
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(i);
cout << i << endl; // prints 43
return 0;
}
An alternate way to modify a value held by the caller is to pass a pointer to that value, rather than the value itself. This is still call by value, but in this case the value you pass the function is a pointer. Example:
void foo( int* x ) // x is now a pointer to integer
{
(*x)++; // The (*x) dereferences the pointer. What happens if you leave off the parens?
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(&i); // the & there takes the address of 'i' and passes that to foo()
cout << i << endl; // prints 43
return 0;
}
Because C does not support call-by-reference arguments, it requires this last scheme. Some C++ code also uses pointers in this way. Modern C++ style tends to avoid bare pointers wherever possible, but you'll still see pointers from time to time.
Punchline: You'll want to apply this knowledge to your shape boxShape structure above. You either want to pass shape boxShape by reference, or pass a pointer to shape boxShape. Both are valid approaches, although C++ tends to prefer passing a reference.