How to efficiently manuplate very long vector? - c++

I have a very long vector as below in Eigen:
MatrixXi iIndex(1000000);
which is initialized into zeros, with only a short continuous part(less than 100) filled with 1 's, the position of which is randomized.
I need to do the following things in a long loop:
int count;
int position;
for(int i=0;i<99999;i++){
//... randomly fill iIndex will short `1` s
// e.g. index = (someVectorXi.array() == i).cast<int>();
count = iIndex.sum(); // count all the nonzero elements
//position the first nonzero element index:
for (int j=0; j<1000000;j++){
if(iIndex(j))
position = j;
}
}
But it is really very slow.
Is there any way to expedite?

my 2 cents: group the bits in e.g. uint32_t, so you can check whether an i32 differs from 0. When it is different, then you may take longer to find out which bits are 1.
Assuming the number of bits is a multitude of 32 (making it easier):
for (int i = 0; i < max / sizeof(uint32_t); ++i)
{
if (wordGrp[i] != 0)
{
uint32_t grp = wordGrp[i];
for (j = 0; j < BITS_PER_UINT32; j++)
{
if ((grp & 1) == 1) std::cout << "idx " << (i*32 + j) << " is 1\n";
grp >>= 1;
}
}
}

Related

Stuck on recursion algorithm in arrays

