g_tree_insert overwrites all data - binary-tree

I wonder how I should use the GTree (from GLib) to store data? Every new value I insert into GTree with g_tree_insert routine is overwrite the previous one!
GTree *tree; //init
tree = g_tree_new( g_str_equal ); //"g_str_equal" is a GLib default compare func
//...
for( i = 0; i < 100; ++i )
g_tree_insert( tree, random_key(), random_value() ); //insert some random vals
//
printf( "%d", g_tree_nnodes( tree ) ); //should be 100? NO! Prints "1"!!!
What am I doing wrong? Thank you.

That's because equality is not the same as comparison, g_tree_new needs a function that gives you the order of two keys (i.e. dictionary order), not just whether they are equal or not.

I think I found a solution. The problem was in the:
tree = g_tree_new( g_str_equal );
The official tutorial said it is the one of the default GCompareFunc's, so I decided to use it (by the way, I successfuly use it in the GHashTable with no problem). But it is the trouble. The correct initialization is:
tree = g_tree_new((GCompareFunc)g_ascii_strcasecmp);
And voila! It works! Thanx to IBM tutorials.

Related

I am Trying to solve a problem in hacker rank. My algorithm is okay but can't find the output

I am Trying to solve a problem in hacker rank, Which title is breaking best and worst. but the function I write didn't give proper output for any of the test case but in my visual code ide it is giving the correct result.
The problem is find out the sequence of increasing number and decreasing. finally return the result in two space separated integers. I've write the function to the point and my IDE is giving the accurate result but in hacker rank it's giving error
here is the link of problem
my solution approach
function breakingRecords(scores) {
let increase = 0;
let decrease =0;
{code that properly increase the value of
increase and decrease.}
}
const result = (increase,decrase);
return result;
}
What I made mistake in my code is I return my value normally in two variable but those value I have to return in array like
const result = [increase,decrase];
return result;
That's it!!

Using the Haxe While Loop to Remove All of a Value from an Array

