mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

After you set filters with glTexParameteri for the binded texture object, then that texture object will always be rendered with that filter until you set the filters again to some other value. So, if you want to test the different filters just to see how they do, then you could do:

glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glBegin(GL_QUADS);
  // .. render something..
glEnd();

// ..

glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glBegin(GL_QUADS);
  // .. render something ..
glEnd();

It is just a matter of binding the texture, and applying a different set of filters for the different objects you render. You might not see this kind of code very often because people tend to apply just one type of filter to one texture, but it is possible to alternate the filtering like in the above.

and then do texture[1] = texture[0], does what i did before go into texture[1] aswell?

Yes. The texture ID is nothing more than an address or pointer to the texture object, so, doing texture[1] = texture[0] doesn't create a new object just like copying a pointer doesn't copy the object that they point to, it just makes them both point to the same object. So, texture[1] and texture[0] will simply represent the exact same texture all the time, whatever you do to one, you do to the other.

You have to understand that the whole point of all this is that the texture itself (the image) is transferred …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Brave -> heart

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You don't need to load a new texture, nor do you need to generate new texture objects (the glGenTextures call). When SOIL loads the image and puts it into an OpenGL texture object texture[0], you then bind it and use it when rendering vertices. If you want to reuse it for other things that you render, simply bind it with those objects too. In other words, you have this type of code:

texture[0] = SOIL_load_OGL_texture( /* .. */ );

// .. other stuff..

glBindTexture(GL_TEXTURE_2D, texture[0]);
// render some stuff ...

// .. some more stuff ..

glBindTexture(GL_TEXTURE_2D, texture[0]); // re-bind the texture again.
// render something else ..

// etc...

So, you should never need to have multiple texture objects that point to the same texture, just re-use the texture ID for other objects if you need to use the same texture for multiple entities that you render.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

After several years of efforts, he trained Rantanplan to do it.

Step 1: Collect underwear.
Step 2: ???????
Step 3: Profit!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I first use a shader to create a texture, correct?

No. Shaders are used to transform texture(s), at least, fragment shaders do that. Shaders are basically small programs that run on the GPU. A vertex shader is a small program that runs for each vertex (point in a 3D mesh) that you render, and its job is to apply whatever transformations are necessary to prepare it to be rendered on the screen (these transformations include projecting it into a point on the screen, and other things like computing its texture coordinates, applying a bump-map to it, or even animating the vertex). After vertices are projected to a place on the screen, the OpenGL pipeline generates a number of pixels on those surfaces that should appear on the screen. The fragment shader is a small program that takes each pixel (or fragment) and performs a final transformation of the values associated to the pixel, that can include applying lighting, blending the pixel color coming from different textures, and possibly generating colors too, even animating them, and I think that's what you are asked to do.

And then I have it change colors based on a certain time?

Yes, shaders have a number of inputs, some that are fixed by OpenGL, and some that you can customize. You can use Uniforms (see glUniform) which are like constant parameters, and Attibutes (see glVertexAttrib) which are per-vertex values. The inputs that are fixed by OpenGL include …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If I may suggest an improvement, notice that you don't really need to count the number of nodes in your list before you do the sorting. The bubble sort algorithm has the effect of pushing that maximum value at the end of the list. So, at every outer-loop iteration, you increase by one the number of sorted nodes at the end of the list. If you keep track of the last sorted element from after terminating the inner-loop, you have the node at which you should stop the next inner-loop. As for stopping the outer-loop, you just need to stop when the last sorted element is equal to HEAD.

void Sort()
{
    node * list_end = NULL;
    while(list_end != HEAD)  // this also takes care of the HEAD == NULL case, which you forgot!
    {
        node *temp, *swap1;
        swap1 = HEAD;
        while( swap1->NEXT != list_end )
        {
            if(swap1->DATA > swap1->NEXT->DATA)
            {
                node *swap2 = swap1->NEXT;
                swap1->NEXT = swap2->NEXT;
                swap2->NEXT = swap1;
                if(swap1 == HEAD)
                {
                    HEAD = swap2;
                    swap1 = swap2;
                }
                else
                {
                    swap1 = swap2;
                    temp->NEXT = swap2;
                }
            }
            temp = swap1;
            swap1 = swap1->NEXT;
        }
        // update the list_end to the last sorted element:
        list_end = swap1;
    }
}

Another important optimization that you missed is to check for no-swaps in the inner-loop. During your inner-loop, you should keep a bool value to tell whether a swapped has occurred or not through the inner-loop. The reason for this is that if there were no swaps …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

First, you need to know that you are allowed to swap the values of variables. In other words, the variable a,b,c,d don't have to have the same value all throughout your program. So, the idea is not to print out the four variables in order, but to rearrange the values such that a < b < c < d at the end.

As an example, here is a start, the first if statement should be:

