take an array from a circular array - c++

So, my goal is to capture data in a buffer.
I need speed and I just need a fixed size so I was thinking that a circular array would be the best.
But what I want to do is at each step to:
first, overwrite the latest information in the array with the newest that just arrived
next, using the all array starting from the oldest to the newest
repeat
I have difficulty to see how to handle the second step in C++ while being efficient. Or maybe something else than a circular array would be better? Any advise or point of view is welcome.
To have something more graphic:
for step in steps:
(current writing position = 2)
current buffer = [8, 9, 3, 4, 5, 6, 7]
new info = 10
overwrite buffer(new info)
new buffer = [8, 9, 10, 4, 5, 6, 7]
current writing position += 1 //(3)
array to use = [4, 5, 6, 7, 8, 9, 10]
function(array to use)
(I used integer following each other to see the chronology of each information in the buffer)
What I am thinking about is to copy the last part and first part and then concatenate them:
std::vector<int> buffer{8, 9, 10, 4, 5, 6, 7};
std::vector<int> oldest(&buffer[3],&buffer[6]);
std::vector<int> youngest(&buffer[0],&buffer[2]);
oldest.insert( oldest.end(), youngest.begin(), youngest.end() );
function(oldest)
If you know something that would be quicker please tell me.

If you really need speed you should not copy elements but use the index information you already have to access the elements in the right order.
So the handling function would just need a pointer to the array (or reference to std::vector), know the size and the current working pos.
// process from working pos to end of buffer
for(int i = current_pos; i < buffer_size; ++i) {
processElement(new_buffer [i]);
}
// process the remainder from begin to working pos
for(int i = 0; i < curent_pos; ++i) {
processElement(new_buffer [i]);
}
This should not be to hard to inplement as your working position marks both, the begin and end of your data to process.

