In Place rotation C++ Practice - c++

I have a working rotating function going for my "items" int array. The code below gets it done, except that im transferring values out unnecessarily. Im trying to acheive the "inplace" rotation. What I mean by that is where the ptrs would increment or decrement instead of grabbing values out of the array..By which I need to "up" the efficiency level in that way for this method..Any Suggestions?
void quack::rotate(int nRotations)
{
if ( count <= 1 ) return;
else // make sure our ptrs are where we want them.
{
intFrontPtr = &items[0].myInt;
intBackPtr = &items[count-1].myInt;
}
for (int temp = 0; nRotations != 0;)
{
if ( nRotations > 0 )
{
temp = *intFrontPtr;
*intFrontPtr = *intBackPtr;
*intBackPtr = temp; // Connect temps for the rotation
--intBackPtr; // Move left [...<-] into the array
}
else if ( nRotations < 0 )
{
temp = *intBackPtr;
*intBackPtr = *intFrontPtr;
*intFrontPtr = temp; // Connect temps for the rotation
++intFrontPtr; // Move right [->...] into the array
}
if ( intBackPtr == &items[0].myInt ||
intFrontPtr == &items[count-1].myInt )
{
intFrontPtr = &items[0].myInt;
intBackPtr = &items[count-1].myInt; // need to re-set
if ( nRotations > 0 ) nRotations--; // Which ways did we rotate?
else nRotations++;
}
}
}
Oh yes, Im trying to practice c++ and know their are many functions floating around that are programmed to do this already...Im trying to "build my own". I think i've got it down syntactically, but the efficiency is always where i struggle. As, a novice, I would greatly appreciate critisim towards this aspect..

There is an old trick for rotating elements in an array (I first saw it in Programming Pearls)
Say you want to rotate an array to the left by three elements.
First reverse the first three elements, next reverse the remaining elements, and then reverse the entire array.
Starting Array:
1 2 3 4 5 6 7
After reversing the first three elements
3 2 1 4 5 6 7
After reversing the remaining elements
3 2 1 7 6 5 4
Finally reverse the entire array to get the final rotated array
4 5 6 7 1 2 3
Reversing portions of the array can be done in place so you don't need any extra memory.

You can leave the data in place, and have a "base index" member to indicate where the array should start. You then need to use this to adjust the index when accessing the array. The array itself should be private, and only accessed through accessor functions that do the adjustment. Something like this:
class quack
{
public:
explicit quack(int size) : items(new Item[size]), size(size), base(0) {}
~quack() {delete [] items;}
void rotate(int n) {base = (base + n) % size;}
Item &operator[](int i) {return items[(base + i) % size];}
private:
quack(quack const&) = delete; // or implement these if you want
void operator=(quack const&) = delete; // the container to be copyable
Item *items;
int size;
int base;
};
although I'd call it something like RotatableArray, rather than quack.

As usual, if you really have to physically rotate the elements, the correct answer for C++ would be to use std::rotate, which does exactly what you want to do.
If you have to implement it manually (as a practice assignment), take a look at these slides for algorithms from John Bentley's "Programming Pearls".

doing the rotations one by one is really not the way to go. If you are doing anything more than 2 or 3 rotations it gets really slow really quick.
edit:
as a final thought... putting the elements in a (double) linked 'looped' list (so the final element points to the first), would require for a rotate to only move the head pointer a few elements. (The head pointer being a pointer to indicate which element in the looped list is the beginning).
this is by far the quickest (and easiest) way to do a rotate on a list of elements

Really the way to do it is to use indexes instead of pointers.
int to = 0;
int from = (to + nRotations) % count;
if (to == from)
return;
for (int i=0; i < count; i++) {
swap(from, to);
from = advance(from);
to = advance(to);
}
// ...
static inline int advance(int n, int count) { return (n + 1) % count; }

