Only first element init as 1 [duplicate] - c++

This question already has answers here:
Initialization of all elements of an array to one default value in C++?
(12 answers)
Closed 3 years ago.
I have an array, ex:
int M[10] = { 1 };
I expected M[0] ~ M[9] will all be filled with 1, but when I printed them out, it doesn't, only M[0] is 1, others are 0.

This is a common misconception. Often you see people write things like this
int m[10] = { 0 };
To "initialise all elements to 0"; however, really that just initialises the first element to 0 and the rest are default initialised (to 0, which is why it works). Really they could've just written int m[10] = {};
You have the same problem: you initialise only the first element to 1 then the rest default to 0. You can either specify all the parameters, or use std::fill:
int m[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int n[10];
std::fill(std::begin(n), std::end(n), 1);

Related

How do I initialize a Eigen Sparse Matrix with a (values, innerIndices, outerStarts) triplet? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 29 days ago.
Improve this question
I'm new to working with Eigen/Sparse.
I'm trying to initialize a Eigen Sparse matrix with a (values, innerIndices, outerStarts) triplet. I see that there is an option to do this through a COO style triplet but not the one I mentioned.
I'm thinking of something like
Eigen::SparseMatrix<double> A(nrow,ncol);
A.valuePtr() = &values
A.innerIndexPtr() = &innerIndices
A.outerIndexPtr() = &outerStarts
I've tried
Eigen::SparseMatrix<double> A(nrow,ncol);
A.valuePtr() = &values
A.innerIndexPtr() = &innerIndices
A.outerIndexPtr() = &outerStarts
But it crashes with a segfault.
Use the Map specialization for sparse matrices. Like this:
#include <Eigen/Sparse>
#include <iostream>
Eigen::SparseMatrix<double> make()
{
double values[] = { 1., 2., 3., 4. };
int inner[] = { 4, 3, 2, 1 }; // nonzero row indices
int outer[] = { 0, 1, 2, 3, 4, 4 }; // start index per column + 1 for last col
return Eigen::SparseMatrix<double>::Map(
5 /*rows*/, 5 /*cols*/, 4 /*nonzeros*/, outer, inner, values);
}
int main()
{
std::cout << make() << '\n';
}
prints
Nonzero entries:
(1,4) (2,3) (3,2) (4,1)
Outer pointers:
0 1 2 3 4 $
0 0 0 0 0
0 0 0 4 0
0 0 3 0 0
0 2 0 0 0
1 0 0 0 0
Note that I make a map but immediately copy it to a proper SparseMatrix in the return value.

How to rotate a dynamic array to the right?

I have a custom array object. It has two main variables:
m_array = Pointer to dynamic array.
m_size - The size of the array. The size for this array is 10.
When I rotate to the left, this works fine:
std::rotate(m_array + 0, m_array + 1, m_array + m_size);
This is equivalent to:
// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
When I try rotating to the right, I'm getting a runtime error.
I need the equivalent of this:
// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
I tried this:
std::rotate(m_array + m_size, m_array + m_size + 1, m_array + 0);
I get the error: Invalid iterator range
So, I thought this was m_size, so I tried this:
std::rotate(m_array + m_size - 1, m_array + (m_size - 1) + 1, m_array + 0);
And I get the same error.
Thoughts are welcomed.
The source I tried to follow:
http://en.cppreference.com/w/cpp/algorithm/rotate
To do a right rotation (to borrow your phrase), you want the range to be everything but the last element in the array. I'll leave it to you to adapt this code to work on variable-sized arrays.
#include <algorithm>
#include <iostream>
int main() {
int data[10] = { 0, 1, 2, 3, 4,
5, 6, 7, 8, 9 };
auto print_all = [&data]() {
for(auto v: data) {
std::cout << v << ' ';
}
std::cout << '\n';
};
print_all();
// rotate elements to the left
std::rotate(data, data + 1, data + 10);
print_all();
// rotate element to the right, back to the original position
std::rotate(data, data + 9, data + 10);
print_all();
return 0;
}
My output looks like this:
./rotate
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 0
0 1 2 3 4 5 6 7 8 9
The reason std::rotate(v.rbegin(), v.rbegin() + 1, v.rend()) works is that it uses reverse iterators. That means that v.rbegin() + 1 is actually decrementing the position in the array and is equal to v.begin() + v.size() - 1.
When using raw pointer arithmetic, there is no way to get the same reverse iterating behavior. You will have to manually translate the left rotation to a right rotation. This can easily be done by flipping the rotate position about the center of the array and performing a left rotate.
Left or right rotation can be boiled down to dividing an array into 2 sections and then swapping them. Whether it is a left rotation or right rotation just dictates where the division is made. For a left rotate by k, the rotation point is at k mod N. For a right rotate, the rotation point is at -k mod N where N is the total length of the array. This selects the index in the original array you would like to be at index 0 of the newly rotated array.
So the following right rotate by 1,
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend())
is equivalent to using raw pointers in the following way:
int* p = &v[0];
int n = v.size();
int k = -1;
std::rotate(p, p + mod(k, n), p + n);
where mod() is the modulo operation (basically the % operator that always wraps to a positive number):
int mod(int x, int y) { return ((x % y) + y) % y; }

