C Table implemented by an array - c

Basically I'm trying to implement a table with help of an array. The array functionality is already given and should not be altered. What I'm having trouble configuring is my table_remove function. Keep in mind that I'm not striving for the most effective way to do this.
What I tried to do is loop through the entire table to find if there is a key that matches.
If the key is found, save the position.
If not exit.
So after the position is found I set it to free the key & value on that position in hope that it will 'remove' the key & value pair from that position. However, my given test program returns "Removing the last element from a table does not result in an empty table.". If I add in the end "array_setVal(array, NULL, index) then the entire program crashes (Probably because it tries to write on that null position further on in the test).
So now I'm wondering if I'm approaching this issue the wrong way and have to do further operations to actually remove the value from the position without sort of messing up the position itself so next time I use table_insert, the position will be empty and another key & value pair will be inserted in that spot.
int saveRemovedIndex = -1;
/* Check if the key already exists */
for(int indexCounter = 0; indexCounter <= MAXINDEX; indexCounter++){
i = array_inspectValue(t->values, indexCounter);
if (t->cf(i->key,key)==0) {
saveRemovedIndex = indexCounter;
break;
}
}
/* Checks if the key actually exists in the table.
* If it exists, remove it. Else quit.*/
if (saveRemovedIndex != -1) {
i = array_inspectValue(t->values, saveRemovedIndex);
if(t->keyFree!=NULL) {
t->keyFree(i->key);
}
if(t->valueFree!=NULL) {
t->valueFree(i->value);
}
} else {
return;
}

Related

Longest path with N steps in matrix

I'm trying to find a simple path of length N in a RxC matrix, given a starting cell. The path should follow a restriction, given by a boolean function. The goal is to later use this to find the longest path in the matrix.
I got a solution set up, however I don't know how to modify it to know when a solution does not exist.
My solution consists of a DFS approach using backtracking. The solution is correct when there is one, but the program returns the longest path found instead of saying such path doesn't exist.
I know there are similar problems with solutions available but I'd like to understand where my logic is failing.
Here's the code (from a cell we can move in all 8 directions):
Bool DFS(Map *map,Point* srcPt,short steps,Bool (*restrictionCompare)(Point *p1, Point *p2))
{
Point *target;
short row = getPointRow(srcPt);
short col = getPointCol(srcPt);
// Found N-steps path!
if (steps == 0)
{
puts("Path found!\n");
return 1;
}
//Mark the M[row][col] as visited
markAsVisited(map,row,col);
// Iterate over all 8 directions of a cell
for (short i = 0; i < DIRECTIONS; ++i)
{
short coords[2];
// Get a valid adjacent cell
if (getNeighbour(map,srcPt,i,coords,restrictionCompare) == FALSE) continue;
target = getMapPoint(map,coords[0],coords[1]); // This is the valid neighbour
//if cell wasn't visited before...
if (isVisited(target) == FALSE)
{
// ..recursively call DFS from cell
if(DFS(map,target,--steps,restrictionCompare) == TRUE)
{
// Show point
showPoint(target);
return TRUE;
}
}
}
// Backtrack
markAsUnvisited(map,row,col);
return FALSE;
}
An example of path of length found by the program:
Any suggestions on how to improve the code's efficiency is also welcome.

My strcmp doesn't return 0 when it should