I may have an alternate solution to rotating the array inline. Rather than the old trick of reversing sets of elements, as proposed earlier, this approach works as follows:
Initialization:
(Note q = amount to shift left, n = length of array)
Determine the first source element, which is located at x1=q%n
The destination element is at x2=0
char, ch1, is the ar[x1] element
char, ch2, is the ar[x2] element
Loop on i=0 to n-1, where n = length of array
Overwrite the destination element, ar[x2] with ch1
Set ch1 = ch2
Set x1 = x2
Set x2 = x2 - q
If x2 is negative due to the above subtraction, add n to it
ch2 = ar[x2]
The following may help explain how this works.
Example, rotate to the left by 2 characters:
a b c d e f g
c d e f g a b
x1 ch1 x2 ch2
2 c 0 a
0 a 5 f
5 f 3 d
3 d 1 b
1 b 6 g
6 g 4 e
4 e 2 c
As you can see, this requires no more than n iterations, so it is linear time algorithm that also rotates inline (requires no additional storage other than the few temporary variables).
Here is a function that implements the above algorithm so you can try it out:
void rotate(char *ar, int q)
{
if (strlen(ar) < 2)
{
return;
}
if (q <= 0)
{
return;
}
char ch1;
char ch2;
int x1;
int x2;
int i;
int n;
n = strlen(ar);
q %= n;
if (q == 0)
{
return;
}
x1 = q;
ch1 = ar[x1];
x2 = 0;
ch2 = ar[x2];
for (i=0;i<n;i++)
{
ar[x2] = ch1;
ch1 = ch2;
x1 = x2;
x2 -= q;
if (x2 < 0)
{
x2 += n;
}
ch2 = ar[x2];
}
}

Here's one that I got by modifying the code here:
template<class It>
It rotate(It begin, It const middle, It end)
{
typename std::iterator_traits<It>::difference_type i = 0, j;
if (begin != middle && middle != end)
{
while ((i = std::distance(begin, middle)) !=
(j = std::distance(middle, end)))
{
It k = middle;
std::advance(
k,
std::max(typename std::iterator_traits<It>::difference_type(),
j - i));
std::swap_ranges(k, end, begin);
if (i > j) { std::advance(begin, j); }
else { std::advance(end, -i); }
}
}
return std::swap_ranges(middle - i, middle, middle);
}

Here is code for sdtom solution
void rotateArray(int arr[], int low, int high)
{
while (low<high) {
int temp = arr[low];
arr[low]=arr[high];
arr[high]=temp;
low++;
high--;
}
}
void rotate (int arr[], int k,int uperLimit)
{
rotateArray(arr,0,k);
rotateArray(arr,k+1,uperLimit-1);
rotateArray(arr,0,uperLimit-1);
}

https://stackoverflow.com/q/17119000/2383578 : This is somewhat similar to what is discussed here. Rotating the array by a particular amount.

There are many ways to do array rotation by d places.
Block swap algorithm.
Juggling Algorithm.
Reversal Algorithm.
The link below is from Programming Pearls pdf. Check this out. Explained very clearly with code.
http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf

Related

Partition for randomised quicksort (with few unique elements)

I've been tasked to write a partition function for a randomised quicksort with few elements (optimising it by including 3 partitions instead of 2). I've tried implementing my version of it, and have found that it doesn't pass the test cases.
However, by using a classmates' version of partition, it seems to work. Conceptually, I don't see the difference between his and mine, and I can't tell what is it with my version that causes it to break. I wrote it with the concept as him (I think), which involves using counters (j and k) to partition the arrays into 3.
I would greatly appreciate anybody that could point out why mine doesn't work, and what I should do to minimise the chances of these again. I feel like this learning point will be important to me as a developer, thank you!
For comparison, there will be 3 blocks of code, the snippet directly below will be my version of partition, following which will be my classmates' version and lastly will be the actual algorithm which runs our partition.
My version (Does not work)
vector<int> partition2(vector<int> &a, int l, int r) {
int x = a[l];
int j = l;
int k = r;
vector<int> m(2);
// I've tried changing i = l + 1
for (int i = l; i <= r; i++) {
if (a[i] < x) {
swap(a[i], a[j]);
j++;
}
else if (a[i] > x) {
swap(a[i], a[k]);
k--;
}
}
// I've tried removing this
swap(a[l], a[j]);
m[0] = j - 1;
m[1] = k + 1;
return m;
}
My classmates' (which works)
vector<int> partition2(vector<int> &a, int l, int r) {
int x = a[l];
int p_l = l;
int i = l;
int p_e = r;
vector<int> m(2);
while (i <= p_e) {
if (a[i] < x) {
swap(a[p_l], a[i]);
p_l++;
i++;
} else if (a[i] == x) {
i++;
} else {
swap(a[i], a[p_e]);
p_e -= 1;
}
m[0] = p_l - 1;
m[1] = p_e + 1;
}
return m;
}
Actual quick sort algorithm
void randomized_quick_sort(vector<int> &a, int l, int r) {
if (l >= r) {
return;
}
int k = l + rand() % (r - l + 1);
swap(a[l], a[k]);
vector<int> m = partition2(a, l, r);
randomized_quick_sort(a, l, m[0]);
randomized_quick_sort(a, m[1], r);
}
The difference between the two functions for three-way partition is that your code advances i in each pass through the loop, but your classmate's function advances i only when the value at position i is less or equal to the pivot.
Let's go through an example array. The first value, 3, is the pivot. The letters indicate the positions of the variables after each pass through the loop.
j k
3 1 5 2 4
i
The next value is smaller: swap it to the left side and advance j:
j k
1 3 5 2 4
i
The next value, 5, is greater, so it goes to the right:
j k
1 3 4 2 5
i
That's the bad move: Your i has now skipped over the 4, which must go to the right part, too. Your classmate's code does not advance the i here and catches the 4 in the next pass.
Your loop has some invariants, things that must be true after all passes:
All items with an index lower than i are smaller than the pivot.
All items with an index greater than k are greater than the pivot.
All items with an index from j to i - 1 are equal to the pivot.
All items from i to k have not yet been processed.
You can also determine the loop conditions from that:
The pivot is the leftmost element by definition, because the quicksort function swaps it there. It must belong to the group of elements that are equal to the pivot, so you can start your loop at l + 1.
All items starting from k are already in the correct part of the array. That means that you can stop when i reaches k. Going further will needlessly swap elements around inside the "greater than" partition and also move k, which will return wrong partition boundaries.