if( b < a ) {
  int tmp = a;
  a = b;
  b = tmp;     // at this point a stores the original value of b, and vice versa, the values are swapped.
};

After that if-statement, the first two values will be in order.

Then, you need an if-else statement to find out where c should go. If c should go at the start, then you need to "rotate" the values (a kind of double swap). If c should go between a and b, then you need to swap b and c. And if c should go after both a and b, then you don't need to do anything. This amounts to one if and one else-if statement.

Finally, you do the same for d. This time you'll one if and two else-if statements, which makes a total of 6 if-statements, as hinted to you.

It is also possible to proceed by putting c and d in correct order also (as with a and b), and then proceed to interleave the (a,b) …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Don't use recursion when you expect a linear recursion depth (or more). In your code, for an array of size N, your recursive function will eventually be called N times. When you use recursion, in the real world, you have to be vigilant about the depth of the recursion because too much depth will fill the stack very quickly and lead to stack-overflow errors. Normally, recursion is only used for log(N) calls, for example, you can implement a merge-sort with recursive calls because the depth is limited by O(log(N)). Similarly, people often implement quicksort algorithms with recursion, with best-case depth of log(N), but because the worst-case depth is linear, the basic quicksort algorithm is not used in practice, instead, people use introsort or similar variants that make sure to put a hard limit on the depth of recursion. Most algorithms that are more naturally expressed as recursions have log(N) depth, like "good" sorting algorithms, binary searches, etc.

All naive sorting algorithms, like bubble-sort, selection-sort, insertion-sort, etc., which are all O(N^2), will lead to a linear recursion depth, and they are usually just as easy to implement as a loop. For these two reasons, you will never see or hear about recursive implementations of these algorithms.

There are ways in which you can use recursion even with an expected linear depth. This involves what is called "tail recursions" which is a way to program the function such that the recursion will not lead to a filling of the stack. Basically, the …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

skenario I thought about was that we would have functions min and max returning pointers to smallest and biggest node. Then we would sort the linked list. If we swap nodes the min and max would stay valid, if we exchange values, we get suden change of these values (so in this case we must store values, not node pointers)

This is what interface specifications are for. If your sorting algorithm swaps values, then you should specify in the post-conditions of your sorting function that all iterators or node pointers previously obtained to elements of the list are invalidated. This all boils down to the interface specification. In the STL, the linked-list implementation std::list specifies that the sort function does not invalidate iterators to the nodes, implying that node positions are swapped, not their values. One could relax this specification by specifying a sort function that could invalidate iterators, which would allow for value swapping as an optimization for small data elements. However, that would be cumbersome for people using it as they would often expect iterators to remain valid through all mutations of the linked-list, and it would have very limited application since there is rarely much advantage to storing very small data elements in a linked-list structure because the performance problems associated to the lack of locality of references are often much worse than the overhead in copying data around when storing in a contiguous array (e.g. std::vector or std::deque). And if what you are looking …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You rearrange to math such that you don't get numbers that are too large (possibly overflowing) or too small (possibly underflowing), or such that you avoid many other pitfalls of numerical calculations, like subtracting two numbers that are almost the same value, adding a large number with a very small one (which is a big problem when taking averages or other statistics), and so on.

In this case, you can fix the theoretical calculation simply like this:

double factor = (N - 1) / double(N);
double avg = 1.0;
for(int i = 2; i <= N; ++i) {
  avg += factor;
  factor *= (double(N) - i) / double(N);
};
std::cout << "Theoretically, the average number of random songs played before a repeat event is " << avg << std::endl; 

The other way to fix such problems is to develop an alternative expression, often an approximate one, which produces less round-off errors. Like in the above case, the Approximate expression is just as good as the theoretical one, or even better because it gives you the result within acceptable precision in one simple math expression as opposed to a loop. The idea here is that if the exact expression might lead to a lot of round-off error, then it is acceptable to use an approximate solution with less round-off error problems. In other words, if the round-off error of the exact expression is larger than the combination of the approximation error and its round-off error, then you are better off …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here is a simple traversal algorithm that probably would make sense for one pass of the sorting:

node* previous = NULL;
node* candidate1 = HEAD;
node* candidate2 = candidate1->NEXT;
while( candidate2 != NULL ) {
  // do stuff.. (like swapping if necessary)

  previous = candidate1;
  candidate1 = candidate2;
  candidate2 = candidate2->NEXT;
};

This is how to handle the three pointers. So, again, previous always points to the node before the first candidate, or NULL if none exist (if the first candidate is HEAD). The above loop also has the feature that it will not execute if there is only one node, which makes sense since there is no need to sort anything if there is just one node.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I hope nobody asks you to sort 1000 values!

Ever heard of the concept of scalability?
Ever heard of arrays?
Ever heard of sorting algorithms?

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@AD
He specified:

I was told not to swap the data inside the nodes, but move the nodes themselves.

