C++

All posts tagged C++

Second example problem:

Given an m * n field of trees and open spaces, find out the biggest square house that can be built with no intersection with trees.

For a suboptimal solution, simple solution starts with scanning every space to see if it is open or not (starting in the upper-left). Find the largest possible square starting at the given space, then find the maximum size square possible in the entire area.

Note that each loop has two conditions, the total width/height of the area AND the max value.  This max-value check keeps the loops from searching for open squares that could not possibly be larger than the current largest square (e.g. too close to one edge of the area).

Now, the function itself, starting at the specified location, searches diagonally for trees, stopping at the first and/or nearest tree it encounters.  It does this by first checking the current square for a tree.  If there is no tree it scans downward until it a) finds a tree or b) reaches the edge of the map.  It repeats the process to the right.  It then increments the “top-left” square inward and repeats the process.

The code above has one special optimization.  We first declare a global variable  std::unordered_map<int,int> FoundMax; This unordered (hash) map is keyed on the x,y coordinates of a square, and stores the maximum size of a square found starting at those coordinates.  This way, it we happen to be searching a diagonal sub-set of a previously searched larger square, we will not have to loop further to find the area of that square.  Note that because this searching works diagonally, we could actually use membership in the FoundMax map as an exit condition (or perhaps, in the outer main loop to prevent calling Find2 in the first place).

The complexity of this algorithm is N for the outer-most loop (once for each square).  From each square, we search a maximum of M additional squares (where M < N), making for a worst-case complexity of O(n*m).  This isn’t a valid expression, true, and by investigation we can see that m decreases logarithmically with respect to n, making a true complexity of O(n log(n)).

Ideas for further optimization: For all upper-left squares with the same X value, the maximum distance down is less than the maximum distance of the previous Y value down. We could therefore skip searching for the next downward tree with a lookup of the nearest downward tree from Y-1 (if we were storing that value). The same goes for the nearest tree to the right from the current X for squares starting on the same Y.

Ok,

So I was recently presented with an example coding exercise as stated below:

Every athlete is characterized by his mass ‘m’ (in kg) and strength ‘s’ (in kg).
You are to find the maximum number of athletes that can form a tower standing one upon another.
An athlete can hold a tower of athletes with total mass equal to his strength or less than his strength.
Input contains the number of athletes n and their parameters.
For example:

n
m1 s1
m2 s2

mn sn

If mi > mj then si > sj, but athletes with equal masses can be of different strength.
Number of athletes n < 100000. Masses and strengths are positive integers less than 2000000.
For example:
Input #1

4
3 4
2 2
7 6
4 5

Would yield
Output #1

3

Working through the Solution

Phase one, figure out how to store the data.  Easy, store it in a linked list, could be a list of tuples/pairs, but I actually created a class to store the weight/strength, because I want to be able to do a complex sort on the data (see below).

Now, the problem description states that if one athlete weights more than another, it will have greater strength as well.  This provides us with one crucial optimization, we know that the strongest athlete will also be the heaviest.  This athlete, therefore, should go on the bottom of the tower.  We could do a linear search for the strongest, but we can also find the strongest after sorting the list, and we’ll want a sorted list for later.  Therefore, using the comparison operators we described above, we can sort the list of athletes, and begin processing as so:

In the above code, we grab the first entry after sorting, which is (by definition) the strongest. Starting with that athlete’s strength as the maximum weight for any tower to be formed. We then pass the array of athletes, the starting point and weight left to our recursive function. The “tot” variable is there for analysis purposes. The function is defined as below.

The analysis of the algorithm is actually contained in the comments above, but I’ll point out some key points here:

  1. The maximum size of the tower (within the current iteration) is limited to the number of athletes left in the list.  If we find a tower equal to the size of the list, we are done.
  2. If the current athlete weighs more than the remaining weight limit, they (and any other athletes of the same mass) cannot fit on the tower.
  3. The first athlete of any weight is also the strongest (thanks to the sorted list).  Therefore, we only need to consider ONE of any athlete with a given weight (e.g. ALL athletes of weight 4 will be able to support a tower of a most the size of the strength of the strongest athlete).

The loop in the above function scans the lists of athletes, to determine the maximum size of a tower each athlete could support, standing on top of the tower as it stands before the function is called.  Therefore, the first time the function is called, it stands each athlete, in sequence, on top of the shoulders of the strongest athlete, and sees how tall the tower can be built.

If the current athlete can fit on the tower at all (based on remaining weight limit), the recursive call then determines the size of the tower that could then stand on the shoulders of the current athlete. Thanks to item 3 above, we must only perform the recursive call once per athlete weight.  This greatly reduces the number of recursive calls.  The return value of the recursive call is compared to the current maximum tower height found previously (and stored if greater than).  The loops then checks that the maximum tower height does not equal the remaining number of athletes.  If it does, we have found the greatest tower height and can return.

The function returns the tallest tower it found that could stand on the shoulders of the previous athlete.  When the recursion returns completely, we have solved the problem. Worse case scenario of this algorithm is actual 2^n, which is terrible.  But this is because every possible combination of towers must be considered.  However, thanks to our end-conditions (the 3 steps above), we can actually reduce actual complexity to a linear (O(n)) complexity.  This is because we really only have to search the list once, excluding “duplicate” athletes (athletes that could not have supported a stronger tower are discounted thanks to step 3).  With step 1 above, we do not need to continue looping once we have found a maximum tower, and can exit.

