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.
Related
I`m trying to write merge sort with 2 threads.
I divide array into 2 pieces and sort each half with usual merge sort. After that I just merge two sorted parts.
Usual merge sort works correctly, and if I apply it to eash part without threads, it works correctly too.
I run a lof of tests on randomly generated short arrays, and there can be 2k of correct tests, but sometimes my multithread sort doesn`t work properly.
After sorting each half but before merging them, I check them. Sometimes the set of numbers in current part of array occurs to be different from orinigal set of numbers in that part before sorting, the numbers just appear from nowhere.
There must be some problem with threads, because there is no such problem without them.
As you can see, I made buffer with length = array.size() and I pass reference on it to functions. When merging two sorted arrays, this buffer is used.
Each buffer element is initialized with 0.
I`m sure that there is no shared data, because every function uses separated part of buffer. The correct work of usual merge sort supports that.
Please, help to understand, what is wrong with this way of using threads, I`m absolutely confused.
P. S. my code is supposed to execute sorting in N threads, not in 2, thats why I create array of threads. But even with 2 it doesnt work.
Multithread function:
void merge_sort_multithread(std::vector<int>& arr, std::vector<int>& buffer, unsigned int threads_count)
{
int length = arr.size();
std::vector<std::thread> threads;
// dividing array into nearly equal parts
std::vector<int> thread_from; // array with indexes of part`s start
std::vector<int> thread_length; // array with part`s length
make_parts(thread_from, thread_length, threads_count, length);
// start threads
for (int i = 0; i < threads_count; ++i)
{
threads.push_back(std::thread(merge_sort, std::ref(arr), std::ref(buffer),
thread_length[i], thread_from[i]));
}
// waiting for end of sorting
for (int i = 0; i < threads_count; ++i)
threads[i].join();
// ------- here I check each part and find mistakes, so next function is not important ----
merge_sorted_after_multithreading(arr, buffer, thread_from, thread_length, threads_count, 0);
}
Usual merge sort:
void merge_sort(std::vector<int>& arr, std::vector<int>& buffer, size_t length, int from)
{
if (length == 1)
{
return;
}
int length_left = length / 2;
int length_right = length - length_left;
// sorting each part
merge_sort(arr, buffer, length_left, from);
merge_sort(arr, buffer, length_right, from + length_left);
// merging sorted parts
merge_arrays(arr, buffer, length_left, length - length_left, from, from + length_left);
}
Merging two sorted arrays with buffer:
void merge_arrays(std::vector<int>& arr, std::vector<int>& buffer, size_t length_left, size_t length_right, int start_left, int start_right)
{
int idx_left, idx_right, idx_buffer;
idx_left = idx_right = idx_buffer = 0;
while ((idx_left < length_left) && (idx_right < length_right))
{
if (arr[start_left + idx_left] < arr[start_right + idx_right])
{
do {
buffer[idx_buffer] = arr[start_left + idx_left];
++idx_buffer;
++idx_left;
} while ((idx_left < length_left) && (arr[start_left + idx_left] < arr[start_right + idx_right]));
}
else
{
do {
buffer[idx_buffer] = arr[start_right + idx_right];
++idx_buffer;
++idx_right;
} while ((idx_right < length_right) && (arr[start_right + idx_right] < arr[start_left + idx_left]));
}
}
if (idx_left == length_left)
{
for (; idx_right < length_right; ++idx_right)
{
buffer[idx_buffer] = arr[start_right + idx_right];
++idx_buffer;
}
}
else
{
for (; idx_left < length_left; ++idx_left)
{
buffer[idx_buffer] = arr[start_left + idx_left];
++idx_buffer;
}
}
// copying result to original array
for (int i = 0; i < idx_buffer; ++i)
{
arr[start_left + i] = buffer[i];
}
}
Dividing array into separated parts:
void make_parts(std::vector<int>& thread_from, std::vector<int>& thread_length, unsigned int threads_count, size_t length)
{
int dlength = (length / threads_count);
int odd_length = length % threads_count;
int offset = 0;
for (int i = 0; i < threads_count; ++i)
{
if (odd_length > 0)
{
thread_length.push_back(dlength + 1);
--odd_length;
}
else
thread_length.push_back(dlength);
thread_from.push_back(offset);
offset += thread_length[i];
}
}
P.P.S. Each function except multithread sort was tested and works correctly
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).
I try to solve this challenge on CodeFights, but, it doesn't work. My best solution got 25/26 (time limit exceeded on the last test) but I deleted that because I tried it yesterday (it was O(n^2)). Now I tried a new one in O(n). I am very tired and I really want to get this done today, so please help me.
Here are the statements:
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Example
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
And here is my code until now... (poor code):
#include <iostream>
#include <vector>
#include <algorithm>
bool almostIncreasingSequence(std::vector<int> sequence)
{
int count = 0;
for(int i = 0; i < sequence.size()-1; i++)
{
if(sequence[i] > sequence[i+1])
{
count++;
sequence.erase(sequence.begin(), sequence.begin() + i);
i--;
}
if(count == 2)
return false;
}
return true;
}
int main()
{
std::cout << std::endl;
return 0;
}
Here is a C++11 solution with O(N) runtime:
constexpr auto Max = std::numeric_limits<std::size_t>::max();
bool is_sorted_but_skip(const std::vector<int>& vec, std::size_t index = Max){
auto Start = index == 0 ? 1 : 0;
auto prev = vec[Start];
for(std::size_t i = Start + 1; i < vec.size(); i++){
if(i == index) continue;
if(prev >= vec[i]) return false;
prev = vec[i];
}
return true;
}
bool almostIncreasingSequence(std::vector<int> v)
{
auto iter = std::adjacent_find(v.begin(), v.end(), [](int L, int R){ return L >= R; });
if(is_sorted_but_skip(v, std::distance(v.begin(), iter)))
return true;
return is_sorted_but_skip(v, std::distance(v.begin(), std::next(iter)));
}
We use std::adjacent_find to find the first element, iter greater than or equal its next element. Then we check that sequence is strictly sorted while skipping iter's position.
Otherwise, we check that the sequence is strictly sorted while we skip iter+1's position
Worse case complexity: 3 linear scan
Demo
Here's a hint (well, almost a solution really):
If you see a decrease between one element to the next, then you have to remove one of them (*).
Now, what if you find two decreases, between two disjoint pairs of elements? That's right :-)
Keeping that in mind, you should be able to solve your problem using a linear scan and a bit of constant-time work.
(*) excluding the first and the last pair of elements.
This is still O(N^2), because you delete the first element of the vector in each iteration. Don't delete the first element and don't i-- in the loop.
If you must erase the numbers (you don't, but still), at least do it from the end of the list. That way erasing a number is probably an O(1) operation (I'm not 100% sure that's how std::vector is implemented).
You really don't have to erase the numbers.
#include<iostream>
#include<vector>
using namespace std;
int almostIncreasingSequence( vector<int> sequence );
int main(){
int array[] = {40, 50, 60, 10, 20, 30};
std::vector<int> vect (array, array + sizeof(array) / sizeof(int) );
bool ret = almostIncreasingSequence(vect);
if( ret ){
std::cout<<"Array is strictly increasing.";
}
else{
std::cout<<"Array is not strictly increasing.";
}
return 0;
}
bool almostIncreasingSequence(std::vector<int> sequence) {
int val = 0;
int currentBig = sequence.at(0);
for (int i = 1; i < sequence.size(); i++){
if( currentBig < sequence.at(i))
{
currentBig = sequence.at(i);
}
else{
val++;
if( val>1)
{
return false;
}
if( i > 1 ){
if (sequence.at(i) > sequence.at(i-2)){
if( currentBig < sequence.at(i) ){
}
else{
currentBig = sequence.at(i);
}
}
}
else{
currentBig = sequence.at(i);
}
}
}
return true;
}
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).
I have some numbers stored in a std::vector<int>. I want to find which number appears most in the vector.
e.g. in the vector
1 3 4 3 4 2 1 3 2 3
the element that occurs the most is 3.
Is there any algorithm (STL or whatever) that does this ?
Sort it, then iterate through it and keep a counter that you increment when the current number is the same as the previous number and reset to 0 otherwise. Also keep track of what was the highest value of the counter thus far and what the current number was when that value was reached. This solution is O(n log n) (because of the sort).
Alternatively you can use a hashmap from int to int (or if you know the numbers are within a limited range, you could just use an array) and iterate over the vector, increasing the_hashmap[current_number] by 1 for each number. Afterwards iterate through the hashmap to find its largest value (and the key belonging to it). This requires a hashmap datastructure though (unless you can use arrays which will also be faster), which isn't part of STL.
If you want to avoid sorting your vector v, use a map:
int max = 0;
int most_common = -1;
map<int,int> m;
for (vi = v.begin(); vi != v.end(); vi++) {
m[*vi]++;
if (m[*vi] > max) {
max = m[*vi];
most_common = *vi;
}
}
This requires more memory and has a very similar expected runtime. The memory required should be on the order of a full vector copy, less if there are many duplicate entries.
Try this
int FindMode(vector<int> value)
{
int index = 0;
int highest = 0;
for (unsigned int a = 0; a < value.size(); a++)
{
int count = 1;
int Position = value.at(a);
for (unsigned int b = a + 1; b < value.size(); b++)
{
if (value.at(b) == Position)
{
count++;
}
}
if (count >= index)
{
index = count;
highest = Position;
}
}
return highest;
}
This is how i did it:
int max=0,mostvalue=a[0];
for(i=0;i<a.size();i++)
{
co = (int)count(a.begin(), a.end(), a[i]);
if(co > max)
{ max = co;
mostvalue = a[i];
}
}
I just don't know how fast it is, i.e. O() ? If someone could calculate it and post it here that would be fine.
Here is an O(n) generic solution for finding the most common element in an iterator range. You use it simply by doing:
int commonest = most_common(my_vector.begin(), my_vector.end());
The value type is extracted from the iterator using iterator_traits<>.
template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
T most_common(InputIt begin, InputIt end)
{
std::map<T, int> counts;
for (InputIt it = begin; it != end; ++it) {
if (counts.find(*it) != counts.end()) {
++counts[*it];
}
else {
counts[*it] = 1;
}
}
return std::max_element(counts.begin(), counts.end(),
[] (const std::pair<T, int>& pair1, const std::pair<T, int>& pair2) {
return pair1.second < pair2.second;})->first;
}