Context : I'm searching for all the words contained in a 2d array (horizontally,vertically and diagonaly).
So what I do is I get all the possible words, check if they're in the given dictionary and if they are store them in an array. The thing is, I don't want it to have duplicates.
Here's a snippet of the code:
for (i=l-1;i>=0;i--){
palavra[aux]=mat[i][caux];
for (j=i;j>=0;j--){
palavra[aux]=mat[j][caux];
palavra[aux+1]='\0';
for (it=0;encontradas[it]!=NULL;it++){
if (strcmp(palavra,encontradas[it])==0)flag=1;
else flag=0;
}
if (flag==0) {
r = palavra_existe(dic,palavra);
if (r!=0) {
found[auxenc]=mystrdup(palavra);
auxenc++;
}
}
flag=0;
aux++;
}
aux=0;
}
The
if (strcmp(palavra, found[it])==0)flag=1
line is there to check if the formed worded has been found already, to avoid creating a duplicate. The problem is it doesn't work, duplicates appear anyway (as the flag variable never takes the value 1).
What could I be missing here?
The flag variable does get the value 1, but then it turns back to 0 again in the next iteration.
Set flag to zero before the loop, and when you find a match you set it to 1 and exit the loop:
flag = 0;
for (it = 0; encontradas[it] != NULL; it++) {
if (strcmp(palavra,encontradas[it]) == 0) {
flag=1;
break;
}
}
(Exiting the loop isn't needed for the logic to work, but there is no point in looping through the rest of the items once you have found a match.)

How does ng-repeat work?

I dissected ng-repeat and extracted the code blocks attached, seeing that these comprise the logic that handles the repeating algorithm (which I want to understand how it works).
I have quite a few questions, but since they are all about the internals of ng-repeat I chose to ask them all here. I don't see any reason to separate them into different SO questions. I have marked inline to which line(s) of code each question refers to.
Why do they need to make sure that trackById is not the native hasOwnProperty function? (that's what that assertNotHasOwnProperty function does, part of Angular's internal API)
As far as my intuition go, this code executes on items already in the repeater, when it has to update the collection - it just picks them up and pushes them into the list for processing, right?
This code block obviously looks for duplicates in the repeater collection. But how exactly does it do that is beyond me. Please explain.
Why does Angular have to store the block object both nextBlockMap and in nextBlockOrder?
What are block.endNode and block.startNode?
I assume the answer to the above question will clarify how this algorithm work, but please explain why it has to check if the nextNode has (been) '$$NG_REMOVED'?
What happens here? Again, I assume question 6 will already provide an answer to this one. But still pointing that out.
Like I said, I dug through ng-repeat to find the code I deemed relevant to the repeating mechanism. Plus, I do understand the rest of the directive. So without further ado, here is the code (from v1.2.0):
length = nextBlockOrder.length = collectionKeys.length;
for (index = 0; index < length; index++) {
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
trackById = trackByIdFn(key, value, index);
// question #1
assertNotHasOwnProperty(trackById, '`track by` id');
// question #2
if (lastBlockMap.hasOwnProperty(trackById)) {
block = lastBlockMap[trackById];
delete lastBlockMap[trackById];
nextBlockMap[trackById] = block;
nextBlockOrder[index] = block;
// question #3
} else if (nextBlockMap.hasOwnProperty(trackById)) {
// restore lastBlockMap
forEach(nextBlockOrder, function(block) {
if (block && block.startNode) lastBlockMap[block.id] = block;
});
// This is a duplicate and we need to throw an error
throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
expression, trackById);
// question #4
} else {
// new never before seen block
nextBlockOrder[index] = { id: trackById };
nextBlockMap[trackById] = false;
}
}
for (index = 0, length = collectionKeys.length; index < length; index++) {
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
block = nextBlockOrder[index];
// question #5
if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;
if (block.startNode) {
// if we have already seen this object, then we need to reuse the
// associated scope/element
childScope = block.scope;
// question #6
nextNode = previousNode;
do {
nextNode = nextNode.nextSibling;
} while(nextNode && nextNode[NG_REMOVED]);
if (block.startNode != nextNode) {
// existing item which got moved
$animate.move(getBlockElements(block), null, jqLite(previousNode));
}
previousNode = block.endNode;
} else {
// new item which we don't know about
childScope = $scope.$new();
}
// question #7
if (!block.startNode) {
linker(childScope, function(clone) {
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
$animate.enter(clone, null, jqLite(previousNode));
previousNode = clone;
block.scope = childScope;
block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0];
block.endNode = clone[clone.length - 1];
nextBlockMap[block.id] = block;
});
}
}
lastBlockMap = nextBlockMap;
After some tinkering with the directive, I became familiar with ng-repeaters code, and managed to answer some of my questions. I highlighted in bold the things I couldn't yet figure out on my own, and would appreciate if anyone could shed some light on the bold parts:
The ID is tested for hasOwnProperty, because they use that method to check whether the ID is present in the iteration objects (lastBlockMap, nextBlockMap) (this process explained below). I couldn't find out on what scenario this can actually happen, however.
I was correct in my assumption. nextBlockMap contains all items that will be transcluded on the current model change. lastBlockMap contains everything from the previous model update. It used for finding duplicates in the collection.
OK, this one is pretty straightforward actually. In this for loop, ng-repeat fills up nextBlockMap with items from lastBlockMap. Looking at the order of ifs, it's easy to see that if the item cannot be found in lastBlockMap, but it is already present in nextBlockMap (meaning, it was already copied there from lastBlockMap, and therefore its trackById appears twice in the collection) - it's a duplicate. What the forEach does is simply run through all initialized items in nextBlockMap (blocks that have a startNode property) and push their ID back into lastBlockMap. I cannot however understand why this is necessary.
The only reason I could find for separating nextBlockOrder (all trackByIds in an array) from nextBlockMap (all block objects in a trackById hash), is this line, which working with an array makes it an easy and simple operation: if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;. It is explained in the answers to question 5 and 6:
block.startNode and block.endNode are the first and last DOM nodes in the block belonging to an item in the collected being repeated. Therefore, this line here sets previousNode to reference the last DOM node of the previous item in the repeater.
previousNode is then used as the first node, in a loop that checks how the DOM changed when items have been moved around or removed from the repeater collection - again, only in case we are not working with the first block in the array.
This is easy - it initializes the block - assigning the $scope and startNode and endNode for later reference, and saves everything in nextBlockMap. The comment created right after the cloned element, is there to guarantee we always have an endNode.