I got stuck with the following task:
"Write a recursive function that takes a one-dimensional array of 100 randomly set integers and finds the position at which a sequence of 10 numbers begins with the minimum sum".
I've written 2 functions:
int recursiveArrSum(int mass[], int dim = 10, int sum = 0) {
if (dim == 0) return sum;
sum += mass[dim-1];
return recursiveArrSum(mass, --dim, sum);
}
int recArrMinSum(int mass[], int dim=100, int tempSum=100, int idx=0, int addPar=0){
if (dim == 0) return idx;
mass[dim]=mass[addPar];
if (tempSum >= recursiveArrSum(mass)){
tempSum = recursiveArrSum(mass);
idx = dim-1;
//mass[dim]=mass[addPar];
}return recArrMinSum(mass, --dim, tempSum, idx, ++addPar);
1st one (recursiveArrSum) - works fine, but the second one drives me crazy...
I can't understand how I need to iterate an array during evoking the function on last return statement. I made it using for loop, and it works correctly:
for (int i=0; i<91; i++){
int tempS=0;
for (int j=i; j<=i+9; j++){
tempS += arr[j];
cout << tempS<< endl;
}
if (tempS<tempSum) {
tempSum=tempS;
k=i+1;
}
}
but recursion doesn't...
Could anyone suggest me the way for solving this issue?
Open for any questions.
Thanks in advance.
This is how I would do it:
A function that keeps in its arguments the current position, the current sum, the minimum sum and the starting position of this minimum sum. The function also transports as arguments the array (obviously), its size and the dimension of the sum (10 in your case).
void compute(int mass[], int massSize = 100, int dim = 10, int currentPosition = 0, int currentSum = 0, int minSum = 99999, int minPosition = -1)
{
// Before suming the first dim elements, we keep going adding the element at the current position and we increase the current position.
if (currentPosition < dim)
{
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition], minSum, minPosition);
return;
}
// When reaching the end of the array, we print our best solution.
if (currentPosition > massSize)
{
std::cout << "Min sum of " << dim << " elements is " << minSum << ", starting at position " << minPosition << std::endl;
return;
}
// In all the other cases, we check if the current sum is better than the minimum sum. If yes, we update the minimum sum and its starting position. Then call again the function!
if (currentSum < minSum)
{
minSum = currentSum;
minPosition = currentPosition - dim;
}
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition ] - mass[currentPosition -dim], minSum, minPosition);
}
Calling the function is easy: compute(mass, SIZE, 10); where mass is your array, SIZE is its size and 10 is your dimension.
With a dimension equals to 5 in this array:
8; 8; 4; 10; 9; 9; 6; 3; 3; 5; 3; 8; 3; 7; 9; 10; 10; 5; 6; 4; 1; 4; 1; 5; 2; 8; 6; 1; 7; 9;
Min sum of 5 elements is 13, starting at position 20
When writing a recursive function, the first things to do is to think about the exit case, the init cases (if there are any) and the "classic" case when you're in the middle of your search.
Feel free to ask any question, I added some comments to make it clear enough.
It is unclear how your code is supposed to work. To iterate the array and find the smallest sum you do something like this (pseudo code):
int currentSum = sum of elements 0 till 9
int smallestSum = currentSum
int smallestIndex = 0
for (i = 10; i < 100; ++i) {
currentSum = currentSum - mass[ i -10] + mass[i]
if (currentSum < smallestSum) {
smallestSum = currentSum
smallestIndex = i
}
}
As initial guess it takes the sum of the first 10 elements, ie elements 0 till 9. After that it iterates the array. Sum of elements 1 till 10 is the same as sum of elements 0 till 9 minus first element plus element 10. More general: To get the sum in the next iteration, element at i-10 is subtracted and element at i is added.
Not exactly sure what you're allowed to include from the STL, but there's this solution:
// Or std::pair<int, int*>
struct resultPair {
int first;
int* second;
};
// Or std::accumulate
int sumOf(int* arr, size_t s) {
int sum = 0;
for (size_t i=0; i<s; ++i)
sum += arr[i];
return sum;
}
resultPair minSeqOfN(int* arr, size_t s, size_t N) {
if (s < N) throw; // Or however you want to check pre-conditions
int sum = sumOf(arr, N);
if (s == N) return { sum, arr }; // Base case
auto nextRes = minSeqOfN(arr+1, s-1, N);
if (nextRes.first < sum) return nextRes;
else return resultPair{sum, arr};
}
The function keeps calling itself minus the first element, until the sequence size is equal to the input array size (then there's just 1 possible answer).

How to use less memory in Sieve_of_Eratosthenes

I'm coding on a leetcode-like platform. There is a task: counter the number of primes below a given bound.
I used the algorithm: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
I copy the code from here: https://www.geeksforgeeks.org/sieve-of-eratosthenes/ , except that I make false represents isPrime to avoid using memset. Here is my code:
void SieveOfEratosthenes(int n)
{
bool *prime = new bool[n+1](); // initialized by false by default
for (int p=2; p*p<=n; p++)
{
if (prime[p] == false)
{
for (int i=p*p; i<=n; i += p)
prime[i] = true;
}
}
for (int p=2; p<=n; p++)
if (prime[p])
cout << p << " ";
}
However, when I execute it, the platform tells me that I used too much memory in the case of 100 000 000 as the enter.
I've checked that sizeof(bool) equals to 1.
Is there some way to use less memory for this piece of code?
A couple of suggestions:
use a bit array representing only odd numbers
break the problem up into segments so the partial sieve uses much less memory
#Kim Walish has a fast C++ version here:
https://github.com/kimwalisch/primesieve/wiki/Segmented-sieve-of-Eratosthenes
You can make it use less memory still by always limiting the segment size to the L1 cache size, and by changing the IsPrime array to also be a bit array of odd numbers.
This is a memory optimized implementation of the sieve of eratosthenes. The basic idea is that, you only need to store the status of the odd numbers. Rest of it is similar to the normal implementation.
#include <iostream>
class Solution {
public:
int countPrimes(int n) {
//if(n <= 1) return 0; // including n
if(n <= 2) return 0; // number of primes less than 0 / 1 / 2 is 0
const int MAXN = 1500000 + 5; // adjust MAXN accordingly
// finding prime from 1 up to N
int status[(MAXN >> 1) + 1]; // we need space for only the odd numbers
// works well up to 1.5 * 10 ^ 6, for numbers larger than that, you need to adjust the second operand accordingly
int prime[115000 + 1000]; // prime number distribution , pi(x) = x/ (ln(x) - 1) , adjust this according to MAXN
// If status[i] = 0 -> i is prime
// If status[i] = 1 -> i is not prime
for(int i = 1 ; i <= (n >> 1) ; ++i) status[i] = 0; // for every i , 2 * i + 1 is the odd number, marking it as prime
int sqrtN = static_cast <int> ((sqrt (static_cast <double> (n))));
// computing sqrt(N) only once because it is costly computing it inside a loop
// only accounting the odd numbers and their multiples
for(int i = 3 ; i <= sqrtN ; i += 2){
if(status[i >> 1] == 0){
// if this is still a prime then discard its multiples
// first multiple that needs to be discarded starts at i * i
// all the previous ones have already been discarded
for(int j = i * i ; j <= n ; j += (i + i)) {
//printf("Marking %d as not prime\n",j);
status[j >> 1] = 1;
}
}
}
int counter = 0;
prime[counter++] = 2;
for(int i = 3 ; i <= n ; i += 2){
if(status[i >> 1] == 0){
prime[counter++] = i;
}
}
if( (n & 1) && !status[n >> 1]) counter--; // if n is prime, discard n
std::cout << "Number of primes less than " << n << " is " << counter << "\n";
for(int i = 0 ; i < counter; ++i){
std::cout << prime[i];
if(i != counter - 1) std::cout << "\n";
}
std::cout << "\n";
return counter;
}
};
int main(int argc, char const *argv[])
{
Solution solution;
int n; std::cin >> n;
solution.countPrimes(n);
return 0;
}

Find Maximum Strength given number of elements to be skipped on left and right.Please Tell me why my code gives wrong output for certain test cases?

Given an array "s" of "n" items, you have for each item an left value "L[i]" and right value "R[i]" and its strength "S[i]",if you pick an element you can not pick L[i] elements on immediate left of it and R[i] on immediate right of it, find the maximum strength possible.
Example input:
5 //n
1 3 7 3 7 //strength
0 0 2 2 2 //Left Value
3 0 1 0 0 //Right Value
Output:
10
Code:
#include < bits / stdc++.h >
using namespace std;
unsigned long int getMax(int n, int * s, int * l, int * r) {
unsigned long int dyn[n + 1] = {};
dyn[1] = s[1];
for (int i = 2; i <= n; i++) {
dyn[i] = dyn[i - 1];
unsigned long int onInc = s[i];
int left = i - l[i] - 1;
if (left >= 1) {
unsigned int k = left;
while ((k > 0) && ((r[k] + k) >= i)) {
k--;
}
if (k != 0) {
if ((dyn[k] + s[i]) > dyn[i]) {
onInc = dyn[k] + s[i];
}
}
}
dyn[i] = (dyn[i] > onInc) ? dyn[i] : onInc;
}
return dyn[n];
}
int main() {
int n;
cin >> n;
int s[n + 1] = {}, l[n + 1] = {}, r[n + 1] = {};
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
for (int i = 1; i <= n; i++) {
cin >> l[i];
}
for (int i = 1; i <= n; i++) {
cin >> r[i];
}
cout << getMax(n, s, l, r) << endl;
return 0;
}
Problem in your approach:
In your DP table, the information you are storing is about maximum possible so far. The information regarding whether the ith index has been considered is lost. You can consider taking strength at current index to extend previous indices only if any of the previously seen indices is either not in range or it is in range and has not been considered.
Solution:
Reconfigure your DP recurrence. Let DP[i] denote the maximum answer if ith index was considered. Now you will only need to extend those that satisfy range condition. The answer would be maximum value of all DP indices.
Code:
vector<long> DP(n,0);
DP[0]=strength[0]; // base condition
for(int i = 1; i < n ; i++){
DP[i] = strength[i];
for(int j = 0; j < i ; j++){
if(j >= (i-l[i]) || i <= (j+r[j])){ // can't extend
}
else{
DP[i]=max(DP[i],strength[i]+DP[j]); // extend to maximize result
}
}
}
long ans=*max_element(DP.begin(),DP.end());
Time Complexity: O(n^2)
Possible Optimizations:
There are better ways to calculate maximum values which you might want to look into. You can start by looking into Segment tree and Binary Indexed Trees.

Why is this bitset collection algorithm not working?

Here's my goal:
Create all possible bit strings of length N.
Once I've created a possible string, I want to take B bits at time, covert them to a index, and use that index to fetch a character from the following string:
define ALPHABET "abcdefghijklmnopqrstuvwxyz012345"
I want to add each character to a string, then print the string once all bits have been parsed.
Repeat until all possible bit strings are processed.
Here's my solution:
for (unsigned int i = 0; i < pow(2, N); i++) {
// Create bit set.
std::bitset <N> bits(i);
// String to hold characters.
std::string key_val;
// To hold B bits per time.
std::bitset <B> temp;
for (unsigned int j = 0; j < bits.size(); j++) {
// Add to bitset.
temp[j % B] = bits[j];
if (j % B == 0) {
key_val += ALPHABET[temp.to_ulong()];
}
}
std::cout << key_val << std::endl;
key_val.clear();
}
Here's the problem:
The output makes no sense. I can see the program creates really weird sequences, that aren't what I need.
Ideally, the output should be (what I'd like) :
aaaaa
aaaab
aaaac
.
.
.
And here's the output what I'm getting:
aaaaa
baaaa
acaaa
bcaaa
aeaaa
beaaa
agaaa
bgaaa
aiaaa
.
.
.
The "append character" condition triggers immediately (j == 0), this is probably not what you want. You'll also need to take care about the end if bits size is not a multiple of B
for (unsigned int j = 0; j < bits.size(); j++) {
// Add to bitset.
temp[j % B] = bits[j];
if (j % B == B - 1 || j == bits.size() - 1) {
key_val += ALPHABET[temp.to_ulong()];
}
}
Edit: Instead of looping over all bits individually, you can probably do something like this:
for (int j = 0; j < bits.size(); j += B) {
key_val += ALPHABET[bits.to_ulong() % B];
bits >>= B;
}
P.S.: If the bits fit into the loop variable, you don't need a bitset at all.
for (unsigned int i = 0; i < (1 << N); i++) {
std::string key_val;
for (unsigned int j = 0; j < bits.size(); j += B) {
key_val += ALPHABET[(i >> j) % B];
}
std::cout << key_val << std::endl;
}
P.P.S. You may want / need to count down in the inner loop instead if you want the digits reversed

all possible combinations bits

I am working on a program in C++ to demonstrate the workings of coding theory (in the sense of error correction using linear codes). I am adding parity bits to a string of bits ('words'). This is so I can still see what the message used to be if some bits have changed during transmission (Error detection and correction). One important thing to know is the minimum distance between two words. To calculate this I need to compile a list of all possible words and compare them to each other. If my error correction code consists of words of length n=6, there would be 2^6 = 64 possible combinations. My question is about how I can generate all these possible words and store them in an array.
These are two instances of what these words would look like:
0 0 0 0 0 0
1 0 0 0 0 0
1 1 0 1 0 1
I know I can generate combinations of two numbers with an algorithm like this:
for (int i = 1; i <= 5; i++)
for (int j = 2; j <= 5; j++)
if (i != j)
cout << i << "," << j << "," << endl;
However, this code only generates combinations of two numbers and also uses numbers other than 1 or 0.
EDIT
I have created a few for loops that do the job. It is not especially elegant:
int bits[64][6] = { 0 };
for (int x = 0; x < 32; x++)
bits[x][0] = 1;
for (int x = 0; x < 64; x += 2)
bits[x][1] = 1;
for (int x = 0; x < 64; x += 4)
{
bits[x][2] = 1;
bits[x + 1][2] = 1;
}
for (int x = 0; x < 64; x += 8)
{
bits[x][3] = 1;
bits[x + 1][3] = 1;
bits[x + 2][3] = 1;
bits[x + 3][3] = 1;
}
for (int x = 0; x < 64; x += 16)
{
for (int i = 0; i < 8; i++)
bits[x + i][4] = 1;
}
for (int x = 0; x < 64; x += 32)
{
for (int i = 0; i < 16; i++)
bits[x + i][5] = 1;
}
You may use the following: http://ideone.com/C8O8Qe
template <std::size_t N>
bool increase(std::bitset<N>& bs)
{
for (std::size_t i = 0; i != bs.size(); ++i) {
if (bs.flip(i).test(i) == true) {
return true;
}
}
return false; // overflow
}
And then to iterate on all values :
std::bitset<5> bs;
do {
std::cout << bs << std::endl;
} while (increase(bs));
If size is not a compile time value, you may use similar code with std::vector<bool>
I'd use iota or similar:
vector<int> foo(64); // Create a vector to hold 64 entries
iota(foo.begin(), foo.end(), 0); // Inserts the range of numbers in foo [0,foo.size())
for(auto& i : foo){
cout << bitset<6>(i) << endl;
}
I should probably also point out that an int is a sizeof(int) collection of bits, so hopefully you can work with that using bit-wise operators.
If you must use a more literal collection of bits, I would second Jarod42's answer, but still use iota:
vector<bitset<6>> bar(64);
iota(bar.begin(), bar.end(), 0);
for(auto& i : bar){
cout << i << endl;
}
Use a double loop from 0 to 62 and from the first loop index to 63.
Inside the loops convert the two indexes to binary. (A simple way is to convert to hexadecimal and expand the hex digits into four bits.)