Fairly simple, I want to loop over every index of an array of arraysize using only one var for the loop. I have a way to do it with two vars i and j, where i tracks the actual index and loops around and j counts up to arraysize and terminates the loop:
for (unsigned int i = start, j = 0; //start is the starting index
j < arraysize;
++i == arraysize ? i = 0 : 0, ++j)
{
//do stuff
}
Is there some nifty way to do this with only i? Order doesn't matter, if backward iteration makes sense for some reason.
Clarification: I want to loop from start to arraysize - 1, then from 0 to start - 1.
At least as I understand it, you want to loop through the entire array, but you want to start from somewhere other than the beginning, then when you reach the end, you want to start back at the beginning and keep going until you reach the original starting point.
Assuming that's correct, it's pretty easy:
for (size_t i=0; i<arraysize; i++)
process(array[(i+start)%arraysize]);
I would prefer to abstract that algorithm into generic function (which would work even on things like std::forward_list), without doing superfluous modulo and addition operations (though, they may be acceptable in many cases):
#include <algorithm>
#include <iostream>
#include <iterator>
template<typename FwdIter, typename F>
F for_each_shifted(FwdIter first, FwdIter start, FwdIter last, F f)
{
using std::for_each;
return for_each(first, start, for_each(start, last, f));
}
int main()
{
using namespace std;
int v[] = { 1, 1, 2, 6, 24 };
for_each_shifted(begin(v), begin(v) + 3, end(v), [](int x)
{
cout << x << endl;
});
}
Output is:
6
24
1
1
2
Live Demo
for ( i=start; i<start+arraysize; i++ ) {
// do stuff with (i % arraysize) in place of i
}
for (size_t i = start; (i + 1) % arraysize != start: i = (i + 1) % arraysize) {
// stuff
}
This would get you there:
for (unsigned int i = start; i < start + arraySize; i++)
{
DoSomething(array[i % arraySize]);
}
Alternatively:
for (unsigned int i = 0; i < arraySize; i++)
{
DoSomething(array[(i + start) % arraySize]);
}
For example you can use the folloing loop statement
for ( int i = start; i < arraysize + start; i++ )
and inside the loop body instead of i use expression i % arraysize
Related
I've written some code to find a desired sub-array within a larger array and replace it with a different sub-array of the same length.
e.g.:
int array[] = {1,2,3,4,1,2,3,4};
int find[] = {1,2,3};
int replace[] = {7,8,9};
replaceSubArray(array, 8, find, replace, 3);
And replaceSubArray modifies 'array' to contain {7,8,9,4,7,8,9,4}
My function looks like this:
void replaceSubArray(char* longArray, int longLength, char* find, char* replace, int shortLength) {
int findIndex = 0, replaceIndex = 0;
for (int i = 0; i < longLength; ++i) //loop through larger array
{
if (longArray[i] == find[findIndex]) //if we find a match for an element
{
if (++findIndex == shortLength) //increment the findIndex and see if the entire subarray has been found in the larger array
{
for (int j = i - (shortLength - 1); j <= i; ++j) //entire array has been matched so go back to start of the appearance of subarray in larger array
{
longArray[j] = replace[replaceIndex]; //replace the matched subarray with the contents of replace[]
replaceIndex++;
}
replaceIndex = 0; //reset replaceIndex and findIndex to 0 so we can restart the search for more subarray matches
findIndex = 0;
}
} else { //if an element wasn't matched, reset findIndex to 0 to restart the search for subarray matches
findIndex = 0;
}
replaceIndex = 0;
}
}
It works fine but I am a beginner programmer and was curious if there is any better way to do this? Or if there are any built in functions that would help.
Use standard algorithms. You have
int array[] = {1,2,3,4,1,2,3,4};
int find[] = {1,2,3};
int replace[] = {7,8,9};
then you can use (requires #include <algorithm>, #include <iterator>)
using std::begin, std::end;
auto it = begin(array);
for (;;) {
it = std::search(it, end(array), begin(find), end(find));
if (it == end(array))
break;
it = std::copy(begin(replace), end(replace), it);
}
(live demo)
You can also use the Boyer-Moore searcher: (requires #include <functional>)
using std::begin, std::end;
auto searcher = std::boyer_moore_searcher(begin(find), end(find));
auto it = begin(array);
for (;;) {
it = std::search(it, end(array), searcher);
if (it == end(array))
break;
it = std::copy(begin(replace), end(replace), it);
}
(live demo)
Whether or not this will improve performance depends on a lot of factors, so profile.
To replace just the first occurence:
#include <string.h>
void replaceSubArray(int* longArray, int longLength, int* find, int* replace, int shortLength)
{
int i, k = 0;
for (i = 0 ; i < longLength ; ++i)
{
if (longArray[i] == find[k++])
{
if ( k == shortLength )
{
memcpy(longArray + i + 1 - k, replace, sizeof(int) * shortLength);
break;
}
continue;
}
k = 0;
}
}
To replace all occurences:
#include <string.h>
void replaceSubArray(int* longArray, int longLength, int* find, int* replace, int shortLength)
{
int i, k = 0;
for (i = 0 ; i < longLength ; ++i)
{
if (longArray[i] == find[k++])
{
if ( k == shortLength )
memcpy(longArray + i + 1 - k, replace, sizeof(int) * shortLength);
else
continue;
}
k = 0;
}
}
In C I would prefer this way.
PS: The question was tagged with C too before. Noticed that just now that C tag has been removed. Still posted in case if it helps.
If the elements in your find-array are all different, you could in most cases skip some indexes in your else-case:
replace:
else { //if an element wasn't matched, reset findIndex to 0 to restart the search for subarray matches
findIndex = 0;
}
with
else { //if an element wasn't matched, reset findIndex to 0 to restart the search for subarray matches
findIndex = 0;
i+=find.length-findIndex; // there could not be a match starting before this index.
}
If not all entries in your find-index are different you could use a similar (more complicated) approach. See Knuth–Morris–Pratt algorithm
Using memcpy instead of a loop to make the actual replace should also speed things up a bit.
Hint:
Always profile each change to see if, and in which extend, the change improved the performance.
Here is the sample code in which I used std::vector and few already present feature of c++
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
int main () {
std::vector<int> vect1 = {1,2,3,4,5};
std::vector<int> find = {3,4,5};
std::vector<int> replace = {5,6,7};
auto it = std::search(vect1.begin(),vect1.end(),find.begin(),find.end()); // Finds sub array in main vect1
int i = 0;
while ((it != vect1.end()) && (i< replace.size())) {
*it = replace[i]; // replace each elements on by one start from searched index from std::search
i++; //iterate replace vector
it++; //iterate main vector
}
return 0;
}
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).
So for an assignment I've been asked to create a function that will generate an array of fibonacci numbers and the user will then provide an array of random numbers. My function must then check if the array the user has entered contains any fibonacci numbers then the function will output true, otherwise it will output false. I have already been able to create the array of Fib numbers and check it against the array that the user enters however it is limited since my Fib array has a max size of 100.
bool hasFibNum (int arr[], int size){
int fibarray[100];
fibarray[0] = 0;
fibarray[1] = 1;
bool result = false;
for (int i = 2; i < 100; i++)
{
fibarray[i] = fibarray[i-1] + fibarray[i-2];
}
for (int i = 0; i < size; i++)
{
for(int j = 0; j < 100; j++){
if (fibarray[j] == arr[i])
result = true;
}
}
return result;
}
So basically how can I make it so that I don't have to use int fibarray[100] and can instead generate fib numbers up to a certain point. That point being the maximum number in the user's array.
So for example if the user enters the array {4,2,1,8,21}, I need to generate a fibarray up to the number 21 {1,1,2,3,5,8,13,21}. If the user enters the array {1,4,10} I would need to generate a fibarray with {1,1,2,3,5,8,13}
Quite new to programming so any help would be appreciated! Sorry if my code is terrible.
It is possible that I still don't understand your question, but if I do, then I would achieve what you want like this:
bool hasFibNum (int arr[], int size){
if (size == 0) return false;
int maxValue = arr[0];
for (int i = 1; i < size; i++)
{
if (arr[i] > maxValue) maxValue = arr[i];
}
int first = 0;
int second = 1;
while (second < maxValue)
{
for (int i = 0; i < size; i++)
{
if (arr[i] == first) return true;
if (arr[i] == second) return true;
}
first = first + second;
second = second + first;
}
return false;
}
Here is a function that returns a dynamic array with all of the Fibonacci numbers up to and including max (assuming max > 0)
std::vector<size_t> make_fibs( size_t max ) {
std::vector<size_t> retval = {1,1};
while( retval.back() < max ) {
retval.push_back( retval.back()+*(retval.end()-2) );
}
return retval;
}
I prepopulate it with 2 elements rather than keeping track of the last 2 separately.
Note that under some definitions, 0 and -1 are Fibonacci numbers. If you are using that, start the array off with {-1, 0, 1} (which isn't their order, it is actually -1, 1, 0, 1, but by keeping them in ascending order we can binary_search below). If you do so, change the type to an int not a size_t.
Next, a sketch of an implementation for has_fibs:
template<class T, size_t N>
bool has_fibs( T(&array)[N] ) {
// bring `begin` and `end` into view, one of the good uses of `using`:
using std::begin; using std::end;
// guaranteed array is nonempty, so
T m = *std::max_element( begin(array), end(array) ); will have a max, so * is safe.
if (m < 0) m = 0; // deal with the possibility the `array` is all negative
// use `auto` to not repeat a type, and `const` because we aren't going to alter it:
const auto fibs = make_fibs(m);
// d-d-d-ouble `std` algorithm:
return std::find_if( begin(array), end(array), [&fibs]( T v )->bool {
return std::binary_search( begin(fibs), end(fibs), v );
}) != end(array);
}
here I create a template function that takes your (fixed sized) array as a reference. This has the advantage that ranged-based loops will work on it.
Next, I use a std algorithm max_element to find the max element.
Finally, I use two std algorithms, find_if and binary_search, plus a lambda to glue them together, to find any intersections between the two containers.
I'm liberally using C++11 features and lots of abstraction here. If you don't understand a function, I encourage you to rewrite the parts you don't understand rather than copying blindly.
This code has runtime O(n lg lg n) which is probably overkill. (fibs grow exponentially. Building them takes lg n time, searching them takes lg lg n time, and we search then n times).
So I have the following code and I need to derive the execution time growth rate, however I have no idea where to start. My question is, how do I go about doing this? Any help would be appreciated.
Thank you.
// function to merge two sorted arrays
int merge (int smax, char sArray[], int tmax, char tArray[], char target[])
{
int m, s, t;
for (m = s = t = 0; s < smax && t < tmax; m++)
{
if (sArray[s] <= tArray[t])
{
target[m] = sArray[s];
s++;
}
else
{
target[m] = tArray[t];
t++;
}
}
int compCount = m;
for (; s < smax; m++)
{
target[m] = sArray[s++];
}
for (; t < tmax; m++)
{
target[m] = tArray[t++];
}
return compCount;
}
It's actually very simple.
Look, the first for loop increases either s or t at each iteration, so it's O(smax + tmax). The second loop is obviously O(smax), the third is O(tmax). Altogether we get O(smax + tmax).
(There exist some cleverer ways to prove, but I've intentionally left them out.)
All loops are bounded in number of iterations by (smax + tmax). So you could say the algorithm is O( max(smax,tmax) ) or O( smax +tmax).
I want a simple yet efficient circular buffer/queue. If I use std::vector, I have to do this:
if ( v.size() >= limit ) {
std::vector<int> it = v.begin();
v.insert( it, data );
v.erase( it+1 );
}
Is there any simpler solution?
You want to maintain the size of the buffer, overwriting older items. Just overwrite the old ones as time goes on. If you want to deal with the case where nItems < limit, then you would need to deal with that, this is just a simple example of using modulo to insert into a fixed size buffer.
std::vector<int> data(10);
for (int i = 0 ; i < 100 ; ++i)
{
data[i%10] = i;
}
for (std::vector<int>::const_iterator it = data.begin() ; it !=data.end(); ++it)
{
std::cout << *it << std::endl;
}
That method of insertion will keep the last 10 elements in the buffer.
A std::list might be an easier alternative to building a list than std::vector. There's also std::queue.
It's also funny that you're using a vector to implement a circular queue but ask a question on how to implement a circular list. Why not use a map?
In c++11 for a fixed size alternative you should be using std::array:
const unsigned int BUFFER_SIZE = 10;
std::array<int, BUFFER_SIZE> buffer; // The buffer size is fixed at compile time.
for (i = 0; i < 100; ++i) {
buffer[i % BUFFER_SIZE] = i;
}
Try std::deque. The interface is like using a std::vector but insert and removal at beginning and end are more efficient.
You can use your vectors as usual, and then create a get_element(index) function to make it feel circular. It's pretty fast and straight-forward, since it's just integer manipulation.
template<typename T>
T get_element(std::vector<T> vec, int index) {
int vector_size = vec.size();
int vector_max = vector_size - 1;
int vector_min = 0;
int index_diff = 0;
int refined_index = 0;
// index_diff is the amount of index-out-of-range. Positive means index was
// bigger than the vector size, negative means index was smaller than 0
if (index > vector_max) {
index_diff = index - vector_max;
} else if (index < vector_min) {
index_diff = index;
} else {
index_diff = 0;
}
// Make the indexing feel circular
// index mod 16 yields a number from 0 to 15
if (index_diff > 0) {
refined_index = index % vector_size;
} else if (index_diff < 0) {
int temp_index = index % vector_size;
if (temp_index != 0) {
refined_index = vector_size - std::abs(temp_index);
// if the negative mod equals to 0, we can't have 16 - 0 = 16 index,
// so we set it to 0 manually
} else {
refined_index = 0;
}
} else {
refined_index = index;
}
return vec[refined_index];
}
Then use it like:
int result = get_element<int>(myvec, 256);
Note that any index smaller than 0 starts rotating from the last element of your vector, which is of course intended.