Delete records using integer list

I want to Loop through the array of integers and want to remove the items in the TLToProcess list which i have stored in the array of integers
here is the code
I want to remove only the selected in the list integer
iSize.add(TLToProcess.size());
if(TLToProcess[i].Scan_In1__c==null)
{
if(TLToProcess[i].typew__c=='Pending')
{
TLForMissingHHhh.add(TLToProcess[i]);
}
}
else if ( c[i].Scan_In1__c!=null)
{
if (TLToProcess[i].typew__c=='Pending' )
{
TLToProcess[i].typew__c='Processed';
}
}
}
Now i want to remove record 1 by 1 from TLToProcess using
remove() can any body tell me how to do it.
Thanks
Anu
Not sure I understand your problem, but if what you're trying to avoid is modifying your List of integers inside a loop and getting this error: {"Collection was modified; enumeration operation may not execute."} you can create a copy of your List(.ToList()) and use it to iterate, and this way you can call Remove() safely.
List<Int32> arr = new List<Int32>();
for (int i = 0; i < 10; i++)
{
arr.Add(i);
}
foreach(var o in arr.ToList())
{
arr.Remove(o);
}
Is that the intent?

How can I read a random line from a notecard in LSL?

I have a notecard with a different word on each line, and I'd like to be able to select from the lines randomly. How can I do that?
First, as you mention, you need a notecard. For this example, I'm using one named "colors" with the following contents:
red
blue
green
yellow
orange
purple
With that notecard present, the following script will read and chat a random line from the card each time the prim is touched.
//this script will grab and chat a random line from the "colors" notecard each time the prim is touched.
string card = "colors";
key linecountid;
key lineid;
integer linemax;
integer random_integer( integer min, integer max )
{
return min + (integer)( llFrand( max - min + 1 ) );
}
default
{
state_entry()
{
//get the number of notecard lines
linecountid = llGetNumberOfNotecardLines(card);
}
touch_start(integer total_number)
{
lineid = llGetNotecardLine(card, random_integer(0, linemax));
}
dataserver(key id, string data)
{
if (id == linecountid)
{
linemax = (integer)data - 1;
}
else if (id == lineid)
{
llSay(0, data);
}
}
}
It's not clear why you do such unnecessary math with adding one and then substracting it again later in the answer you give yourself above.
If you want to make sure you have a more random number as there are known issues with the randomness of llFrand you could do (without checking whether the number is even or odd):
integer max;
integer random = llFrand((integer)(max/2)) + llFrand((integer)(max/2));
The second issue with your code above is that you are not checking against CHANGED_INVENTORY and I'm not quite sure why you'd not do that. Following up on this second issue, why do you ask a question to get a random notecard line number and give an answer that provides a random within a range? And what will you do if the notecard changes? Change the code and the notecard? This seems to be redundant to me.
NOTECARD named colors or whatever you set in the script:
blue
red
green
yellow
black
SCRIPT within the same prim:
// this script reads from a notecard which is named whatever you set in init
// in this example from a notecard named "colors"
string ncName;
key ncNumOfLinesReqId;
key ncReqId;
integer numOfLines;
init()
{
// Put the name of your notecard as in the prim's inventory here.
ncName = "colors";
}
default
{
changed(integer change)
{
// reset script to make sure you have the current number of lines
// CHANGED_OWNER has the integer value 0x80 (128)
// CHANGED_INVENTORY has the integer value 0x01 (1)
if (change & (CHANGED_OWNER | CHANGED_INVENTORY))
{
llResetScript();
}
}
state_entry()
{
init();
// get the number of notecard lines
ncNumOfLinesReqId = llGetNumberOfNotecardLines(ncName);
}
touch_start(integer num_detected)
{
// if the number of lines is 0
if (!numOfLines)
{
// PUBLIC_CHANNEL has the integer value 0
llSay(PUBLIC_CHANNEL, "~!~ Unconfigured, check notecard ~!~");
}
else // if number of lines not 0
{
ncReqId = llGetNotecardLine(ncName, (integer)llFrand(numOfLines));
}
}
dataserver(key reqId, string data)
{
if (reqId == ncNumOfLinesReqId)
{
// make sure you typecast!
numOfLines = (integer)data;
}
else if (reqId == ncReqId)
{
// PUBLIC_CHANNEL has the integer value 0
llSay(PUBLIC_CHANNEL, data);
}
}
}
Further information:
The notecard you are reading from does not necessarily have to be in the same prim. If you know the UUID of the notecard, you can read from it as long as it's transferable (and not deleted). Be warned that changing the contents of the notecard and saving, stores the new content under a different UUID. But if you're that skilled, you might as well store the text on a web service and get the text snippet count and text snippets from there.
More on the official Second Life wiki.

Resources