Anyway, the full source is in my (poorly misspelled) repository here: http://svn.hellwig.us/repo/VC11/ExcersizeTest.

Ok,

So getting back into C++ programming, I’ve been allocating plenty of dynamic memory (using new  and new[] ) .  However, I’ve only been using delete , never delete[] .  If fact, I’ll be honest, I forgot about delete[] , but that’s OK, I didn’t need the [] form anyway.  Why you ask?

Take this example:

Now, almost every example you see online will actually have delete[] buf; , this is correct, but unnecessary.  Why?  The only difference between delete and delete[] is item deconstruction.

When you call delete, all the memory you allocated with new[] is still erased. The problem is, only the first element (the one being directly pointed to) is deconstructed. None of the other members of your array are deconstructed. In my example this is OK, because the array was an array of “char”s, you can’t deconstruct a char in C++, it’s not an object.

 

When is delete[] useful?

When you allocate an array of objects that themselves allocate more memory. delete[]  makes sure that each entry in the allocated array is properly deconstructed. Example:

 

Can I just call delete[] all the time?

Sure, well, almost.   delete[]  works on a specific type of pointer.  When you call myclass * myptr = new myclass[5] , you are telling the system to reserve you sizeof(myclass)*5  bytes of memory.  This size is all that is stored in the memory allocator.  When you call delete[] myptr; , the memory allocator goes through the following process:

  1. How much memory was reserved starting at the address stored in myptr (answer: sizeof(myclass) * 5);
  2. Start at offset = 0.
  3. Call the myclass.deconstructor at the address myptr + offset.
  4. Increase offset by sizeof(myclass)
  5. If offset < total allocated memory, goto 3.  Else, continue;
  6. Delete/Free all memory reserved (sizeof(myclasS) * 5 bytes) starting at address storef in myptr;.

However, if you tried to call delete[] (void *) myptr;  all calls to sizeof(myclass) above will be replaced with sizeof(void), which returns no size (no object can be of type void). Therefore, none of the objects in the array will be deconstructed.  Calling delete[] (void *)ptr;  is the same as calling delete (void *)ptr; .

Similarly, if you recast the pointer to a different type, delete[] will not know the proper size of each object, and any attempts to deconstruct those “objects” will most likely result in errors/exceptions.  Example:

Of course, casting pointers in C++ is always dangerous.  The compiler and system do not keep track of allocated memory by type, only size.  Therefore, you should always be careful when having to cast a pointer.

Note: There are acceptable times to cast a pointer (when reading in bytes that are actually multi-byte values, say casting an int* as a char*), but often times, this can also be handled with Unions.

Anyway, that’s my “quick” overview of the delete and delete[] operations in C++.

Ok, so many of the jobs I am applying for now want C++ experience.  Problem is, none of the companies I have worked for in the past 8 years wanted me to write in C++.  The industry used to use Ada, and many legacy programs still have all their code in Ada.  Not only that, but the companies that use C++ often use model-based development suites, meaning they don’t write any actual code, the compiler does it all for them.

Anyway, I am quite familiar with C++.  It was the first real language I ever programmed in (not counting Quick Basic).  I took 3 years of C++ in high school.  I did all sorts of things in the days before Java, Python, Perl, .NET, etc…  Now days, I’m not even sure people know what C++ means.  They probably use so many libraries, they really only use C++ for the Syntax and wide array and industry tested (and free) compilers.

Long story a little bit shorter, I have started to upload some of my old C++ code to my SVN server.  The page describing it all is on my website here: C++ Code.

That is all.

So I figured I’d start playing around with micro-controllers again (ok, never really played around so much as took classes in college).  Anyway, my old HC12 micro-controller is stuck in storage, and it’s not supported anymore (it was old before I graduated college).  I decided that I would try-out the new Raspberry Pi since I found it in stock a couple months ago.  It’s a nifty little computer, but not really a micro-controller.  It lacks real-time support (from the “default” Linux-based OS) and even sub-millisecond control (which sucks for sensors and whatnot).  I then decided I should pair the Pi with an Arduino, a true real-time micro-controller.  Anyway, I plan to hook up some stuff around my house to the Arduino, and then control the Arduino over the internet via the Pi.  The only real reason for the Pi in this scenario is to avoid the high power-consumption of a regular PC.

Soo… I’ve been playing around with both devices and the various ICs and electrical components I have left over from college.  Bought myself some relays, etc.. so I can control things like lamps.  Uploaded my code to my SVN server for two reasons, backup, and the ability to move it easily between my PC and the Pi (since I can program the Arduino directly from the Pi, I can avoid my computer when desirable). Nothing exciting yet, I wired up a couple 7-segment displays to an I2C 16-port expander, got a Ping))) sensor measuring distance, and wired up a 4-button debounced switch panel, so now I just got to think of something to do with all this stuff.

I just created an SVN repository to host my various projects.  Right now it only has the source for my lone android application, a tip calculator (unique, I know).  There are 1800+ results for Tip Calculator apps in the Google play store, so I doubt I’ll be adding mine to the fray, but the wife can use it and it was a good intro to Java and Android programming.

The SVN repo is here:  http://svn.hellwig.us/repo.  It’s open for browsing, but I don’t really need any community contributions right now.  I’m using eclipse, so the apps are setup as eclipse projects.   No apks just yet, working on fixing the last few bugs.  I’ll probably create an FTP account to host the actual releases.

Anywho, that’s that.