I'm wanting to remove all of a possibly duplicated value in an array. At the moment I'm using the remove(x:T):Bool function in a while loop, but I'm wondering about the expression part.
I've started by using:
function removeAll(array:Array<String>, element:String):Void
while (array.remove(element)) {}
but I'm wondering if any of these lines would be more efficient:
while (array.remove(element)) continue;
while (array.remove(element)) true;
while (array.remove(element)) 0;
or if it makes any kind of difference.
I'm guessing that using continue is less efficient because it actually has to do something, true and 0 are slightly more efficient, but still do something, and {} would probably be most efficient.
Does anyone have any background information on this?
While other suggested filter, it will create a new instance of list/array which may cause your other code to lose reference.
If you loop array.remove, it is going to loop through all the elements in the front of the array every time, which is not so performant.
IMO a better approach is to use a reverse while loop:
var i = array.length;
while(--i >= 0)
if(array[i] == element) array.splice(i, 1);
It doesn't make any difference. In fact, there's not even any difference in the generated code for the {}, 0 and false cases: they all end up generating {}, at least on the JS target.
However, you could run into issues if you have a large array with many duplicates: in that case, remove() would be called many times, and it has to iterate over the array each time (until it finds a match, that is). In that case, it's probably more efficient to use filter():
function removeAll(array:Array<String>, element:String):Array<String>
return array.filter(function(e) return e != element);
Personally, I also find this to be a bit more elegant than your while-loop with an empty body. But again, it depends on the use case: this does create a new array, and thus causes an allocation. Usually, that's not worth worrying about, but if you for instance do it in the update loop of a game, you might want to avoid it.
In terms of the expression part of the while loop, it seems that it's just set to empty brases ({}) when compiled so it doesn't really matter what you do.
In terms of performance, a much better solution is the Method 2 from the following:
class Test
{
static function main()
{
var thing:Array<String> = new Array<String>();
for (index in 0...1000)
{
thing.push("0");
thing.push("1");
}
var copy1 = thing.copy();
var copy2 = thing.copy();
trace("epoch");
while (copy1.remove("0")) {}
trace("check");
// Method 2.
copy2 = [
for (item in Lambda.filter(copy2, function(v)
{return v != "0";}))
item
];
trace("check");
}
}
which can be seen [here](https://try.haxe.org/#D0468"Try Haxe example."). For 200,000 one-character elements in an Array<String>, Method 2 takes 0.017s while Method 1 takes 44.544s.
For large arrays it will be faster to use a temporary array and then assign that back after populating ( method3 in try )?
OR
If you don't want to use a temp you can assign back and splice ( method4 in try )?
https://try.haxe.org/#5f80c
Both are more verbose codewise as I setup vars, but on mac seems faster at runtime, summary of my method3 approach:
while( i < l ) { if( ( s = copy[ i++ ] ) != '0' ) arr[ j++ ] = s;
copy = arr;
am I missing something obvious against these approaches?

GAMS decimal numbers

I have the following code:
loop (d,
rnd(d)=uniformInt(1,nd)
);
I am going to use the integer numbers rnd(d) as an index of another set s(i). But for example when rnd(d)=34.000 however, it is integer, but s(34.000) has no valid index since, 34.000 is not 34 !! and GAMS shows a error message.
I don't know if #Lutz solution worked out for you. In case it did not, you can try the following:
First, it is not necessary to loop over the set d, just a simple:
rnd(d) = uniformInt(1,nd);
will suffice.
Next line can go like:
loop(d,
s(i)$(i.val = ord(d)) = . . .;
);
If you still have issues, then using #Lutz suggestion just append '*1.000' to 'ord(i)' and/or 'rnd(d)', whichever is giving you issues.
Is i an ordered set? If yes, you could use something like this:
loop(d,
s(i)$(ord(i)=rnd(d)) = ...;
)

Storing pointers wrong/not using Unordered_map.find correctly

so the title essentially says it all. I am writing a symbol table in c++ for a compiler project I am working on, and all is going well except for looking up identifiers in the table.
So this is how I store into the table (pseudo like):
vector<symbolTable*>* symbolStack = new symbolTable();
//where a symbolStack is a vector of unordered_maps (symbolTables),
//each iteration in vector referencing a new block of code.
string* check = new string(root->children[0]->lexicode->c_str());
symbol* sym = new symbol();
...... //setting sym info
symbol_entry pair = make_pair(check, test)
//the unordered_map has keys of (string*, symbol*)
symbolStack[tableNumber]->insert(pair);
I am pretty solid that this works, as I have tested printing the size/infos from the map and it all seems to be storing as expect. Here is where the problem is happening for me (this takes place in a different function later):
for(int i = 0; i =< tableNumber;i++){
auto finder = symbolStack[i]->find(checkS) //checkS == check from above
if(finder == symbolStack[i]->end()) cout<<not found;
else cout<<we did it!!!!
My else is never reached. However, if I do this assuming the string*->c_str() == "test":
cout<<string->c_str(); // prints out "test"
cout<<finder->second->c_str() //prints out "test".
So the question. Why is it finding the key, and knowing it found the key, but at the same time returning that is has reached the end of the symbol stack without finding it? I have been trying to figure this out for a good 4 days solid now. Is it that my pointers are somehow off? Any insight is appreciated greatly.
So somewhat answer to my own question.
First I will say this: I have concluded the comparison with find() or similar methods do not work because for some reason the pointers are not matching up. I have no clue why this is still, or what I am doing wrong.
What I did to solve my issue and complete my code is this:
for(int k = 0; k<= tableNumber; k++){
unordered_map<string*,symbol*>::iterator it;
for(it = symbolStack[k]->begin(); it != symbolStack[k]->end(); it++)
{
string a = targetString->c_str();
string b = it->first->c_str();
if(a.compare(b) == 0) cout<<"You have found the match! \n";
}
}
}
So this answers how to get it working pragmatically if somebody else is in a similar ship, however not really answers why my other attempt failed other than noticing the pointer values were different.
In symbolTable you store pointers to strings as keys, not strings themselves. Therefore unordered_map compares pointers, not strings, and cannot find matching items. When you reconstruct the key string (as in your answer, using string b = it->first->c_str()), the comparison on strings works again. So, either you need to store string instead of string * in symbolTable, or you need to provide your own comparison function that will compare keys of type string *.

Actionscript 3.0 random number script not running

Hello I am creating a simple game that asks questions. However I would like the questions to be randomed throughout the game.
So, there are 11 questions so I random a number between one and eleven
Then it would set an array value so that if the question has already been chosen it would not be chosen again.
Once it has randomed a value for a question that has not been asked it goes to that frame. (Using Adobe Flash)
So, simply:
Random number -> has this question been asked? -> Yes (restart script) -> No (Go to corresponding frame)
I have set up a code but for some reason it does not run. When I use "Stop();" it ignores it and keeps going through the frames. What is going on here? Can someone create a code for me that just works? I can read code just fine, but I fail at writing it. So I can change the frames where necessary.
Thanks in advance!
Keep two arrays; one of all the questions, unmodified, and one that you choose the questions from, removing as you go. Something like:
var allQuestions:Array = ["...", "...", ...];
var questions:Array = [];
public function getRandomQuestion():String
{
// if our questions are empty, fill them
if( questions.length == 0 )
this.fillQuestions();
// choose a random question index
var index:int = int( Math.random() * questions.length );
// this will remove that question from the array and return it. The [0] at the end
// is because splice returns an array, so we're returning the first value of
// it (i.e. the question we just removed)
return questions.splice( index, 1 )[0];
}
public function fillQuestions():String
{
// fill the questions array here from our full array
for each( var s:String in allQuestions )
questions.push( s );
}

Resources