-
-
Save andrewljohnson/dda1eb62306b31112bd05ee5df6f1c5f to your computer and use it in GitHub Desktop.
/* | |
This method prints all possible blocks, recursively. | |
For example, if you have blockers A & B, and attacker C, there are three posible blocks. | |
No blockers: | |
A: | |
B: | |
C blocks A: | |
A: C | |
B: | |
C blocks B | |
A: | |
B: C | |
defenders is a vector of possible defender IDs (ints) | |
indexOfDefender is which ID in defenders is being grouped into a block on this iteration | |
blockAssignments is a vector of int vectors, where each vector represents an attacker than can have 0 or more blockers | |
FIRST ITERATION: | |
The first time this method is called, blockAssignments is a vector of empty vectors. | |
This is a valid move and the empty vector of vectors gets printed - this means none of the attackers is blocked. | |
NEXT ITERATION: | |
->If defenders is length 0, there are no other possible blocks and it returns, having printed the only valid move (i.e. no blocks). | |
->If defenders is greater than length 0, the defenders[indexOfDefender] is pushed into a vector in blockAssignments. | |
Then the function calls itself, this time with blockAssignments not empty, and indexOfDefender incremented. | |
On this recursive call, it prints blockAssignments which now has one int in one of the vectors. | |
If there is only one possible blocker, then it returns. Then in the outer call, the defender gets popped out of blockAssignment, then pushed into the next blockAssignment vector, and recurses. | |
If there is more than one blockers, it now loops within the inner call to add the other defenders into blockAsssignments. | |
*/ | |
void groupDefenders(vector<vector<int>> blockAssignments, vector<int> defenders, int indexOfDefender) { | |
int x = 0; | |
for (vector<int> attackerBucket:blockAssignments) { | |
cout << x << ": "; | |
for (int defender:attackerBucket) { | |
cout << defender << " "; | |
} | |
cout << "\n"; | |
x+= 1; | |
} | |
if(indexOfDefender == defenders.size()) { | |
return; | |
} | |
for(int v=0; v<blockAssignments.size();++v) { | |
vector<int> attacker = blockAssignments[v]; | |
attacker.push_back(defenders[indexOfDefender]); | |
blockAssignments[v] = attacker; | |
groupDefenders(blockAssignments, defenders, indexOfDefender+1); | |
attacker.pop_back(); | |
blockAssignments[v] = attacker; | |
} | |
} |
so I would describe this function as like... print out all ways for these attackers to be blocked. blockAssignments contains data for all the attackers and some defenders for which a block has already been chosen. defenders and indexOfDefender specify a number of defenders that could block any of the attackers. this method iterates over all ways to choose blocks for the remaining defenders.
so at that point, I think understanding this function comes down to understanding why the logic in that last for-loop works. you could comment it, but really the idea is that you're going to choose all the possible ways that defenders[indexOfDefender] can be allocated, and print out each of them.
it would be more c++ ish I think if you represented a set of defenders with begin and end iterators rather than defenders & indexOfDefender
there's also something going wrong when you have to constantly be setting blockAssignments[v] = attacker
- you shouldn't normally have to do this. blockAssignments[v]
should give you a reference
there's also something going wrong when you have to constantly be setting blockAssignments[v] = attacker - you shouldn't normally have to do this. blockAssignments[v] should give you a reference
Hmm, this works:
for (int v=0; v<blockAssignments.size();++v) {
blockAssignments[v].push_back(defenders[indexOfDefender]);
groupDefenders(blockAssignments, defenders, indexOfDefender+1);
blockAssignments[v].pop_back();
}
And this works with the &:
for(int v=0; v<blockAssignments.size();++v) {
vector<int>& attacker = blockAssignments[v];
attacker.push_back(defenders[indexOfDefender]);
groupDefenders(blockAssignments, defenders, indexOfDefender+1);
attacker.pop_back();
}
But this doesn't, because I guess it makes a copy? This not working is why I added the assignments you commented on.
for(int v=0; v<blockAssignments.size();++v) {
vector<int> attacker = blockAssignments[v];
attacker.push_back(defenders[indexOfDefender]);
groupDefenders(blockAssignments, defenders, indexOfDefender+1);
attacker.pop_back();
}
Yeah exactly - the line vector<int> attacker = blockAssignments[v]
is doing a copy. Any time you just assign a vector to another vector it makes a copy. So you don't want to do that, you want to use one of the other two formulations.
I think you want blockAssignments and defenders to be
const blah&
so that it doesn't do an extraneous copy