String decode: looking for a better approach

I have worked out a O(n square) solution to the problem. I was wondering about a better solution to this. (this is not a homework/interview problem but something I do out of my own interest, hence sharing here):
If a=1, b=2, c=3,….z=26. Given a string, find all possible codes that string
can generate. example: "1123" shall give:
aabc //a = 1, a = 1, b = 2, c = 3
kbc // since k is 11, b = 2, c= 3
alc // a = 1, l = 12, c = 3
aaw // a= 1, a =1, w= 23
kw // k = 11, w = 23
Here is my code to the problem:
void alpha(int* a, int sz, vector<vector<int>>& strings) {
for (int i = sz - 1; i >= 0; i--) {
if (i == sz - 1) {
vector<int> t;
t.push_back(a[i]);
strings.push_back(t);
} else {
int k = strings.size();
for (int j = 0; j < k; j++) {
vector<int> t = strings[j];
strings[j].insert(strings[j].begin(), a[i]);
if (t[0] < 10) {
int n = a[i] * 10 + t[0];
if (n <= 26) {
t[0] = n;
strings.push_back(t);
}
}
}
}
}
}
Essentially the vector strings will hold the sets of numbers.
This would run in n square. I am trying my head around at least an nlogn solution.
Intuitively tree should help here, but not getting anywhere post that.
Generally, your problem complexity is more like 2^n, not n^2, since your k can increase with every iteration.
This is an alternative recursive solution (note: recursion is bad for very long codes). I didn't focus on optimization, since I'm not up to date with C++X, but I think the recursive solution could be optimized with some moves.
Recursion also makes the complexity a bit more obvious compared to the iterative solution.
// Add the front element to each trailing code sequence. Create a new sequence if none exists
void update_helper(int front, std::vector<std::deque<int>>& intermediate)
{
if (intermediate.empty())
{
intermediate.push_back(std::deque<int>());
}
for (size_t i = 0; i < intermediate.size(); i++)
{
intermediate[i].push_front(front);
}
}
std::vector<std::deque<int>> decode(int digits[], int count)
{
if (count <= 0)
{
return std::vector<std::deque<int>>();
}
std::vector<std::deque<int>> result1 = decode(digits + 1, count - 1);
update_helper(*digits, result1);
if (count > 1 && (digits[0] * 10 + digits[1]) <= 26)
{
std::vector<std::deque<int>> result2 = decode(digits + 2, count - 2);
update_helper(digits[0] * 10 + digits[1], result2);
result1.insert(result1.end(), result2.begin(), result2.end());
}
return result1;
}
Call:
std::vector<std::deque<int>> strings = decode(codes, size);
Edit:
Regarding the complexity of the original code, I'll try to show what would happen in the worst case scenario, where the code sequence consists only of 1 and 2 values.
void alpha(int* a, int sz, vector<vector<int>>& strings)
{
for (int i = sz - 1;
i >= 0;
i--)
{
if (i == sz - 1)
{
vector<int> t;
t.push_back(a[i]);
strings.push_back(t); // strings.size+1
} // if summary: O(1), ignoring capacity change, strings.size+1
else
{
int k = strings.size();
for (int j = 0; j < k; j++)
{
vector<int> t = strings[j]; // O(strings[j].size) vector copy operation
strings[j].insert(strings[j].begin(), a[i]); // strings[j].size+1
// note: strings[j].insert treated as O(1) because other containers could do better than vector
if (t[0] < 10)
{
int n = a[i] * 10 + t[0];
if (n <= 26)
{
t[0] = n;
strings.push_back(t); // strings.size+1
// O(1), ignoring capacity change and copy operation
} // if summary: O(1), strings.size+1
} // if summary: O(1), ignoring capacity change, strings.size+1
} // for summary: O(k * strings[j].size), strings.size+k, strings[j].size+1
} // else summary: O(k * strings[j].size), strings.size+k, strings[j].size+1
} // for summary: O(sum[i from 1 to sz] of (k * strings[j].size))
// k (same as string.size) doubles each iteration => k ends near 2^sz
// string[j].size increases by 1 each iteration
// k * strings[j].size increases by ?? each iteration (its getting huge)
}
Maybe I made a mistake somewhere and if we want to play nice we can treat a vector copy as O(1) instead of O(n) in order to reduce complexity, but the hard fact remains, that the worst case is doubling outer vector size in each iteration (at least every 2nd iteration, considering the exact structure of the if conditions) of the inner loop and the inner loop depends on that growing vector size, which makes the whole story at least O(2^n).
Edit2:
I figured out the result complexity (the best hypothetical algoritm still needs to create every element of the result, so result complexity is like a lower bound to what any algorithm can archieve)
Its actually following the Fibonacci numbers:
For worst case input (like only 1s) of size N+2 you have:
size N has k(N) elements
size N+1 has k(N+1) elements
size N+2 is the combination of codes starting with a followed by the combinations from size N+1 (a takes one element of the source) and the codes starting with k, followed by the combinations from size N (k takes two elements of the source)
size N+2 has k(N) + k(N+1) elements
Starting with size 1 => 1 (a) and size 2 => 2 (aa or k)
Result: still exponential growth ;)
Edit3:
Worked out a dynamic programming solution, somewhat similar to your approach with reverse iteration over the code array and kindof optimized in its vector usage, based on the properties explained in Edit2.
The inner loop (update_helper) is still dominated by the count of results (worst case Fibonacci) and a few outer loop iterations will have a decent count of sub-results, but at least the sub-results are reduced to a pointer to some intermediate node, so copying should be pretty efficient. As a little bonus, I switched the result from numbers to characters.
Another edit: updated code with range 0 - 25 as 'a' - 'z', fixed some errors that led to wrong results.
struct const_node
{
const_node(char content, const_node* next)
: next(next), content(content)
{
}
const_node* const next;
const char content;
};
// put front in front of each existing sub-result
void update_helper(int front, std::vector<const_node*>& intermediate)
{
for (size_t i = 0; i < intermediate.size(); i++)
{
intermediate[i] = new const_node(front + 'a', intermediate[i]);
}
if (intermediate.empty())
{
intermediate.push_back(new const_node(front + 'a', NULL));
}
}
std::vector<const_node*> decode_it(int digits[9], size_t count)
{
int current = 0;
std::vector<const_node*> intermediates[3];
for (size_t i = 0; i < count; i++)
{
current = (current + 1) % 3;
int prev = (current + 2) % 3; // -1
int prevprev = (current + 1) % 3; // -2
size_t index = count - i - 1; // invert direction
// copy from prev
intermediates[current] = intermediates[prev];
// update current (part 1)
update_helper(digits[index], intermediates[current]);
if (index + 1 < count && digits[index] &&
digits[index] * 10 + digits[index + 1] < 26)
{
// update prevprev
update_helper(digits[index] * 10 + digits[index + 1], intermediates[prevprev]);
// add to current (part 2)
intermediates[current].insert(intermediates[current].end(), intermediates[prevprev].begin(), intermediates[prevprev].end());
}
}
return intermediates[current];
}
void cleanupDelete(std::vector<const_node*>& nodes);
int main()
{
int code[] = { 1, 2, 3, 1, 2, 3, 1, 2, 3 };
int size = sizeof(code) / sizeof(int);
std::vector<const_node*> result = decode_it(code, size);
// output
for (size_t i = 0; i < result.size(); i++)
{
std::cout.width(3);
std::cout.flags(std::ios::right);
std::cout << i << ": ";
const_node* item = result[i];
while (item)
{
std::cout << item->content;
item = item->next;
}
std::cout << std::endl;
}
cleanupDelete(result);
}
void fillCleanup(const_node* n, std::set<const_node*>& all_nodes)
{
if (n)
{
all_nodes.insert(n);
fillCleanup(n->next, all_nodes);
}
}
void cleanupDelete(std::vector<const_node*>& nodes)
{
// this is like multiple inverse trees, hard to delete correctly, since multiple next pointers refer to the same target
std::set<const_node*> all_nodes;
for each (auto var in nodes)
{
fillCleanup(var, all_nodes);
}
nodes.clear();
for each (auto var in all_nodes)
{
delete var;
}
all_nodes.clear();
}
A drawback of the dynamically reused structure is the cleanup, since you wanna be careful to delete each node only once.