Standard library function to create array of indices whose corresponding value is a given number

I've got a C-style array called board that contains some char's. I'm trying to create a std::array or std::vector (either would be fine, although std::array would be preferable) to store all the indices of board that are a certain value (in my case, 0).
This code I wrote is functional and works well:
std::vector<int> zeroes;
zeroes.reserve(16);
//board has 16 elements, so zeroes.size() will never be larger than 16.
//I used this reserve for speedup - the compiler doesn't require it.
for (int i = 0; i < 16; ++i)
{
if (board[i] == 0)
{
zeroes.push_back(i);
}
}
However, from past experience, whenever a std function exists that could replace part of my code, it is terser and hence stylistically preferred and also faster. My function seems like a fairly basic operation - I know there is a standard function* to access the index of an array that contains a value when that value only occurs once** in the array. So, is there a standard function to create an array of the indices that contain a value, assuming that more than one such index exists?
* Technically, two nested function calls: int x = std::distance(board, std::find(board, board + 16, 0));. See the accepted answer here.
** Well, it still works if more than one index with the desired value is present, but it returns only the first such index, which isn't very useful in my context.
Edit:
As one of the answers misunderstood the question, I'll clarify what I'm seeking. Let's say we have:
char board[16] = {0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2};
Now, the indices which I'm looking for are {0, 2, 8, 9, 13, 14} because board[0] = 0, board[2] = 0, board[8] = 0, etc. and these are the only numbers which satisfy that property.
Here's a solution using std::iota and std::remove_if:
#include <algorithm>
#include <iostream>
int main () {
const std::size_t board_size = 16;
char board [board_size] = {
0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2
};
// Initialize a zero-filled vector of the appropriate size.
std::vector<int> zeroes(board_size);
// Fill the vector with index values (0 through board_size - 1).
std::iota(zeroes.begin(), zeroes.end(), 0);
// Remove the index values that do not correspond to zero elements in the board.
zeroes.erase(std::remove_if(zeroes.begin(), zeroes.end(), [&board] (int i) {
return board[i] != 0;
}), zeroes.end());
// Output the resulting contents of the vector.
for (int i : zeroes) {
std::cout << i << std::endl;
}
}
Output of the program (demo):
0
2
8
9
13
14

Mathematically rotate an array of ordered numbers