The idea of this exercise is to not swap the data. I agree that if the data is small, it is better to swap the data, if this was for a real problem, not an exercise.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You also should take a look at Shader Designer. This is an IDE for GLSL, I've used it in the past when I played around with shaders, it's pretty nice and easy. I think it also provides base codes to start from.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

To swap two nodes of a single linked-list you will have to keep track of three pointers, let's call them "previous", "candidate1" and "candidate2". These three should always appear in that order in the list, that is, "previous" is the node before the first candidate for swapping and "candidate1" and "candidate2" are the two nodes that need to be swapped. So, we have:

Before the swap:

  • previous->NEXT == candidate1
  • candidate1->NEXT == candidate2
  • candidate2->NEXT == next_candidate

Then, after the swap, you just need to have the following:

  • previous->NEXT == candidate2
  • candidate1->NEXT == next_candidate
  • candidate2->NEXT == candidate1

From the above, it's pretty clear that all you have to do to perform the swap is to do this:

previous->NEXT = candidate2;
candidate1->NEXT = candidate2->NEXT;
candidate2->NEXT = candidate1;

It's that simple, except that you also have to consider the case of previous == NULL which would occur if candidate1 == HEAD, if that's the case, then you simply skip the first step.

BTW, your sorting loop is not complete, you need a nested loop. Doing one pass will only result in the largest value appearing at the end of the list (that's the "bubble" in bubble-sort), you need to do multiple passes until all is sorted.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This is a huge topic and you will have to think it through much more than that to make it out alive (figuratively).

What you want is a game engine. Either make your own simple design or pick one off-the-shelf.

If you want suggestions for an off-the-shelf option, I would suggest Ogre3D (and its game logic extension NeoAxis).

Ogre3D also gives you a very typical example of how things are generally structured when making an essential part of a game engine, i.e., the renderer. You can see its core structure here.

Overall, a game engine has three main parts: renderer, physics engine, and game logic manager.

The renderer takes care of putting things on the screen. Typical features include rendering maps and objects, lighting, cameras, visual effects, particle systems, pixel shaders, shadows, etc.. This is the kind of tasks that Ogre3D does.

The physics engine takes care of all the physical interactions between objects, such as integrating motion, computing forces (often called "rag-doll" physics), kinematics (often called "skinning"), collision detection, etc... The Open Dynamics Engine (ODE) is a very basic example of such a physics engine.

The game logic manager takes care of all the "rules of the game". This might range from taking input from the user, to keeping the scores.

There are also other auxiliary parts to a game engine, like handling menus, network gaming, etc..

The reason why all these parts are generally separated is that they have very …

sergent commented: He is talking about a console game... not game engines. I don't think a person who knows OpenGL or DX would not know how to divide something into different files. +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

That syntax is the initialization list.

The initialization list is for all sub-objects (which includes both base-class instances and data members) of an object. It is simply a comma-separated list of constructor calls for each base-class instance and data member belonging to a class. In your specific example, value is a data member of the general class template A and it is constructed with value i.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Erasing elements while iterating through them is a problem because, with a container like std::vector, any operation that adds or erases elements in the vector will cause all iterators to be invalid. In other words, your iterator it that you use in your loop becomes invalid as soon as an element is erased (or added) from the vector. It needs to be reset. This is because erasing or adding an element to a vector might cause a reallocation of the memory, and since iterators for a vector is often just a pointer (or a thin-wrapper for a pointer), if the memory is reallocated elsewhere, that iterator no longer points to a valid element of the vector.

Not all STL containers are like that. There are different containers for different needs. Vectors are often not the best if you are going to do a lot of insertions / deletions in the middle of the sequence. The alternative, linked-lists which are more efficient at mid-sequence insertion / deletion, also have many drawbacks that are not negligible either (locality of references) and often out-weight its theoretical performance benefits.

Normally, the preferred strategy for removing elements of a vector is to simply not erase them just yet. Instead, you implicitely remove them from the vector by re-packing all the remaining elements, leaving a bunch of empty elements at the end of the vector, which you erase afterwards.

I think you can implement your algorithm simply by making clever use of std::remove (

TrustyTony commented: Thanks for your expert advice! Nice to see I was correct. +12
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

"If we gave this man an enema, we could bury him in a matchbox." - Christopher Hitchens (in layman terms: "this man is full of it")

On the geeky side:

"There are only 10 kinds of people in this world: those who know binary and those who don’t."

"Windows 95 is a 32 bit extension for a 16 bit patch to an 8 bit operating system originally coded for a 4 bit microprocessor by a 2 bit company that can't stand 1 bit of competition."

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

As I said earlier, the interesting part of this problem, from a perspective of learning computer programming, is to understand why that theoretical calculation doesn't work (outputs NaN).

The loop that computes the theoretical value will try to calculate both 1000^1000 and 1000!, which are both extremely large values can simply cannot be stored in a double-precision floating point number.

This is an important lesson to learn. Even a perfectly sound mathematical formula might not be any useful when trying to compute it on a computer because of the inherent limitations in representation and precision.

To some extent, the experimental calculation might also suffer the same fate because computing the average of a large sequence of numbers might also give a similar problem. Overall, we call this numerical stability.

Theory describes the expected whereas exprimentation describes reality.

Sure, but in computer science, both theoretical and experimental calculations are only approximated. The key is to understand how approximate they are, and how to mitigate these problems in order to get something useful. Blindly doing an experimental calculation is just as bad as blindly doing a theoretical calculation, neither results can be trusted if you don't consider the numerical approximations inherent to those calculations.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Since the overhaul, there are some nice feature of the old system that are missing in the thread titles. By thread titles, I mean as they show up in the forum listings (the icon (new, read, etc.), title, # of replies, time of last post, etc.). Some of the features of the old system that I have in mind are the following:

  • When hovering over the title, the first few lines of the question used to appear. Now, there's nothing.
  • The number of up-votes / down-votes associated to the OP used to appear on the right of the title. That seems to be gone.
  • What happened to the view-count on the thread?

I found that these features were pretty useful to determine if its worthwhile clicking and reading the thread. I miss them. Any plans for them to reappear?

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I generally like the new editor and the markdown. It's not only simpler but also more feature-rich (at least it seems at first glance), which is a nice combination. But I have a few beefs:

1.
The transition messed up some previous posts. For example, I wrote two tutorials on the C++ forum, making heavy use of the [ICODE] blocks [/ICODE]. All these inline code blocks were translated into single code-line blocks. I don't know if it's fixable, that would be nice.

2.
Is there a way to do (La)TeX blocks (inline or not)? Or some other similar markup for math equations in particular. It's not like I tend to need that so much, but once in a while it comes in handy.

3.
This may be specific to me. I use Linux with system-wide spell checker (Sonnet) (all I write, anywhere I write it, is checked for spelling and is easily corrected with a right-click). For some weird reason, this new editor is immune to that, it's the first such editor that I encounter in the few years I've been using this feature (the old editor didn't have that problem). I love this system-wide spell checker, any ideas why the new editor is such an exception to this, and what could possibly solve this?

Thanks.

BTW, I also agree with previous posters that the alternation of line colors is not helpful for the code, I think just making it fainter would be …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You think robo calls are bad. Here in Canada, there were robo calls by the conservatives directed at the people favorable to an opposing party, the calls redirected them to the wrong location to go and vote. It's been a big scandal for the past few weeks.

I guess the political parties have realized that people can't install a spam filter on their phones!

Just another way in which the politicians disgrace the democratic process, treating the people as mindless kattle who can be told what to do or fooled by recorded messages delivered by robots!

Why is it wrong for a people to have a county in their homeland?

rant:
The idiocy of that statement compels me to comment on it, although I find it out-of-place in this IT forum. The idea of "people having a country in their homeland" is a theoretical concept. It's the concrete effects that matter. If having a country gives you more rights, equality, freedoms, laws, support systems, power (in the democratic sense), peace, etc., then that's all great, because these things are great. That's what we often like to picture a country to be about, but it isn't always so in its concrete implementation. If having a country means giving you a US-backed license for war, genocide, discrimination, theocratic rule, arms racing, torture, reckless spy operations and foreign abdunctions, and countless other crimes, then that's all wrong. The theoretical concept of "people having a country in their homeland" is meaningless …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Because the object is passed by value to the area function, meaning that another, temporary rectangle object is created and passed to the area function. When the area function is done, that temporary is destroyed. Afterwards, when the main function ends, the obj is destroyed.

Try changing the area function to pass by reference as so:

float area(const Rectangle& rect);

and similarly for the friend declaration of it. This should eliminate the temporary and result in only a single destruction.

Another test you can do is to create a copy-constructor as so:

Rectangle(const Rectangle& lhs) {cout << "Rectangle copy-constructed!" << endl; len = lhs.len; bre = lhs.bre; }
lastbencher commented: Thanks :) +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The M_PI is not standard but appears in many compilers. That is just the pi constant, so you can create your own constant const double pi = 3.14159; and substitute pi for the M_PI in the code.

To be standard, the time function appears in #include <ctime> and should be qualified as std::time.

Sorry about that, I wrote the code pretty quickly.

Let me guess, you tried to compile with Visual Studio, which is the only main compiler that I know of which would give you this kind of problem.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

All your prof wants of you is that you compute the function given here for M = 1000. It requires a loop and a few basic math operations.

So much ink has been spilled on this issue, it's crazy.

Forget all the random shuffling business. This is a just about translating a basic math equation (summation with some factorial in it) into a computer program.

Just to end the 4 weeks of suffering:

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <set>

int main() {
  const int N = 1000;

  double num = N - 1;
  double denom = N;
  double avg = 2.0;
  for(int i = 2; i <= N; ++i) {
    avg += num / denom;
    num *= double(N) - i;
    denom *= double(N);
  };
  std::cout << "Theoretically, the average number of random songs played before a repeat event is " << avg << std::endl; 

  std::cout << "Approximately, the average number of random songs played before a repeat event is " 
        << (std::sqrt(M_PI * N / 2.0) - 1.0 / 3.0 + std::sqrt(M_PI / (2.0 * N)) / 12.0 - 4.0 / (135.0 * N)) << std::endl;

  srand((unsigned int)time(NULL));

  double exp_avg = 0.0;
  for(int i = 0; i < 1e6; ++i) {
    std::set<int> s;
    int j = 0;
    while(s.insert( rand() % N ).second) ++j;
    exp_avg = (i * exp_avg + double(j)) / (i + 1);
  };
  std::cout << "Experimentally, the average number of random songs played before a repeat event is " << exp_avg << std::endl; 

  return …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Don't even bother trying to give a circumvented explanation on the legitimacy of your purposes for this type of code. You're not talking to idiots who were born yesterday, don't insult our intelligence.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Are you kidding me? You have written ~Node(){delete this;};. This is wrong on so many levels. You should not do this, you don't need to do this, and it will most probably crash your program when you run this.

You have to consider the "this" pointer as a constant, in fact, it is a constant. Its actual type is either Node * const or const Node * const (if the member function is declared const).

You cannot modify the this pointer inside a member function. This is what the compiler is telling you when it says "lvalue is required as left operand of assignment". An lvalue means a variable that can be modified, and this does not qualify as an lvalue.

As L7Sqr suggested, you need to create an iterator class that stores a pointer to a Node and then you can implement the increment operator (and dereferencing operators) as you already did.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think that at that age, if the kid wants to learn something, he'll learn it regardless of how hard it is. If he doesn't want to learn it, it won't matter much how easy it is. That's just the kind of curiosity and passion that kids have at that age (when they are old enough to understand complex things, but too young for their minds to be too occupied by other things.. you know what I'm talking about..).

The question is not a matter of the most "objectively easy" language (that is, if "objective" and "easy" can even make any sense together). The question is what topics of programming (or IT) can be interesting to kids of that age and which language (or tools) gets them to do that the quickest. In other words, how to direct the interest of the kid towards the path of least resistance.

My initial interests were in math stuff (simulation, 3D graphics, etc.) and software engineering puzzles. Delphi and C++ were great languages to progress quickly with those interests in mind.

Other interests, other fields, would mandate different languages as the easier entry-point to start getting some basic programs working easily. Python is probably good for basic computer sciency work (algorithms, data structures, etc.). VB is probably better for GUI apps and the like.

The problem with teaching programming to kids is that there are so many possible things that can trigger their interest. You cannot commit to one area or type of …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The edit button seems to require a number of page refreshing and/or leaving and coming back to the thread.

Also, I have no idea what you intended to initially write in your d.mkv example.
You should refer to this page about the syntax rules. I think what you are looking for is the inline code (or code span) which requires one or two backticks (or "accent aïgu") to bracket the code. "d.mkv" (one backtick around the "code")

EDIT: nevermind, you're right the percent 0 and 2 combination always disappears completely, the escaping with backslash doesn't help it.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Editing of posts works fine? As always, you can only edit your post for up to 30 minutes after posting.

Wrong, at least, not right now. Editing of posts does not work (no button appears for it, unless it's now somewhere else that I can't find), and it's not a time matter, in one of my last posts I tried to edit less than a minute after, and there was not way to do so.

EDIT: After all, it seems that the edit post works, except that it doesn't appear immediately, I had to leave the thread and come back, just refreshing the page didn't do anything. Also, if you forget to enter something in the "reason for edit" your edit gets deleted! This time it didn't matter, but I bet people will be really annoyed by that really quickly.

The site was in read-only mode for the last 2 days while we went through the migration process. Due to some permissions bugs in the old system, a couple of messages did slip through (fewer than 10, I believe). Unfortunately, those did not make it into the migration script.

I think rubberman was referring to the fact that some old threads are simply not accessible at all. They show up in the thread list on the forums but when you click on them they pop a 404 error (due to excessive re-direction in the links, "This webpage has a redirection loop.", i.e., an infinite loop that …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Shortly after getting my hands on my first computer when I was 13 (in 1998 or so) I wondered how applications were made, so I started making simple GUI apps with RapidQ (a free open-source VB-like programming language and GUI tool). A couple of months later I switched to Delphi and started going through NeHe tutorials on OpenGL 3D graphics programming. I spent quite a few years writing computer games, 3D modeling tools, physics engines and computational geometry code, among other dabblings in encryption, compression and AI. Meanwhile in my boring and way-too-easy high-school math courses, I spent my time programming RPG games on my TI-83 graphic calculator (in some ASM-like language). As I left high-school, I also left Delphi for the promise land of C++, and boy am I happy that I did. Working my way through a mech. eng. degree, I programmed on the side doing computer games and multi-body dynamics simulators. Through engineering work, I've also worked with C, Fortran, Matlab / Simulink, LabVIEW, Java, and others. Now, doing a PhD, I've almost exclusively been programming in C++ for several years (and Matlab/Simulink from time to time), mostly for multi-body dynamics, robot control software and artificial intelligence.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here are some of my favorites:

"Hero­ism breaks its heart, and ide­al­ism its back, on the intran­si­gence of the cred­u­lous and the mediocre, manip­u­lated by the cyn­i­cal and the corrupt." - Christopher Hitchens (R.I.P.)

"You know you're a programmer if you always start counting from 0." - Geek saying

"When you smash the box, you have no choice but to think outside of it." - Me (in the context of describing generic programming techniques)

"Yes, inspiration exists, but it has to find you working." - Picasso

"As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Einstein

"Alles hat ein ende, nur die wurst hat zwei." - German saying ("Everything has an end, only sausages have two.")

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Or maybe:

int main() {
  return 0; // 0 is an object and it doesn't have a name.
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your algorithm is called "Selection Sort".

And no, it is not similar to heap sort. It is true that heap sort has a second phase where the max (or min) elements are extracted from the unsorted section and stacked at the beginning or end of the overall array. However, the main aspect of this phase is that the heap structure is always conserved. A heap structure is a way of arranging the elements of the array such that the max (or min) always appears in the first position in the array. If you set up the structure properly, you can efficiently remove the max (or min) element and update the heap structure to put the new max (or min) element at the first position. So, the heap sort algorithm first rearranges the elements of the array in a heap structure, and then it takes the max (or min), puts it at the last position in the array (before the start of the sorted section of the array), then it updates the heap structured section of the array, and repeats until the entire array is sorted. So, the second phase is similar to Selection Sort, but the important thing is that you don't have to look for the maximum element (which is linear-time) but instead maintain the heap structure (which is log-time, which is much faster).

You can explore heap sort by using the standard sort_heap algorithm, see the example on the reference page.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you mean that you want to call the constructor from the body of that constructor, recursively. That's possible (with the syntax rubberman showed). However, it is nasty and useless because if you want to create your object through some recursive process, then you can easily put that recursive process in another function (e.g. a private helper function). That solution is much better:

class ClassX {
private:
    int knit;
    int perl;
    void recursingInit(int);
public:
    ClassX();
    ClassX(int);
};

void ClassX::recursingInit(int n) {
  // do something..
  //recurse:
  recursingInit(n-1);
};

ClassX::ClassX() // default ctor
: knit(1), perl(2)
{
   this->recursingInit(6);
}

ClassX::ClassX(int warp)
: knit(warp/2), perl(warp)
{
   this->recursingInit(warp);
}

However, if what you are trying to do is like rubberman described, that is, to call one constructor from another, then you should use a feature of the new C++ standard (C++11) called "delegating constructors" which allow you to call upon another constructor (or "delegate" the construction to another constructor). As so:

class ClassX {
private:
    int knit;
    int perl;
public:
    ClassX();
    ClassX(int);
};

ClassX::ClassX() // default ctor
: ClassX(6)  // "delegating constructor" call, since C++11
{
}
ClassX::ClassX(int warp)
: knit(warp/2), perl(warp)
{
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Ahh, good old bug-riddled GSL! If I had a dime for every bug in GSL, I'd be a rich man.

Obviously, the problem is that you run out of memory. Meaning you have a memory leak in a loop. If you call the above function within a loop without freeing the memory of both the rng and its state, you'll eventually run out of memory.

I hope that you understand how random number generators work and why you only need to seed it once. In theory at least, you shouldn't need to recreate a new random number generator more than once. I'm not familiar with GSL's rng code, but if it is logical, then it shouldn't require you to create the rng more than once, but again, GSL is not known for being logical or well programmed, quite to the contrary.

The real answer to your problem is to use the random number generators provided by the C++ standard <random> library or by Boost.Random. Which are both virtually identical and very feature-rich.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Because data members that are in the private scope are only accessible from the class in which they are declared (or a friend), but not in derived classes.

You must use the protected scope to make the data members of the base class accessible to the derived classes. In other words:

class BankAccount
{
protected:   // NOTICE 'protected' here, not 'private'.
	int accountNum;
	double balance;
public:
	bool setAccountNum(int num);
	int getAccountNum() const;
	double getBalance() const;
	void depositMoney(double money);
	bool withdrawMoney(double money);
	void displayAccount() const;
	BankAccount();
};

See this for more info.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Easy, you just return a reference from the indexing operator. Here's what I mean:

class int_array {
  private:
    int arr[10];
  public:
    // element accessor:
    int operator[](int i) const { return arr[i]; };
    // element mutator:
    int& operator[](int i) { return arr[i]; };
};

And that's it, same for std::string elements or anything else.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

That's easy enough, all you need is to construct a predicate functor (and btw, that copying to temporary and turning the entire array into lower case is just incredibly wasteful).

What about this:

template <typename Predicate>
        bool Contains(Predicate pred) const
        {
            for (auto it = TypeData.cbegin(); it != TypeData.cend(); ++it)
            {
                if (pred(*it))  // evaluate predicate.
                    return true;
            }
            return false;
        }

        bool Contains(const T& ToFind) const // don't forget const!!!
        {
            return Contains([&ToFind](const T& rhs) { return (rhs == ToFind); });
        }

Now, all you need is a string version of this predicate that is case-insensitive.

First of all, when you get into the business of specializing templates for standard STL containers (like string) you should keep in mind that std::string or std::vector<T> or others are not as simple as they appear, because in reality they are, respectively, std::basic_string< C, CharTraits, Allocator> and std::vector<T, Allocator> . So, you should normally specify all template arguments in your specializations, otherwise you might get surprises later.

So, here is a simple predicate functor for case-insensitive comparisons:

// General template for non-strings.
template <typename T>
struct CaseInsensitiveCompare { 
  char cannot_create_a_case_insensitive_comparison_for_non_string_type[0]; // this will throw the compiler on a fit of rage!
};

// Specialize for strings:
template <typename C, typename CharT, typename Allocator>
struct CaseInsensitiveCompare< std::basic_string<C, CharT, Allocator> > {
  typedef std::basic_string<C, CharT, Allocator> argument_type;
  typedef bool result_type;
  
  argument_type lhs;
  CaseInsensitiveCompare(const argument_type& aLhs) : lhs(aLhs) {
    using std::tolower; //include standard tolower in ADL.
    for(auto it = lhs.begin(); it …
triumphost commented: I understand partially but thanks.. I'll look into it more to fully understand. +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you are going to create a function template to sort an array, I would recommend that you follow the same signature as the std::sort function. The problem with your function template is that it is not generic enough, it only applies to a C-style array of types which can be compare with > (greater-than) operator. If you look at std::sort, it doesn't suffer any of these problems, it applies to any container or array type and it allows a special comparison function to be provided.

template <typename BidirIterator, typename CompareFunction>
void insSort(BidirIterator first, BidirIterator last, CompareFunction compare)
{
        BidirIterator i = first; ++i;
	for(; i != last ; ++i)
	{
		typename std::iterator_traits<BidirIterator>::value_type key = *i;  // in C++11: auto key = std::move(*i);
		BidirIterator j = i;
                BidirIterator j_prior = j; --j_prior;
                while((j != first) && (compare(key, *j_prior)))
		{
			*j = *j_prior; // in C++11:  *j = std::move(*j_prior);
			--j; --j_prior;
		}
	        *j = key;  // in C++11: *j = std::move(key);
	}
};

template <typename BidirIterator>
void insSort(BidirIterator first, BidirIterator last) {
  insSort(first,last,std::less< typename std::iterator_type<BidirIterator>::value_type >());
};

So, for your problem, you should either create a < less-than operator overload for your Name class, or provide another comparison function to the insSort call.

As for calling insSort with an array, like you have, you just do:

insSort( &nameArray[0], &nameArray[0] + sizeof(nameArray) / sizeof(nameArray[0]) );
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, one way to do this is with a friend function:

#ifndef TEMPLATES_H_INCLUDED
#define TEMPLATES_H_INCLUDED
#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class CustomType
{
    private:
        vector<T> TypeData;
        void Insert() {}
        template<typename A, typename... Args>
        CustomType& Insert(A FirstArg, const Args... RemainingArgs)
        {
            this->TypeData.push_back(FirstArg);
            Insert(RemainingArgs...);
            return *this;
        }

    public:
        CustomType() {}
        template<typename A, typename... Args>
        CustomType(A FirstArg, const Args... RemainingArgs)
        {
            this->TypeData.push_back(FirstArg);
            Insert(RemainingArgs...);
        }
        ~CustomType() {}

        int size() {return TypeData.size();}
        
        //Other functions/overloads removed at the moment.. just for this post.
        
        friend bool Contains_impl(const CustomType<string>& aThis, const string& ToFind);

        template <typename U>
        friend bool Contains_impl(const CustomType<U>& aThis, const U& ToFind);
        
        bool Contains(const T& ToFind) const {
          Contains_impl(*this, ToFind);
        };
};

inline
bool Contains_impl(const CustomType<string>& aThis, const string& ToFind)
{
  // do the extra stuff here.

  for (unsigned I = 0; I < aThis.TypeData.size(); I++)
  {
    if (aThis.TypeData[I] == ToFind)
      return true;
  }
  return false;
}

template <typename T>
bool Contains_impl(const CustomType<T>& aThis, const T& ToFind)
{
  for (unsigned I = 0; I < aThis.TypeData.size(); I++)
  {
    if (aThis.TypeData[I] == ToFind)
      return true;
  }
  return false;
}

#endif // TEMPLATES_H_INCLUDED

When it comes to function templates or member functions of class templates, don't specialize, overload instead!

If you have many functions in a class that should have this same pattern, then you might consider either specializing the entire class template, or creating a helper class template that is specialized (and contains only those functions that need to be specialized).

Also, these types of patterns are often implemented …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Machine Learning is the field of AI that studies this.

An AI agent that learns from past mistakes and successes is in the branch called reinforcement learning.

There are many approaches to this problem. Most notably, you have Q-learning algorithms, and Genetic algorithms (or evolutionary algorithms). The algorithms themselves are pretty easy to implement, but the hard part is to formulate the problem correctly in terms of what actions the agent can take and how the rewards are calculated.

A while ago, I implemented a number of these algorithms to get a bunch of virtual mice to learn how to feed off a pile of cheese without being caught by a cat that was guarding the food. It was, to some extent, pretty successful. In this case, the genetic algorithm worked the best.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The reason why the code that you posted doesn't work is because the champ_type string that you obtain from the user and the one that is inside the object "obj" are not the same. The one you obtain from the user is a local variable in the main() function, which is not the one inside the object "obj".

If you move the obj initialization (line 85) to after you get the input from the user (after line 102), all should work as expected.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

No, don't use goto for such a simple purpose. If nothing more, it's better to replace it with while(true) { }; loop (and a break; statement somewhere in the loop). At the least, this makes it clear that the code is a loop, and respect indentation rules, that alone is already a good argument to motivate using a traditional loop statement (for, while, do-while) instead of a label/goto pair.

Your code does a generation of permutations of letters of a word, may I suggest you take a look at std::next_permutation, and either get inspired from it or use it directly (hints: the number of permutation is fixed (implying a fixed-length loop); and you shouldn't need a random-number generator anywhere, the sequence of all permutations is something that is easily obtained systematically and is deterministic).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your Insert functions seem to work as it should. I ran your code and all the unit-test passed correctly. What's the problem?

Your function to build the linked-list is not going to put the elements in sorted order, you need to do this:

void GetRecursive(LinkedList<T> * _valueList, BSTNode<T> * node)
		{
			if(node->left != NULL)
				GetRecursive(_valueList, node->left);
			_valueList->Insert(node->value, NULL);
			if(node->right != NULL)
				GetRecursive(_valueList, node->right);
		}

Notice that the inserting of the current item must go in between the left and right inserts.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> The PrintValue function had to go to the .cpp file.

If you mark the functions with the keyword inline , then you won't have to put the definition in the cpp file (if you don't want to).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> This BST is used throughout a webcrawling application that I am designing, and as such, it would take an especially long time to re-hash all the calls to it and such.

If this is not for an assignment which specifically requires you to design your own BST, then why are you designing your own BST? Use the standard facilities already available, in this case, std::set which is a BST, or, similarly, std::map , or the hash-function versions of them std::unordered_set and std::unordered_map . Don't reinvent the wheel!

If you are looking for a production-grade implementation of a BST, then grab a production-grade implementation of a BST. The standard ones are good. If you need cache-optimized versions, you might have to look a bit further, there are plenty of solutions available out-there, for starters I have made an implementation of a B-tree and a Cache-oblivious B-tree, which can easily be used as storage for a red-black BST.


>> So I guess my question is - would it be possible to redesign my BST class without having to rehash all the calls and goings-on outside of it? I do believe it functions as far as input and output go - but when it comes to memory management, it doesn't work.

The problems you have with your implementation are about its structure. You could certainly fix it up to a working status, but it's more of a hassle and hazard than restructuring …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

First of all, yes, you are correct in that Foo * myFoo = new Foo(); must be freed with delete mFoo; .

The main problem that I see with your code is the way you handle the values stored in the nodes of your tree. Basically, the values are given to your tree (from the insertions) as non-const references, of which you take the addresses (or pointers) and store them in the nodes of the tree. Then, when you delete a node from the tree, you call delete value; and that is a big problem, because you have no control over how the value was created, you have no ownership right to delete that value.

Another related problem is that when you copy a node (either through the assignment operator or copy-constructor), you do a shallow copy of the pointers (value, left, right) which is all wrong and dangerous. When doing this, both the source node (which was copied) and the destination node (to which the source node was copied) have pointers to the same left-right nodes and to the same value object. When you delete both the source and the destination nodes, you will request the deletion of the same memory twice! Boom! Crash! You need to make a DEEP COPY, meaning not copying the pointers, but allocating new memory and copying the content pointed to by the pointers in the source node. Also, you need a copy-constructor that does that, see the Big Three, …