Maximum value of M digits out of N digits [duplicate]

This question already has answers here:
How to get the least number after deleting k digits from the input number
(11 answers)
Closed 6 years ago.
I am trying to code a program that can do something like this:
in:
5 4
1 9 9 9 0
out:
9990
and i have a problem. It doesnt work on any set of numbers. For example it works for the one above, but it doesnt work for this one:
in:
15 9
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
out: 988887814
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
I did this with a vector approach and it works for any set of numbers, but i'm trying to do it a stack for a better complexity.
EDIT ---- MODIFIED FOR STD::STACK
Code for method using stack:
#include <iostream>
#include <fstream>
#include <stack>
using namespace std;
ifstream in("trompeta.in");
ofstream out("trompeta.out");
void reverseStack(stack<char> st) {
if(!st.empty())
{
char x = st.top();
st.pop();
reverseStack(st);
out<<x;
}
return;
}
int main()
{
int n,m,count=1;
stack <char> st;
char x;
in>>n>>m;
in>>x;
st.push(x);
for(int i=1; i<n; i++)
{
in>>x;
if(st.top()<x && count+n-i-1>=m)
{
st.pop();
st.push(x);
}
else
{
st.push(x);
count++;
if (count>m-1) break;
}
};
reverseStack(st);
}
Code for method using vectors:
#include <iostream>
#include <fstream>
using namespace std;
ifstream in ( "trompeta.in" );
ofstream out ( "trompeta.out" );
int main ()
{
int i = 0, N, M, max, j, p = 0, var;
in >> N >> M;
char* v = new char[N];
char* a = new char[M];
in >> v;
var = M;
max = v[0];
for ( i = 0; i < M; i++ )
{
for ( j = p ; j < N-var+1; j++ )
{
if ( v[j] > max )
{
max = v[j];
p = j;
}
}
var--;
a[i] = max;
max = v[p+1];
p = p+1;
}
for ( i = 0; i < M; i++ )
out << a[i]-'0';
}
Can any1 help me to get the STACK code working?
Using the fact that the most significant digit completely trumps all other digets except in place of a tie, I would look at the first (N-M+1) digits, find the largest single digit in that range.
If it occurs once, the first digit is locked in. Discard the digits which occur prior to that position, and you repeat for "maximum value of M-1 numbers of out N-position" to find the remaining digits of the answer. (or N-position-1, if position is zero based)
If it occurs multiple times, then recursively find "maximum value of M-1 numbers out of N-position" for each, then select the largest single result from these. There can be at most N such matches.
I forgot to mention, if N==M, you are also done.
proof of recursion:
Computing the value of the sub-match will always select M-1 digits. When M is 1, you only need to select the largest of a few positions, and have no more recursion. This is true for both cases. Also the "select from" steps always contain no more than N choices, because they are always based on selecting one most significant digit.
------------------ how you might do it with a stack ----------------
An actual implementation using a stack would be based on an object which contains the entire state of the problem, at each step, like so:
struct data { // require: n == digits.size()
int n, m;
std::string digits;
bool operator<(const data &rhs){ return digits < rhs.digits; }
};
The point of this is not just to store the original problem, but to have a way to represent any subproblem, which you can push and pop on a stack. The stack itself is not really important, here, because it is used to pick the one best result within a specific layer. Recursion handles most of the work.
Here is the top level function which hides the data struct:
std::string select_ordered_max(int n, int m, std::string digits) {
if (n < m || (int)digits.size() != n)
return "size wrong";
data d{ n, m, digits };
data answer = select_ordered_max(d);
return answer.digits;
}
and a rough pseudocode of the recursive workhorse
data select_ordered_max(data original){
// check trivial return conditions
// determine char most_significant
// push all subproblems that satisfy most_significant
//(special case where m==1)
// pop subproblems, remembering best
return answer {original.m, original.m, std::string(1, most_significant) + best_submatch.digits };
}
String comparison works on numbers when you only compare strings of the exact same length, which is the case here.
Yes, I know having n and m is redundant with digits.size(), but I didn't want to work too hard. Including it twice simplified some recursion checks. The actual implementation only pushed a candidate to the stack if it passed the max digit check for that level of recursion. This allowed me to get the correct 9 digit answer from 15 digits of input with only 28 candidates pushed to the stack (and them popped during max-select).
Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
const size_t M where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
You just always want to pick the highest value most significant number remaining. So we'll keep an end iterator to prevent us from picking a digit that wouldn't leave us with enough digits to finish the number, and use max_element to select:
const int pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
auto maximum = 0;
auto end = prev(cend(v), M - 1);
auto it = max_element(cbegin(v), end);
for (auto i = M - 1; i > 0; --i) {
maximum += *it * pow10[i];
advance(end, 1);
it = max_element(next(it), end);
}
maximum += *it;
Live Example
This code depends upon M being greater than 0 and less than N and less than log10(numeric_limits<int>::max())
EDIT: Sad to say this solves the consecutive digits problem, after edits the question wants subsequent digits, but not necessarily consecutive
So the little known numeric library provides inner_product which seems like just the tool for this job. Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
vector<int> foo(M) where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
We'll use foo in the inner_product, initializing it with decreasing powers of 10:
generate(begin(foo), end(foo), [i=int{1}]() mutable {
auto result = i;
i *= 10;
return result; });
We can then use this in a loop:
auto maximum = 0;
for (auto it = prev(rend(v), size(foo) + 1); it != rbegin(v); advance(it, -1)) {
maximum = max<int>(inner_product(cbegin(foo), cend(foo), it, 0), maximum);
}
maximum = max<int>(inner_product(cbegin(foo), cend(foo), rbegin(v), 0), maximum);
Live Example
To use it's initialization requires that your initial M was smaller than N, so you may want to assert that or something.
--EDITED--
here's my suggestion with STACK based on my previous suggestion using vector
findMaxValueOutOfNDigits(stackInput, M, N)
{
// stackInput = [2, 9, 3, 6, 5, 8, 8, 8, 8, 7, 2, 2, 8, 1, 4]
// *where 4 was the first element to be inserted and 2 was the last to be inserted
// if the sequence is inverted, you can quickly fix it by doing a "for x = 0; x < stack.length; x++ { newStack.push(stack.pop()) }"
currentMaxValue = 0
for i = 0; i < (M - N + 1); i++
{
tempValue = process(stackInput, M, N)
stackInput.pop()
if (tempValue > currentMaxValue)
currentMaxValue = tempValue
}
return currentMaxValue
}
process(stackInput, M, N)
{
tempValue = stackInput.pop() * 10^(N - 1)
*howManyItemsCanILook = (M - N + 1)
for y = (N - 2); y == 0; y++
{
currentHowManyItemsCanILook = *howManyItemsCanILook
tempValue = tempValue + getValue(stackInput, *howManyItemsCanILook) * 10^(y)
*howManyItemsCanILook = *howManyItemsCanILook - 1
for x = 0; x < (currentHowManyItemsCanILook - *howManyItemsCanILook); x++
{
stackInput.pop()
}
}
return tempValue
}
getValue(stackInput, *howManyItemsCanILook)
{
currentMaxValue = stackInput.pop()
if (currentMaxValue == 9)
return 9
else
{
goUntil = *howManyItemsCanILook
for i = 0; i < goUntil; i++
{
*howManyItemsCanILook = *howManyItemsCanILook - 1
tempValue = stackInput.pop()
if (currentMaxValue < tempValue)
{
currentMaxValue = tempValue
if (currentMaxValue == 9)
return currentMaxValue
}
}
return currentMaxValue
}
}
note: where *howManyItemsCanILook is passed by reference
I hope this helps

