Checking for valid moves in Reversi for all 8 directions - c

I have a function to check the valid moves in my reversi game. I look at the unoccupied spaces, and check if an adjacent space in any 8 directions are the opposite piece. (If I'm black, I search for white) Now, if I find a piece that's adjacent, I should keep looking towards that direction and see if my own piece is at the end, then I return true, else if its an unoccupied space or off the board boundaries, I return false.
My function doesn't seem to work properly as I print out the wrong moves.
bool checkLegalInDirection(char boardgame[26][26], int size, int row, int col, char color) {
int currentRow, currentCol;
for (int deltaRow = -1; deltaRow < 2; deltaRow++) {
for (int deltaCol = -1; deltaCol < 2; deltaCol++) {
if (deltaRow == 0 && deltaCol == 0) {
break;
} else {
row = row + deltaRow;
col = col + deltaCol;
if (positionInBounds(size, row, col)) {
while (boardgame[row][col] == OppositeColor(color)) {
currentRow = row + deltaRow;
currentCol = col + deltaCol;
if (positionInBounds(size, currentRow, currentCol)) {
if (boardgame[currentRow][currentCol] == color) {
return true;
} else {
return false;
}
}
}
}
}
}
}
}
deltaRow and deltaCol are the increments that go in each direction and add one time to keep searching in a specified location. PositioninBounds is a function I have to make sure my searches are within the board boundaries. My deltarow and deltacol cannot be both 0 at the same time, so somehow I need to skip that step, (which I probably did wrong). Oppositecolor is a function that returns me the opposite color of my own piece.

I think your code has multiple mistakes.
Your code is incorrectly breaking the for loop when you should be continuing with the next iteration (as mentioned by chux).
Change...
if (deltaRow == 0 && deltaCol == 0) {
break;
} else {
...
}
to either chux's suggestion...
if (deltaRow == 0 && deltaCol == 0) {
continue;
} else {
...
}
or to an even simpler solution...
if (deltaRow != 0 || deltaCol != 0) {
...
}
Inside the deltaRow/deltaCol loops, your code is incorrectly modifying the original row/col values which your code will need in later loop iterations.
You can change...
row = row + deltaRow;
col = col + deltaRow;
to...
currentRow = row + deltaRow;
currentCol = col + deltaRow;
Inside the while loop, your code is incorrectly returning false. You can not return false until you have completed all the for loops.
Before entering the while loop, you need to check that the adjacent space is in bounds and opposite color...
if (positionInBounds(size, currentRow, currentCol) && boardgame[currentRow][currentCol] == OppositeColor(color)) {
If so, then skip over all adjacent opposite colors...
while (positionInBounds(size, currentROw, currentColor) && boadgame[currentRow][currentCol] == OppositeColor(color)) {
{
currentRow = currentRow + deltaRow;
currentCol = currentCol + deltaCol;
}
After you have skipped over opposite colors then you need to check for same color. If so then return true.
if (positionInBOunds(size, currentRow, currentCol) && boardgame[currentRow][currentCol] == color) {
return true;
}
You code should only return false after checking all directions...
for (int deltaRow = -1; deltaRow < 2; deltaRow++) {
for (int deltaCol = -1; deltaCol < 2; deltaCol++) {
....
}
}
return false;

Related

C Return Going Back To Loop Predicate Not Ending The Function

Hello I have the following code in C and when the code clause:
if (idx - 1 == 0) {
return opening_address;
}
executes it returns to the While loop's predicate rather than actually returning and ending the function. The code does get hit and likewise for the other return statement in the loop and both have the same behavior and basically do a continue action.
int find_smallest_free_block(int block_size) {
int opening_address = 0;
int idx = 0;
while (idx + lowestPower <= highestPower) {
if (powers[idx].hasHoles) {
if (powers[idx].size > block_size) {
opening_address = powers[idx].head_p->start_address;
// Add 2 holes to the next power down
int try = 0;
try = addHole(idx - 1, powers[idx].head_p->start_address, powers[idx].head_p->end_address / 2);
try = addHole(idx - 1, powers[idx].head_p->end_address / 2, powers[idx].head_p->end_address);
// Remove hole at power
try = removeHole(idx, powers[idx].head_p->start_address);
if (idx - 1 == 0) {
return opening_address; // cant make holes at lowest level
}
idx -= 1;
continue;
} else {
return opening_address;
}
}
idx += 1;
}
return opening_address;
}

C, help continue..? in while loop - polynomial ADT

When the coef is 0, I used continue to not print, but only printTerm(a) comes out and the printTerm(b) part does not come out.
When I delete the (if & continue) statement, both printTerm(a) and printTerm(b) appear, so it seems that there is a problem here (if & continue) statement.
How can I solve this?
int main() {
a[0].coef = 2;
a[0].expon = 1000; // 2x^1000
a[1].coef = 1;
a[1].expon = 2; // x^2
a[2].coef = 1;
a[2].expon = 0; // 1
b[0].coef = 1;
b[0].expon = 4; // x^4
b[1].coef = 10;
b[1].expon = 3; // 10x^3
b[2].coef = 3;
b[2].expon = 2; // 3x^2
b[2].coef = 1;
b[2].expon = 0; // 1
printTerm(a);
printTerm(b);
return 0;
}
void printTerm(polynomial *p) {
int i=0;
printf("polynomial : ");
while(p[i].expon != -1) {
if(p[i].coef == 0) continue;
printf("%dx^%d", p[i].coef, p[i].expon);
i++;
if(p[i].expon != -1 && p[i].coef > 0) printf(" + ");
}
printf("\n");
}
Because you only increment i if p[i].coef is not equal to 0.
If p[i].coef == 0 it skips the increment part and function is stuck in infinite loop, always checking the same array item.
EDIT:
Way to fix this:
Instead of if(p[i].coef == 0) continue; use:
if (p[i].coef == 0)
{
i++;
continue;
}
This way while loop evaluetes next array item instead of being stuck on the same.

Troubles with battleship game in C

So i've been trying to write a sink the battleship game in C. I already wrote a simple version with randomly generated booleans however i was not happy with ships being only one block in size and there were too many of them, but i digress.
Here i've wrote what i believe is a messy piece of code, and it works, sometimes...
Here it is:
void generate_field(int *i, int *j, int n)
{
*i=rand()%n;
*j=rand()%n;
}
void map_gen(struct game *data,int n)
{
int i,j,k,l;
int return_value=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
data->tiles[i][j].ship=0;
data->tiles[i][j].uncovered=0;
}
}
// **4**
generate_field(&k,&l,n);
if(k==0 || k==1)
{
data->tiles[k][l].ship=4;
data->tiles[k+1][l].ship=4;
data->tiles[k+2][l].ship=4;
data->tiles[k+3][l].ship=4;
data->shipcount++;
}
else if(k==(n-1) || k==(n-2))
{
data->tiles[k][l].ship=4;
data->tiles[k-1][l].ship=4;
data->tiles[k-2][l].ship=4;
data->tiles[k-3][l].ship=4;
data->shipcount++;
}
else if(l==0 || l==1)
{
data->tiles[k][l].ship=4;
data->tiles[k][l+1].ship=4;
data->tiles[k][l+2].ship=4;
data->tiles[k][l+3].ship=4;
data->shipcount++;
}
else if(l==(n-1) || l==(n-2))
{
data->tiles[k][l].ship=4;
data->tiles[k][l-1].ship=4;
data->tiles[k][l-2].ship=4;
data->tiles[k][l-3].ship=4;
data->shipcount++;
}
// **3**
do{
generate_field(&k,&l,n);
}while(data->tiles[k][l].ship!=0 && (data->tiles[k+1][l].ship!=0 || data->tiles[k-1][l].ship!=0 || data->tiles[k][l+1].ship!=0 || data->tiles[k][l-1].ship!=0) && (data->tiles[k+2][l].ship!=0 || data->tiles[k-2][l].ship!=0 || data->tiles[k][l+2].ship!=0 || data->tiles[k][l-2].ship!=0));
if((k==0 || k==1) && (data->tiles[k+1][l].ship==0 && data->tiles[k+2][l].ship==0))
{
data->tiles[k][l].ship=3;
data->tiles[k+1][l].ship=3;
data->tiles[k+2][l].ship=3;
data->shipcount++;
}
else if((k==(n-1) || k==(n-2)) && (data->tiles[k-1][l].ship==0 && data->tiles[k-2][l].ship==0))
{
data->tiles[k][l].ship=3;
data->tiles[k-1][l].ship=3;
data->tiles[k-2][l].ship=3;
data->shipcount++;
}
else if((l==0 || l==1) && (data->tiles[k][l+1].ship==0 && data->tiles[k][l+2].ship==0))
{
data->tiles[k][l].ship=3;
data->tiles[k][l+1].ship=3;
data->tiles[k][l+2].ship=3;
data->shipcount++;
}
else if((l==(n-1) || l==(n-2)) && (data->tiles[k][l-1].ship==0 && data->tiles[k][l-2].ship==0))
{
data->tiles[k][l].ship=3;
data->tiles[k][l-1].ship=3;
data->tiles[k][l-2].ship=3;
data->shipcount++;
}
// **2**
do{
generate_field(&k,&l,n);
}while(data->tiles[k][l].ship!=0 && (data->tiles[k+1][l].ship!=0 || data->tiles[k-1][l].ship!=0 || data->tiles[k][l+1].ship!=0 || data->tiles[k][l-1].ship!=0));
if((k==0 || k==1) && (data->tiles[k+1][l].ship==0))
{
data->tiles[k][l].ship=2;
data->tiles[k+1][l].ship=2;
data->shipcount++;
}
else if((k==(n-1) || k==(n-2)) && (data->tiles[k-1][l].ship==0))
{
data->tiles[k][l].ship=2;
data->tiles[k-1][l].ship=2;
data->shipcount++;
}
else if((l==0 || l==1) && (data->tiles[k][l+1].ship==0))
{
data->tiles[k][l].ship=2;
data->tiles[k][l+1].ship=2;
data->shipcount++;
}
else if((l==(n-1) || l==(n-2)) && (data->tiles[k][l-1].ship==0))
{
data->tiles[k][l].ship=2;
data->tiles[k][l-1].ship=2;
data->shipcount++;
}
// **1**
do{
generate_field(&k,&l,n);
}while(data->tiles[k][l].ship!=0);
data->tiles[k][l].ship=1;
data->shipcount++;
}
the **#** are ship sizes.
the int n is the size of a dimension of the matrix array(i have two sizes:Normal which is 5x5 and large which is 8x8)
Anyway i know this could be written in a way simpler way and that it could actually work. The do-while loops are way too long and a lot of the times one or two my ships don't generate. I think it's because i somewhat limited their spawn by using(k==0 or k==n-1) stuff, however i have no idea what to do. Can anyone here give me some hints of how could have i written this differently and more compact and in a way in which it actually works right?
The problem is with how you determine location and direction for the ship.
I would do like this:
void place_ship(struct game* data, int n, int shipsize)
{
int x = 0, y = 0; // Uesd for ship direction
// Generate a direction
if (rand()%2) {
i=rand()%(n - shipsize + 1);
j=rand()%n;
x = 1;
y = 0;
} else {
i=rand()%n;
j=rand()%(n - shipsize + 1);
x = 0;
y = 1;
}
for (k = 0; k < shipsize; k++) {
if (data->tiles[i + x * k][j + y * k].ship != 0) {
// Space already occupied - retry!
return place_ship(data, n, shipsize);
}
}
for (k = 0; k < shipsize; k++) {
data->tiles[i + x * k][j + y * k].ship = shipsize;
}
}

Identify the index corresponding to the smallest data in a set of arrays

This is a trivial algorithmic question, I believe, but I don't seem to be able to find an efficient and elegant solution.
We have 3 arrays of int (Aa, Ab, Ac) and 3 cursors (Ca, Cb, Cc) that indicate an index in the corresponding array. I want to identify and increment the cursor pointing to the smallest value. If this cursor is already at the end of the array, I will exclude it and increment the cursor pointing to the second smallest value. If there is only 1 cursor that is not at the end of the array, we increment this one.
The only solutions I can come up are complicated and/or not optimal. For example, I always end up with a huge if...else...
Does anyone see a neat solution to this problem ?
I am programming in C++ but feel free to discuss it in pseudo-code or any language you like.
Thank you
Pseudo-java code:
int[] values = new int[3];
values[0] = aa[ca];
values[1] = ab[cb];
values[2] = ac[cc];
Arrays.sort(values);
boolean done = false;
for (int i = 0; i < 3 && !done; i++) {
if (values[i] == aa[ca] && ca + 1 < aa.length) {
ca++;
done = true;
}
else if (values[i] == ab[cb] && cb + 1 < ab.length) {
cb++;
done = true;
}
else if (cc + 1 < ac.length) {
cc++;
done = true;
}
}
if (!done) {
System.out.println("cannot increment any index");
stop = true;
}
Essentially, it does the following:
initialize an array values with aa[ca], ab[cb] and ac[cc]
sort values
scan values and increment if possible (i.e. not already at the end of the array) the index of the corresponding value
I know, sorting is at best O(n lg n), but I'm only sorting an array of 3 elements.
what about this solution:
if (Ca != arraySize - 1) AND
((Aa[Ca] == min(Aa[Ca], Ab[Cb], Ac[Cc]) OR
(Aa[Ca] == min(Aa[Ca], Ab[Cb]) And Cc == arraySize - 1) OR
(Aa[Ca] == min(Aa[Ca], Ac[Cc]) And Cb == arraySize - 1) OR
(Cc == arraySize - 1 And Cb == arraySize - 1))
{
Ca++;
}
else if (Cb != arraySize - 1) AND
((Ab[Cb] == min(Ab[Cb], Ac[Cc]) OR (Cc == arraySize - 1))
{
Cb++;
}
else if (Cc != arraySize - 1)
{
Cc++;
}
Pseudo code: EDIT : tidied it up a bit
class CursoredArray
{
int index;
std::vector<int> array;
int val()
{
return array[index];
}
bool moveNext()
{
bool ret = true;
if( array.size() > index )
++index;
else
ret = false;
return ret;
}
}
std::vector<CursoredArray> arrays;
std::vector<int> order = { 0, 1, 2 };//have a default order to start with
if( arrays[0].val() > arrays[1].val() )
std::swap( order[0], order [1] );
if( arrays[2].val() < arrays[order[1]].val() )//if the third is less than the largest of the others
{
std::swap( order[1], order [2] );
if( arrays[2].val() < arrays[order[0]].val() )//if the third is less than the smallest of the others
std::swap( order[0], order [1] );
}
//else third pos of order is already correct
bool end = true;
for( i = 0; i < 3; ++i )
{
if( arrays[order[i]].MoveNext() )
{
end = false;
break;
}
}
if( end )//have gone through all the arrays

skyline algorithm

How do I find the vertices of the broken line that surrounds the silhouette in this image?
A possible input for the example above is:
WIDTH HEIGHT POSITION
3 9 17
5 9 9
12 4 8
3 11 3
10 7 1
2 3 19
So for this example the solution would be
[(1, 0), (1, 7), (3, 7), (3, 11), (6, 11), (6, 7),
(9, 7), (9, 9), (14, 9), (14, 4), (17, 4), (17, 9),
(20, 9), (20, 3), (21, 3), (21, 0)]
This is pretty simple. Make an array that is the length of the X axis, initialize to 0. As you read in the inputs, write the heights into this array if the height is >= the current value at that location in the array.
Then just loop over the array, and every time the value changes it is a vertex.
Basically:
int heights[SIZE] = {0};
int i, width, pos, height, prev = -1;
while (scanf("%d %d %d", &width, &height, &pos) == 3) {
for (i = 0; i < width; ++i) {
if (heights[pos+i] < height)
heights[pos+i] = height;
}
}
for (i = 0; i < SIZE; ++i) {
if (heights[i] != prev) {
printf("(%d,%d) ", i+1, heights[i]);
prev = heights[i];
}
}
printf("\n");
In the naive case, this doesn't seem like a very difficult algorithm. Do you know if the input size will get large/how large?
My initial attempt: Try to move from left to right. First pick the block with the leftmost edge that exists on the origin line. Climb to its top. Find all blocks with a left edge between the current point and the upper right point of the current block. Of that set, pick the closest (but check for edge cases, pun not intended). If the set is empty, start working your way down the right side of the block, looking for other blocks you may intercept.
Basically this is just how you'd trace it with your eye.
You can do some simple optimization by keeping sorted lists and then searching the lists rather than finding sets and digging around. For example, you might keep 4 sorted lists of the blocks, each sorted by the x or y coordinate of one of the sides.
If you have many, many blocks, you could consider using a multi-dimensional data structure to further organize the information.
I solved this problem using the sweep-line algorithm. This is a python class solution.
there two keys:
1) using the variable "points" to save all the left and right points and their heights and the sign of the height to indicate whether the points are left or right.
2) the variable "active" is used to save all the active lines that has been scanned.
class Solution:
# #param {integer[][]} buildings
# #return {integer[][]}
def getSkyline(self, buildings):
if len(buildings)==0: return []
if len(buildings)==1: return [[buildings[0][0], buildings[0][2]], [buildings[0][1], 0]]
points=[]
for building in buildings:
points+=[[building[0],building[2]]]
points+=[[building[1],-building[2]]] # the negative sign means this point is a right point
points=sorted(points, key=lambda x: x[0])
moving, active, res, current=0, [0], [],-1
while moving<len(points):
i=moving
while i<=len(points):
if i<len(points) and points[i][0]==points[moving][0]:
if points[i][1]>0:
active+=[points[i][1]]
if points[i][1]>current:
current=points[i][1]
if len(res)>0 and res[-1][0]==points[i][0]:
res[-1][1]=current
else:
res+=[[points[moving][0], current]]
else:
active.remove(-points[i][1]) #remove height of the lines than have been finished with scanning
i+=1
else:
break
if max(active)<current:
current=max(active)
res+=[[points[moving][0], current]]
moving=i
return res
I made a Java class to try and solve this. The class includes methods for generating, solving and printing data-sets. I haven't tested extensively, there may be a few bugs remaining. Also, my solution may be needlessly complicated, but it's designed to work (in theory) for non-discrete height and coordinate values.
import java.util.Random;
public class Skyline {
private int[][] buildings;
private int[][] skyline;
private int maxLength;
private int maxHeight;
public Skyline(int buildings, int maxLength, int maxHeight) {
this.maxLength = maxLength;
this.maxHeight = maxHeight;
makeRandom(buildings);
}
public Skyline(int[][] buildings, int dimensions) {
this.maxLength = maxLength;
this.maxHeight = maxHeight;
this.buildings = buildings;
}
public void makeRandom(int buildings) {
this.buildings = new int[buildings][3];
Random rand = new Random();
for(int i = 0; i < buildings; i++) {
int start = rand.nextInt(maxLength-3);
int end = rand.nextInt(maxLength - start - 1) + start + 1;
int height = rand.nextInt(maxHeight-1) + 1;
this.buildings[i][0] = start;
this.buildings[i][1] = height;
this.buildings[i][2] = end;
}
boolean swapped = true;
while(swapped) {
swapped = false;
for(int i = 0; i < this.buildings.length-1; i++) {
if(this.buildings[i][0] > this.buildings[i+1][0]) {
swapped = true;
int[] temp = this.buildings[i];
this.buildings[i] = this.buildings[i+1];
this.buildings[i+1] = temp;
}
}
}
// this.buildings[0][0] = 2;
// this.buildings[0][1] = 3;
// this.buildings[0][2] = 8;
}
public void printBuildings() {
print(this.buildings, false);
}
public void printSkyline() {
print(this.buildings, true);
}
public void print(int[][] buildings, boolean outline) {
char[][] str = new char[this.maxLength][this.maxHeight];
for(int i = 0; i < this.maxLength; i++) {
for(int j = 0; j < this.maxHeight; j++) {
str[i][j] = '.';
}
}
for(int i = 0; i < buildings.length; i++) {
int start = buildings[i][0];
int height = buildings[i][1];
int end = buildings[i][2];
//print the starting vertical
for(int j = 0; j < height; j++) {
if(outline) str[start][j] = str[start][j] == '|' ? '.' : '|';
else str[start][j] = '|';
}
//print the ending vertical
for(int j = 0; j < height; j++) {
if(outline) str[end][j] = str[end][j] == '|' ? '.' : '|';
else str[end][j] = '|';
}
//print the horizontal
if(height > 0) {
for(int j = start; j <= end; j++) {
str[j][height] = str[j][height] == '|' ? '|' : '-';
}
}
}
for(int i = maxHeight-1; i >= 0; i--) {
for(int j = 0; j < maxLength; j++) {
System.out.print(str[j][i]);
}
System.out.println();
}
System.out.println();
}
public void solveSkyline() {
for(int i = 0; i < buildings.length; i++) {
boolean reduced = true;
while(reduced) {
reduced = false;
for(int j = i+1; j < buildings.length; j++) {
if(buildings[j][0] < buildings[i][2] && buildings[j][1] > buildings[i][1] && buildings[j][2] >= buildings[i][2]) { //if intersecting building is taller, and longer
buildings[i][2] = buildings[j][0];
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][1] <= buildings[i][1] && buildings[j][2] >= buildings[i][2]) { //intersecting building is shorter, but longer
buildings[j][0] = buildings[i][2];
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][1] > 0 && buildings[j][1] < buildings[i][1] && buildings[j][2] <= buildings[i][2]) { //building is invisible, so ignore it
buildings[j][1] = 0;
reduced = true;
break;
} else if(buildings[j][0] < buildings[i][2] && buildings[j][2] <= buildings[i][2] && buildings[j][1] > buildings[i][1]) {
int[] newBuilding = new int[]{buildings[j][2], buildings[i][1], buildings[i][2]};
int[][] newBuildings = new int[buildings.length+1][3];
boolean inserted = false;
buildings[i][2] = buildings[j][0];
for(int k = 0; k < buildings.length; k++) {
if(inserted == false) {
if(newBuilding[0] < buildings[k][0]) {
newBuildings[k] = newBuilding;
newBuildings[k+1] = buildings[k];
inserted = true;
} else {
newBuildings[k] = buildings[k];
}
}
if(inserted == false && k == buildings.length - 1) {
newBuildings[k+1] = newBuilding;
} else {
newBuildings[k+1] = buildings[k];
}
}
buildings = newBuildings;
reduced = true;
break;
}
}
}
}
}
public static void main(String args[]) {
Skyline s = new Skyline(5, 100, 10);
s.printBuildings();
s.solveSkyline();
s.printBuildings();
s.printSkyline();
}
}
My solution to the problem as described here https://leetcode.com/problems/the-skyline-problem/ it iterates the list of buildings twice, however this could be combined into a single iteration. However, there are more optimal approaches if you consider the pure algorithm solution explained here http://www.algorithmist.com/index.php/UVa_105
class Solution {
public:
vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
// The final result.
vector<pair<int, int>> result;
// To hold information about the buildings
std::set<BuildingInformation> buildingInformation;
// Go through each building, and store information about the start and end heights.
for ( vector<vector<int>>::iterator buildingIt = buildings.begin( ); buildingIt != buildings.end( ); ++buildingIt ) {
BuildingInformation buildingStart;
buildingStart.x = (*buildingIt)[0];
buildingStart.h = (*buildingIt)[2];
buildingStart.StartOrEnd = Start;
buildingInformation.insert(buildingStart);
buildingStart.x = (*buildingIt)[1];
buildingStart.StartOrEnd = End;
buildingInformation.insert(buildingStart);
}
// Keep track of the current height.
int currentHeight = 0;
// A map of active building heights against number of buildings (to handle multiple buildings overlapping with same height).
// As it is a map, it'll be sorted by key, which is the height.
std::map<int, int> heights;
// Go through each building information that we generated earlier.
for ( std::set<BuildingInformation>::iterator it = buildingInformation.begin( ); it != buildingInformation.end( ); ++it ) {
if ( it->StartOrEnd == Start ) {
// This is a start point, do we have this height already in our map?
if ( heights.find( it->h ) != heights.end( ) ) {
// Yes, increment count of active buildings with this height/
heights[ it->h ] += 1;
} else {
// Nope, add this building to our map.
heights[ it->h ] = 1;
}
// Check if building height is taller than current height.
if ( it->h > currentHeight ) {
// Update current height and add marker to results.
currentHeight = it->h;
result.push_back( pair<int, int>( it->x, currentHeight ) );
}
} else {
// This is an end point, get iterator into our heights map.
std::map<int, int>::iterator heightIt = heights.find( it->h );
// Reduce by one.
heightIt->second -= 1;
// If this was the last building of the current height in the map...
if ( heightIt->second == 0 ) {
// Remove from heights map.
heights.erase( heightIt );
// If our height was the current height...
if ( it->h == currentHeight ) {
// If we have no more active buildings...
if ( heights.size( ) == 0 ) {
// Current height is zero.
currentHeight = 0;
} else {
// Otherwise, get iterator to one past last.
heightIt = heights.end( );
// Go back to get last valid iterator.
--heightIt;
// Store current height.
currentHeight = heightIt->first;
}
// Add marker to results.
result.push_back( pair<int, int>( it->x, currentHeight ) );
}
}
}
}
return result;
}
private:
// Is this a building start or end?
enum BuildingStartOrEnd
{
Start = 0,
End
};
// Information about building, there are two of these for each building, one for start, one for end.
struct BuildingInformation
{
int x;
int h;
BuildingStartOrEnd StartOrEnd;
// The ordering algorithm for the key, the rules we want to implement is keys are put in X order, and
// in the case of a tie (x values the same), we want Start pieces to come before End pieces (this is
// to handle cases where an old building ends and a new building begins on same X index, in which case
// we want to process the new start before processing the old end), however if we have two Start pieces
// at the same index, we wish to favour taller pieces (in this scenario we want to add a marker for the
// tallest building), finally if we have two End pieces at the same index, we wish to prefer lower
// pieces, as when multiple buildings end, we only want to add one result for the ultimate lowest point.
bool operator < ( const BuildingInformation & rhs ) const
{
if ( x == rhs.x )
{
if ( StartOrEnd == rhs.StartOrEnd ) {
if ( StartOrEnd == Start )
return h > rhs.h;
else
return h < rhs.h;
} else {
return StartOrEnd < rhs.StartOrEnd;
}
}
return x < rhs.x;
}
};
};

Resources