This approach reduces the copy overhead n-fold where n is the number of extra array elements + 1 used.
Example: array with 2 extra elements
Note, in this case, the oldest value is on the left, the function has been called with pointer to arr[0] (start_pos = 0)
arr == [3, 4, 5, 6, 7, 8, 9, x, x]
now, lets insert the new value 10
arr == [3, 4, 5, 6, 7, 8, 9, 10, x]
start_pos += 1
call function with pointer to the second element (the old 3 won't be used)
function(arr + start_pos)
and now add the 11 and increment the working position (the old 4 won't be used)
arr == [3, 4, 5, 6, 7, 8, 9, 10, 11]
start_pos += 1
function(arr + start_pos)
Now, the array is full.
And only now it is needed to copy the last elements to the begin of the array (after the start_pos to the end) and set working_pos back to 0
depending on the number of extra elements this needs to be done only every 10th, 100th or even 1000th iteration !
result of copying would be:
arr == [6, 7, 8, 9, 10, 11, 9, 10, 11]
*
start_pos = -1 // prepare for the +1 in regular iteration.
next added value (12) will overwrite the * value
arr == [6, 7, 8, 9, 10, 11, 12, 10, 11]
start_pos += 1 // is 0 now
function(arr + start_pos)
Of course, you need one variable to determine the pos to insert the new element behind the other val or you derive from start_pos + nElemsToProcess
If your function() does only take std containers it is probably not the right choice to met the need for speed.

Related

How to use List Iterable functions in flutter

I found iterable functions, but I am not sure how I can use.
For example, skip, take, map, forEach, fold and join
Could you give me examples how to use?
Yes, let's check the following sample code.
List<int> values = [1, 2, 3, 4, 5, 6, 7, 8, 9];
print(values.skip(5).toList());
//[6, 7, 8, 9]
print(values.skip(5).take(3).toList());
//[6, 7, 8]
values.skip(5).take(3).map((e) => e.toString()).forEach((element) {print(element);});
//6 7 8
String str = values.fold("initialValue",
(previousValue, element) => previousValue + ", " + element.toString());
print(str);
//initialValue, 1, 2, 3, 4, 5, 6, 7, 8, 9
str = values.join(", ");
print(str);
//1, 2, 3, 4, 5, 6, 7, 8, 9
skip(1) skips the first value, 1, in the values list literal.
take(3) gets the next 3 values 2, 3, and 4 in the values list literal.
map() Returns a new lazy [Iterable] with elements that are created by calling f on each element of this Iterable in iteration order.
fork() Reduces a collection to a single value by iteratively combining each element of the collection with an existing value
join() Converts each element to a [String] and concatenates the strings.
Hi Avdienko and welcome to Stack Overflow. I will give you an example for a .forEach iterable function performed on a List.
List<int> listOfIntegers = [1, 2, 3, 4, 5];
listOfIntegers.forEach((element) {
print(element.toString() + " ");
});
This code will result in printing "1 2 3 4 5 " to the console.

Finding the number of sum combinations between two arrays that satisfy a condition

The problem:
I have 2 arrays A[v] and M[w], with length v and w, respectively. Given two numbers p and q, I want to find how many combinations of the sum of two elements of these arrays satisfy the following condition:
p >= A[v] + M[w] <= q
An example:
Let:
A = [9, 14, 5, 8, 12, 2, 16],
v = 7,
M = [6, 2, 9, 3, 10],
w = 5,
p = 21,
q = 24
The answer will be 5, because of the following combinations:
14 + 9 = 23
14 + 10 = 24
12 + 9 = 21
12 + 10 = 22
16 + 6 = 22
What I have tried:
The following is an implementation of the problem in C++:
int K = 0; // K is the answer
for (int i=0; i<v; i++) {
for (int j=0; j<w; j++) {
if (A[v]+M[w] >= p && A[v]+M[w] <= q) {
++K;
}
}
}
As we can see the above code uses a loop inside a loop, thus making the time complexity of the program Ο(v×w), pretty slow for large arrays.
The question
Is there a fastest way to solve this problem?
Problem Summary: Given two arrays A and B with sizes v and w respectively, find the number of possible pairings of an element from A and an element from B such that the two elements have a sum that is >= p and <= q.
The simple, brute force algorithm is essentially what you have currently. The brute force algorithm would simply involve testing all possible pairs, which, as you said, would have a time complexity of O(v*w) because there are v ways to choose the first element and w ways to choose the second element when testing all the pairs.
As #thestruggler pointed out in their comment, sorting and binary search could be applied to create a significantly more efficient algorithm.
Let's say we sort B in ascending order. For the test case you provide, we would then have:
A = [9, 14, 5, 8, 12, 2, 16]
B = [2, 3, 6, 9, 10]
p = 21 and q = 24
Now, notice that for every element in a, we can calculate the range of elements in B that, when added to the element, would have a sum between p and q. We can actually find this range in O(logW) time by using what is called Binary Search. Specifically, if we were looking to pair the first number in A with numbers in B, we would binary search for the index of the first element that is >= 12 and then binary search for the index of the last element that is <= 15. The number of elements in B that would work in a pairing with the element from A is then just equal to 1 plus the difference between the two indexes.
Overall, this algorithm would have a complexity of O(WlogW + VlogW) (or O(VlogV + WlogV); if you want to go above and beyond your program could decide to sort the larger array to save time on testing). This is because sorting an array with N elements takes O(NlogN) time, and because each binary search over a sorted array with N elements takes O(logN).
This can also be solved in following way,
First sort both arrays,
[9, 14, 5, 8, 12, 2, 16] => [2, 5, 8, 9, 12, 14, 16]
[6, 2, 9, 3, 10] => [2, 3, 6, 9, 10]
Now iterate all elements of smaller array and do following,
[2, 3, 6, 9, 10],
current element is 2, subtract it with p, lets say it is num it means,
num = p - 2 = 21 - 2 = 19
Then all numbers in other array, grater than of equals to 19 will make sum 21 with 2. But no element in other array is grater than or equals to 19 It means by adding 2 with any element of other array can not grater than or equals to p,
Next element which is 3 and it also can not fulfill the requirement, same can be done with other element, so let's directly move to element 9 for explanation,
[2, 3, 6, 9, 10]
num = p - 9 = 21 - 9 = 12 and by getting lower bound of 12, we will get all numbers, those sum with 9 will be grater than or equal to p(21), as highlighted below,
[2, 5, 8, 9, 12, 14, 16],
Sum of these numbers with 9 is grater than or equals to p, now it is time to find how may of them will produce sum which is less then or equals to q, so to doing that we have to do following,
num = q - 9 = 24 - 9 = 15 and by finding upper bound of 15 will give all the numbers sum with 9 shall be less than of equals to q as highlighted below,
[2, 5, 8, 9, 12, 14, 16],
This way you can find all combinations having sum, p >= sum <= q,
#include <iostream>
#include <vector>
#include <algorithm>
std::size_t combinationCount(int p, int q, std::vector<int> arr1, std::vector<int> arr2){
std::sort(arr1.begin(), arr1.end());
std::sort(arr2.begin(), arr2.end());
std::vector<int>::const_iterator it1 = arr1.cbegin();
std::vector<int>::const_iterator endIt1 = arr1.cend();
std::vector<int>::const_iterator it2 = arr2.cbegin();
std::vector<int>::const_iterator endIt2 = arr2.cend();
if(arr2.size() < arr1.size()){
std::swap(it1, it2);
std::swap(endIt1, endIt2);
}
std::size_t count = 0;
for(; endIt1 != it1; ++it1){
int num = p - *it1;
std::vector<int>::const_iterator lowBoundOfPIt = std::lower_bound(it2, endIt2, num);
if(endIt2 != lowBoundOfPIt){
num = q - *it1;
std::vector<int>::const_iterator upBoundOfQIt = std::upper_bound(it2, endIt2, num);
count += (upBoundOfQIt - lowBoundOfPIt);
}
}
return count;
}
int main(){
std::cout<< "count = "<< combinationCount(21, 24, {9, 14, 5, 8, 12, 2, 16}, {6, 2, 9, 3, 10})<< '\n';
}
Output : 5

How to find longest consistent increment in a python list?

possible_list = []
bigger_list = []
new_list= [0, 25, 2, 1, 14, 1, 14, 1, 4, 6, 6, 7, 0, 10, 11]
for i in range(0,len(new_list)):
# if the next index is not greater than the length of the list
if (i + 1) < (len(new_list)):
#if the current value is less than the next value
if new_list[i] <= new_list[i+1]:
# add the current value to this sublist
possible_list.append(new_list[i])
# if the current value is greater than the next, close the list and append it to the lager list
bigger_list.append(possible_list)
print bigger_list
How do I find the longest consistent increment in the list called new_list?
I expect the result to be
[[0,2], [2], [1,14], [1,14], [1,4,6,6,7], [0,10,11]]
I can find the remaining solution from there myself.
One problem (but not the only one) with your code is that you are always adding the elements to the same possible_list, thus the lists in bigger_list are in fact all the same list!
Instead, I suggest using [-1] to access the last element of the list of subsequences (i.e. the one to append to) and [-1][-1] to access the last element of that subsequence (for comparing the current element to).
new_list= [0, 25, 2, 1, 14, 1, 14, 1, 4, 6, 6, 7, 0, 10, 11]
subseq = [[]]
for e in new_list:
if not subseq[-1] or subseq[-1][-1] <= e:
subseq[-1].append(e)
else:
subseq.append([e])
This way, subseq ends up the way you want it, and you can use max to get the longest one.
>>> subseq
[[0, 25], [2], [1, 14], [1, 14], [1, 4, 6, 6, 7], [0, 10, 11]]
>>> max(subseq, key=len)
[1, 4, 6, 6, 7]

Heapsort, heap "correctness"

My question is whether or not a heap can be "correct". I have an assignment asking me to do a heap sort but first build a heap using an existing array. If I look through the grader code it shows me that there is an exact answer. The way T implemented the heap build I get a slightly different answer but as far as i know is by definition a heap and therefore correct.
The "correct" array order is
{15, 12, 6, 11, 10, 2, 3, 1, 8}
but I get
{15, 12, 10, 11, 2, 6, 3, 1, 8}
The original vector is
{2, 8, 6, 1, 10, 15, 3, 12, 11}
void HeapSort::buildHeap(std::vector<CountedInteger>& vector)
{
std::vector<CountedInteger> temp;
for(int i = 0; i < vector.size(); i++)
{
temp.push_back(vector[i]);
fixDown(temp, i);
}
vector.swap(temp);
for(int i = 0; i < vector.size(); i++)
{
std::cout<< vector[i]<<std::endl;
}
}
void HeapSort::sortHeap(std::vector<CountedInteger>& vector)
{
}
inline unsigned int HeapSort::p(int i)
{
return ((i-1)/2);
}
void HeapSort::fixDown(std::vector<CountedInteger>& vector, int node)
{
if(p(node) == node) return;
if(vector[node] > vector[p(node)])
{
CountedInteger temp = vector[node];
vector[node] = vector[p(node)];
vector[p(node)] = temp;
fixDown(vector, p(node));
}
There are many possible ways to create a max-heap from an input. You give the example:
15, 12, 10, 11, 2, 6, 3, 1 8
15
12 10
11 2 6 3
1 8
It fulfills the heap criterion, so it is a correct max-heap. The other example is:
15, 12, 6, 11, 10, 2, 3, 1, 8
15
12 6
11 10 2 3
1 8
This also fulfills the heap criterion, so it is also a correct max-heap.
Max-heap criterion: Each node is greater than any of its child nodes.
A simpler example is 1, 2, 3, for which there are two heaps,
3 3
/ \ / \
1 2 2 1
Creating a heap out of an array is definitely an operation that can result in multiple different but valid heaps.
If you look at a trivial example, it is obvious that at least some subtrees of one node could switch positions. In the given example, 2 and 7 could switch positions. 25 and 1 could also switch positions. If the heap has minimum and maximum depth equal, then the subtrees of any node can switch positions.
If your grader is automatic, it should be implemented in a way to check the heap property and not the exact array. If your grader is a teacher, you should formally prove the correctness of your heap in front of them, which is trivial.

Python (2.x) list / sublist selection -1 weirdness

So I've been playing around with python and noticed something that seems a bit odd. The semantics of -1 in selecting from a list don't seem to be consistent.
So I have a list of numbers
ls = range(1000)
The last element of the list if of course ls[-1] but if I take a sublist of that so that I get everything from say the midpoint to the end I would do
ls[500:-1]
but this does not give me a list containing the last element in the list, but instead a list containing everything UP TO the last element. However if I do
ls[0:10]
I get a list containing also the tenth element (so the selector ought to be inclusive), why then does it not work for -1.
I can of course do ls[500:] or ls[500:len(ls)] (which would be silly). I was just wondering what the deal with -1 was, I realise that I don't need it there.
In list[first:last], last is not included.
The 10th element is ls[9], in ls[0:10] there isn't ls[10].
If you want to get a sub list including the last element, you leave blank after colon:
>>> ll=range(10)
>>> ll
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ll[5:]
[5, 6, 7, 8, 9]
>>> ll[:]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I get consistent behaviour for both instances:
>>> ls[0:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ls[10:-1]
[10, 11, 12, 13, 14, 15, 16, 17, 18]
Note, though, that tenth element of the list is at index 9, since the list is 0-indexed. That might be where your hang-up is.
In other words, [0:10] doesn't go from index 0-10, it effectively goes from 0 to the tenth element (which gets you indexes 0-9, since the 10 is not inclusive at the end of the slice).
It seems pretty consistent to me; positive indices are also non-inclusive. I think you're doing it wrong. Remembering that range() is also non-inclusive, and that Python arrays are 0-indexed, here's a sample python session to illustrate:
>>> d = range(10)
>>> d
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> d[9]
9
>>> d[-1]
9
>>> d[0:9]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> d[0:-1]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> len(d)
10
when slicing an array;
ls[y:x]
takes the slice from element y upto and but not including x. when you use the negative indexing it is equivalent to using
ls[y:-1] == ls[y:len(ls)-1]
so it so the slice would be upto the last element, but it wouldn't include it (as per the slice)
-1 isn't special in the sense that the sequence is read backwards, it rather wraps around the ends. Such that minus one means zero minus one, exclusive (and, for a positive step value, the sequence is read "from left to right".
so for i = [1, 2, 3, 4], i[2:-1] means from item two to the beginning minus one (or, 'around to the end'), which results in [3].
The -1th element, or element 0 backwards 1 is the last 4, but since it's exclusive, we get 3.
I hope this is somewhat understandable.