BFS maze help c++

I am attempting to make a maze-solver using a Breadth-first search, and mark the shortest path using a character '*'
The maze is actually just a bunch of text. The maze consists of an n x n grid, consisting of "#" symbols that are walls, and periods "." representing the walkable area/paths. An 'S' denotes start, 'F' is finish. Right now, this function does not seem to be finding the solution (it thinks it has the solution even when one is impossible). I am checking the four neighbors, and if they are 'unfound' (-1) they are added to the queue to be processed.
The maze works on several mazes, but not on this one:
...###.#....
##.#...####.
...#.#.#....
#.####.####.
#F..#..#.##.
###.#....#S.
#.#.####.##.
....#.#...#.
.####.#.#.#.
........#...
What could be missing in my logic?
int mazeSolver(char *maze, int rows, int cols)
{
int start = 0;
int finish = 0;
for (int i=0;i<rows*cols;i++) {
if (maze[i] == 'S') { start=i; }
if (maze[i] == 'F') { finish=i; }
}
if (finish==0 || start==0) { return -1; }
char* bfsq;
bfsq = new char[rows*cols]; //initialize queue array
int head = 0;
int tail = 0;
bool solved = false;
char* prd;
prd = new char[rows*cols]; //initialize predecessor array
for (int i=0;i<rows*cols;i++) {
prd[i] = -1;
}
prd[start] = -2; //set the start location
bfsq[tail] = start;
tail++;
int delta[] = {-cols,-1,cols,+1}; // North, West, South, East neighbors
while(tail>head) {
int front = bfsq[head];
head++;
for (int i=0; i<4; i++) {
int neighbor = front+delta[i];
if (neighbor/cols < 0 || neighbor/cols >= rows || neighbor%cols < 0 || neighbor%cols >= cols) {
continue;
}
if (prd[neighbor] == -1 && maze[neighbor]!='#') {
prd[neighbor] = front;
bfsq[tail] = neighbor;
tail++;
if (maze[neighbor] == 'F') { solved = true; }
}
}
}
if (solved == true) {
int previous = finish;
while (previous != start) {
maze[previous] = '*';
previous = prd[previous];
}
maze[finish] = 'F';
return 1;
}
else { return 0; }
delete [] prd;
delete [] bfsq;
}
Iterating through neighbours can be significantly simplified(I know this is somewhat similar to what kobra suggests but it can be improved further). I use a moves array defining the x and y delta of the given move like so:
int moves[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
Please note that not only tis lists all the possible moves from a given cell but it also lists them in clockwise direction which is useful for some problems.
Now to traverse the array I use a std::queue<pair<int,int> > This way the current position is defined by the pair of coordinates corresponding to it. Here is how I cycle through the neighbours of a gien cell c:
pair<int,int> c;
for (int l = 0;l < 4/*size of moves*/;++l){
int ti = c.first + moves[l][0];
int tj = c.second + moves[l][1];
if (ti < 0 || ti >= n || tj < 0 || tj >= m) {
// This move goes out of the field
continue;
}
// Do something.
}
I know this code is not really related to your code, but as I am teaching this kind of problems trust me a lot of students were really thankful when I showed them this approach.
Now back to your question - you need to start from the end position and use prd array to find its parent, then find its parent's parent and so on until you reach a cell with negative parent. What you do instead considers all the visited cells and some of them are not on the shortest path from S to F.
You can break once you set solved = true this will optimize the algorithm a bit.
I personally think you always find a solution because you have no checks for falling off the field. (the if (ti < 0 || ti >= n || tj < 0 || tj >= m) bit in my code).
Hope this helps you and gives you some tips how to improve your coding.
A few comments:
You can use queue container in c++, its much more easier in use
In this task you can write something like that:
int delta[] = {-1, cols, 1 -cols};
And then you simple can iterate through all four sides, you shouldn't copy-paste the same code.
You will have problems with boundaries of your array. Because you are not checking it.
When you have founded finish you should break from cycle
And in last cycle you have an error. It will print * in all cells in which you have been (not only in the optimal way). It should look:
while (finish != start)
{
maze[finish] = '*';
finish = prd[finish];
}
maze[start] = '*';
And of course this cycle should in the last if, because you don't know at that moment have you reach end or not
PS And its better to clear memory which you have allocate in function

weighted RNG speed problem in C++

Edit: to clarify, the problem is with the second algorithm.
I have a bit of C++ code that samples cards from a 52 card deck, which works just fine:
void sample_allcards(int table[5], int holes[], int players) {
int temp[5 + 2 * players];
bool try_again;
int c, n, i;
for (i = 0; i < 5 + 2 * players; i++) {
try_again = true;
while (try_again == true) {
try_again = false;
c = fast_rand52();
// reject collisions
for (n = 0; n < i + 1; n++) {
try_again = (temp[n] == c) || try_again;
}
temp[i] = c;
}
}
copy_cards(table, temp, 5);
copy_cards(holes, temp + 5, 2 * players);
}
I am implementing code to sample the hole cards according to a known distribution (stored as a 2d table). My code for this looks like:
void sample_allcards_weighted(double weights[][HOLE_CARDS], int table[5], int holes[], int players) {
// weights are distribution over hole cards
int temp[5 + 2 * players];
int n, i;
// table cards
for (i = 0; i < 5; i++) {
bool try_again = true;
while (try_again == true) {
try_again = false;
int c = fast_rand52();
// reject collisions
for (n = 0; n < i + 1; n++) {
try_again = (temp[n] == c) || try_again;
}
temp[i] = c;
}
}
for (int player = 0; player < players; player++) {
// hole cards according to distribution
i = 5 + 2 * player;
bool try_again = true;
while (try_again == true) {
try_again = false;
// weighted-sample c1 and c2 at once
// h is a number < 1325
int h = weighted_randi(&weights[player][0], HOLE_CARDS);
// i2h uses h and sets temp[i] to the 2 cards implied by h
i2h(&temp[i], h);
// reject collisions
for (n = 0; n < i; n++) {
try_again = (temp[n] == temp[i]) || (temp[n] == temp[i+1]) || try_again;
}
}
}
copy_cards(table, temp, 5);
copy_cards(holes, temp + 5, 2 * players);
}
My problem? The weighted sampling algorithm is a factor of 10 slower. Speed is very important for my application.
Is there a way to improve the speed of my algorithm to something more reasonable? Am I doing something wrong in my implementation?
Thanks.
edit: I was asked about this function, which I should have posted, since it is key
inline int weighted_randi(double *w, int num_choices) {
double r = fast_randd();
double threshold = 0;
int n;
for (n = 0; n < num_choices; n++) {
threshold += *w;
if (r <= threshold) return n;
w++;
}
// shouldn't get this far
cerr << n << "\t" << threshold << "\t" << r << endl;
assert(n < num_choices);
return -1;
}
...and i2h() is basically just an array lookup.
Your reject collisions are turning an O(n) algorithm into (I think) an O(n^2) operation.
There are two ways to select cards from a deck: shuffle and pop, or pick sets until the elements of the set are unique; you are doing the latter which requires a considerable amount of backtracking.
I didn't look at the details of the code, just a quick scan.
you could gain some speed by replacing the all the loops that check if a card is taken with a bit mask, eg for a pool of 52 cards, we prevent collisions like so:
DWORD dwMask[2] = {0}; //64 bits
//...
int nCard;
while(true)
{
nCard = rand_52();
if(!(dwMask[nCard >> 5] & 1 << (nCard & 31)))
{
dwMask[nCard >> 5] |= 1 << (nCard & 31);
break;
}
}
//...
My guess would be the memcpy(1326*sizeof(double)) within the retry-loop. It doesn't seem to change, so should it be copied each time?
Rather than tell you what the problem is, let me suggest how you can find it. Either 1) single-step it in the IDE, or 2) randomly halt it to see what it's doing.
That said, sampling by rejection, as you are doing, can take an unreasonably long time if you are rejecting most samples.
Your inner "try_again" for loop should stop as soon as it sets try_again to true - there's no point in doing more work after you know you need to try again.
for (n = 0; n < i && !try_again; n++) {
try_again = (temp[n] == temp[i]) || (temp[n] == temp[i+1]);
}
Answering the second question about picking from a weighted set also has an algorithmic replacement that should be less time complex. This is based on the principle of that which is pre-computed does not need to be re-computed.
In an ordinary selection, you have an integral number of bins which makes picking a bin an O(1) operation. Your weighted_randi function has bins of real length, thus selection in your current version operates in O(n) time. Since you don't say (but do imply) that the vector of weights w is constant, I'll assume that it is.
You aren't interested in the width of the bins, per se, you are interested in the locations of their edges that you re-compute on every call to weighted_randi using the variable threshold. If the constancy of w is true, pre-computing a list of edges (that is, the value of threshold for all *w) is your O(n) step which need only be done once. If you put the results in a (naturally) ordered list, a binary search on all future calls yields an O(log n) time complexity with an increase in space needed of only sizeof w / sizeof w[0].