Suppose you have a set of numbers in a given domain, for example: [-4,4]
Also suppose that this set of numbers is in an array, and in numerical order, like so:
[-4, -3 -2, -1, 0, 1, 2, 3, 4]
Now suppose I would like to create a new zero-point for this set of numbers, like so: (I select -2 to be my new axis, and all elements are shifted accordingly)
Original: [-4, -3 -2, -1, 0, 1, 2, 3, 4]
Zeroed: [-2, -1 0, 1, 2, 3, 4, -4, -3]
With the new zeroed array, lets say I have a function called:
"int getElementRelativeToZeroPosition(int zeroPos, int valueFromOriginalArray, int startDomain, int endDomain) {...}"
with example usage:
I am given 3 of the original array, and would like to see where it mapped to on the zeroed array, with the zero on -2.
getElementRelativeToZeroPosition(-2, 3, -4, 4) = -4
Without having to create any arrays and move elements around for this mapping, how would I mathematically produce the desired result of the function above?
I would proceed this way:
Get index of original zero position
Get index of new zero position (ie. index of -2 in you example)
Get index of searched position (index of 3)
Compute move vector between new and original zero position
Apply move vector to searched position modulo the array size to perform the rotation
Provided your array is zero-based:
index(0) => 4
index(-2) => 2
index(3) => 7
array_size => 9
move_vector => index(0) - index(-2)
=> 4 - 2 => +2
new_pos(3) => (index(3) + move_vector) modulo array_size
=> (7 + 2) mod 9 => 0
value_at(0) => -4
That's it
Mathematically speaking, if you have an implicit set of integers given by an inclusive range [start, stop], the choice of choosing a new zero point is really a choosing of an index to start at. After you compute this index, you can compute the index of your query point (in the original domain), and find the difference between them to get the offset:
For example:
Given: range [-4, 4], assume zero-indexed array (0,...,8) corresponding to values in the range
length(range) = 4 - (-4) + 1= 9
Choose new 'zero point' of -2.
Index of -2 is -2 - (-4) = -2 + 4 = 2
Query for position of 3:
Index in original range: 3 - (-4) = 3 + 4 = 7
Find offset of 3 in zeroed array:
This is the difference between the indices in the original array
7 - 2 = 5, so the element 3 is five hops away from element -2. Equivalently, it's 5-len(range) = 5 - 9 = -4 hops away. You can take the min(abs(5), abs(-4)) to see which one you'd prefer to take.
you can write a doubled linked list, with a head-node which points to the beginning
struct nodeItem
{
nodeItem* pev = nullptr;
nodeItem* next = nullptr;
int value = 0;
}
class Node
{
private:
nodeItem* head;
public:
void SetHeadToValue(int value);
...
}
The last value should point with next to the first one, so you have a circular list.
To figur out, if you are at the end of the list, you have to check if the item is equal to the head node

shift an array and insert a new element at given position using memcpy

I need to shift the array and insert a new element at given position using memcpy.
Input: 2, 5, 7, 0, 0, 0
Expected output: 2, 3, 5, 7, 0, 0
Actual output: 2, 3, 5, 0, 0, 0
Is there a mistake in my memcpy? (I have to use arrays - not std::vectors)
#include <stdio.h>
int main()
{
int i=0;
int len=0;
int a[6] = {'\0'};
a[0]= 2;
a[1] = 5;
a[2]= 7;
len=3;
int b=0;
b = 2;
memcpy(a+2, a+1, b * sizeof(int));
//memcpy(a+2, a+1, sizeof(int) * (len-1));
a[1]=3;
for(i=0;i<6;i++)
printf("after %d \n", a[i]);
}
From the manpage for memcpy:
The memory areas should not overlap. Use memmove(3) if the memory areas do overlap.
And for completeness, from the C99 standard:
If copying takes place between objects that overlap, the behavior is undefined.
You are actually copying the 5 (a[1])over correctly, but it is writing over the 7 (a[2])
You will need to add another memcpy to copy the 7 entry over first, and THEN you can copy the 5 over.
Since you are technically moving memory, however, I would suggest what Mike Seymour said, and do a memmove:
http://www.cplusplus.com/reference/clibrary/cstring/memmove/