Detecting a loop in logic circuit simulator - c++

I'm trying to write a logic gates circuit simulator and everything is working so far except for one thing. My structure looks like this:
struct node
{
int number;
bool has_value;
bool is_input;
bool value;
Gate operation;
node* input1;
node* input2;
};
The program calculates output value by using recursion, so any kind of loop inside the structure messes everything up. My question is: How do I detect something like this (see picture) , cause i can't come up with anything that works.
circuit

The obvious way to deal with the problem is to include a bool in each node signifying whether that node has been visited yet in the current simulation step.
You'd want to set this to false initially, such as in the constructor.
Then a simulation step would consist of traversing the graph once to clear the flags. You'd do a recursion from a given node if and only if the flag was currently set.
Then you'd run the simulation step. This would proceed roughly the same way, but with the logic reversed. As you visit each node, you check its visited flag. If it's set, you can return immediately (and you've just detected a cycle in the graph). Otherwise, you set the flag, process the inputs for that node (etc.--your usual simulation "stuff"), then do recursive calls to do simulation on its child nodes. If any of them loops back to this one, that call will return immediately (because you've already set the flag), ending that "leg" of recursive calls.

Related

Is there a way to pass which "level" of structure is desired to a formula in (Arduino) C++?

I am not hugely experienced in C++ coding, but I learn pretty well as I go. But, I have not been able to properly query how to do this, may be using wrong terms or insufficiently expressing my desire. Here's the situation.
I have a lot of variables (3x12) that I have set up under a structure:
struct Tracking
{
String Title;
BoolArray n24hr;
bool State;
unsigned char Days, Weeks;
uint16_t Minutes, TotalMinutes, Daily, Weekly, Monthly, n7d[7], n4w[4];
} Components[3];
I also have code that performs basically the same thing 3 times but on different "levels", e.g. daily, weekly, monthly. It keeps tracks of status over those time periods, filling arrays, finding totals, and duty cycles, etc. It fills the minutes into days, and when that reaches a week, it puts the totals into a week format, and repeats until it reaches monthly levels. So basically, I have it doing something like:
in my main loop:
//calls status formula
StatusFormula();
in a separate file:
//status formula defined
void StatusFormula()
{
// for each element of Components:
//determine current status
//for daily
//add it to the correct spot in the array
//perform calculations on it
//when it reaches a week:
//add it to the correct spot in the next array
//perform calculations on it
//when it reaches a month:
//add it to the correct spot in the next array
//perform calculations on it
}
These calculations are all basically the same, the only differences are the structure member names & the constants for the calculations (i.e., MinsADay, DaysAWk, etc.).
I can get it to work this way, it just means a lot more lines and if I want to change something, I have to repeat it 3 times. What I want is something like this:
in my main loop:
//calls status formula
StatusFormula("Daily"); //sends the status formula information to decide which level (daily, weekly, monthly), it supposed to work on
if (Components[i].Minutes == MinsADay)
{
StatusFormula("Weekly"); //sends the status formula information to decide which level (daily, weekly, monthly), it supposed to work on
if (Components[i].Daily == DaysAWk)
{
StatusFormula("Monthly");
}
}
in a separate file:
//status formula defined
void StatusFormula()
{
//determine which level & variables to use (I would probably use case for this), then
//add it to the correct spot in the correct array
//perform calculations on it
}
I tried passing the level using a string, but it didn't work:
in my main loop:
StatusFormula(i, "Daily"); //sending data to formula, where i is value 0 to 2 for the Components array & defined earlier in the for loop.
in a separate file:
//formula defined as:
void StatusFormula(uint8_t counter, string level)
{Components[counter].level -= //etc... performing calculations as desired.
//so I thought this should evaluate to "Components[i].Daily -=" (& i would be a value 0 to 2) & treat it like the structure, but it doesn't work that way apparently.
I tried passing the structure & variable itself, but that didn't work either:
in my main loop:
StatusFormula(i, Components[i].Daily); //sending data to formula
in a separate file:
//formula defined as:
void StatusFormula(uint8_t counter, Tracking& level)
{level -= //etc... //(level should be Components[i].Daily -=" (& i would be a value 0 to 2)) this didn't work either.
I couldn't find any google searches to help me, and I trialed-and-errored a bunch of ways, but I couldn't figure out how to do that in C++, let alone on the Arduino platform. In Excel VBA, I would just have the variable passed as a string to the formula, which would substitute the word and then treat it like the variable that it is, but I couldn't make that happen in C++. Also to note, I am going to try and define this a separate file/tab so that my massive code file is easier to read/edit, in case that makes a difference. I would paste my code directly, but it is long and super confusing.
I guess what I am asking is how would I pass the structure and/or structure member to the formula in a way that would say the equivalent of:
case 1: //"Daily"
//use Components[i].Daily & Components[i].Minutes & MinsaDay
break;
case 2: //"Weekly"
//use Components[i].Weekly & Components[i].Days & DaysaWk
break;
//etc.
I feel like there should be a way & that I am just missing a small, vital piece. Several people in the comments suggested enums, and after researching, it might possibly be what I want, but I am having trouble visualizing it at the moment and need to do more research and examples. Any suggestions or examples on how to send the appropriate structure & members to the formula to be modified in it?

binary tree doesn't rebuild from file

I'm new on data structures and we were assigned to make a guessing game using binary tree implementation. I have accomplished the program flow without file implementation. I have saved the binary tree preorderly on an external file now I have problem in rebuilding tree from file
in my file I have:
Is it Angel Locsin?:#Neneng B?Is it Sam Pinto? ##White Beauty?Is it
Marian Rivera? ##HotandSexy?Is it Cristine Reyes? ###
The "#" is for a NULL node.
I have also my code. I follow the algorithm of what my professor gave me. I searched on the internet and gave me same algorithm as of what my prof said. My problem is on every third non-null data the program crashes. I think the main reason of crashing is a node that was not set to null after the third non-null data is inserted. If so, how could I set it to NULL so that my program will not crash.I assigned the data from file into array of strings and set a "\0" at the last index of array.
void read(node *temp)
{
while(array[j]=="#")
j++;
if(array[j]=="\0")
return;
node *nNode;
nNode = new node;
nNode->yes=NULL;
nNode->no=NULL;
nNode->data=array[j];
j++;
temp=nNode;
read(temp->yes);
read(temp->no);
}
Your problem is in the definition of your read function. I guess the idea is that "temp" is an output parameter of type "node*". But this is not what you have written.
You need to have a pointer or a reference to the "node*" parameter like e.g. so:
void read(node** temp)
Then adjust the rest of the code such that is compiles by proper (de)referencing. This should solve your crash.

Break and rerun while loop c++ Windows

I'm a rookie programmer, so please be polite.
Well i'm trying to write a simple Terminal Backgammon game, just for fun, but i have a problem.
The entire game runs in a while loop which keeps re running as long as nobody moved all their bricks to the end of the board.
A simple integer controls whatever it is black or white who plays.
I wrote a function to check for any possible moves, cause i want to program to skip the turn in case absolutely no moves can be made.
Well, i want this function to run and in case it returns false(No possible moves) then i want the rest of the code to skip and change the turn to the next player. For example if the dice combination gives no possible moves for black, then i want the program to skip black and go to white.
So i sort of want to break the rest of the while loop, but keep it running.
It's a little complicated for me to explain the issue, but i hope you guys understand.
Thanks alot
- Martin
It sounds like you want to use continue:
while (someCondition)
{
doSomething();
if (someOtherCondition)
continue;
doSomethingElse();
}
In this example, if someOtherCondition is true, the continue statement will cause the program to jump back to the top of the loop rather than continuing to execute the following statements. If someOtherCondition is false, doSomethingElse() will get run as normal.
I think this is roughly what you want to know.
Hope it helps.
while( keepRunning )
{
bool noPossibleMoves = checkForPossibleMoves();
setup for each loop iteration
Do things here that are always necessary.
if( noPossibleMoves )
{
continue; // This will go to the top of the while loop
}
wait for user input etc...
...
...
}

How can I find the actual path found by BFS?

The problem I'm trying to solve concerns a tree of MRT system.
Each node can be connected to 4 points at most, which simplify thing by a lot. Here's my thought.
struct stop {
int path, id;
stop* a;
stop* b;
stop* c;
stop* d;
};
I can write code to save all the information I need for BFS to search for all the points, but my main concern is that, even though BFS finds the point properly, how can I know its path?
BFS will search each level, and when one of it reaches my destination, it will jump out of the run loop, and then, I will get a visited queue and an unvisited queue, how am i supposed to tell the user what stops he needs to visit when the visited queue is filled with every nodes BFS has searched?
To do so, you need to store a map:V->V (from vertices to vertices), which will map from each node v, the vertex u that "discovered" v.
You will populate this map during the iterations of BFS.
Later - you can reconstruct the path by simply going from the target node (in the map) up until you get back to the source, which will be your path (reversed, of course).
Note that this map can be implemented as an array if you enumerate the vertices.

Recursively created linked lists with a class, C++

I'm using C++ to recursively make a hexagonal grid (using a multiply linked list style). I've got it set up to create neighboring tiles easily, but because I'm doing it recursively, I can only really create all 6 neighbors for a given tile. Obviously, this is causing duplicate tiles to be created and I'm trying to get rid of them in some way. Because I'm using a class, checking for null pointers doesn't seem to work. It's either failing to convert from my Tile class to and int, or somehow converting it but not doing it properly. I'm explicitly setting all pointers to NULL upon creation, and when I check to see if it still is, it says it's not even though I never touched it since initialization. Is there a specific way I'm supposed to do this? I can't even traverse the grid without NULLs of some kind
Here's some of my relevant code. Yes, I know it's embarassing.
Tile class header:
class Tile
{
public:
Tile(void);
Tile(char *Filename);
~Tile(void);
void show(void);
bool LoadGLTextures();
void makeDisplayList();
void BindTexture();
void setFilename(char *newName);
char Filename[100];
GLuint texture[2];
GLuint displayList;
Tile *neighbor[6];
float xPos, yPos,zPos;
};`
Tile Initialization:
Tile::Tile(void)
{
xPos=0.0f;
yPos=0.0f;
zPos=0.0f;
glEnable(GL_DEPTH_TEST);
strcpy(Filename, strcpy(Filename, "Data/BlueTile.bmp"));
if(!BuildTexture(Filename, texture[0]))
MessageBox(NULL,"Texture failed to load!","Crap!",MB_OK|MB_ICONASTERISK);
for(int x=0;x<6;x++)
{
neighbor[x]=NULL;
}
}
Creation of neighboring tiles:
void MakeNeighbors(Tile *InputTile, int stacks)
{
for(int x=0;x<6;x++)
{
InputTile->neighbor[x]=new Tile();
InputTile->neighbor[x]->xPos=0.0f;
InputTile->neighbor[x]->yPos=0.0f;
InputTile->zPos=float(stacks);
}
if(stacks)
{
for(int x=0;x<6;x++)
MakeNeighbors(InputTile->neighbor[x],stacks-1);
}
}
And finally, traversing the grid:
void TraverseGrid(Tile *inputTile)
{
Tile *temp;
for(int x=0;x<6;x++)
if(inputTile->neighbor[x])
{
temp=inputTile->neighbor[x];
temp->xPos=0.0f;
TraverseGrid(temp);
//MessageBox(NULL,"Not Null!","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
}
The key line is "if(inputTile->neighbor[x])" and whether I make it "if(inputTile->neighbor[x]==NULL)" or whatever I do, it just isn't handling it properly. Oh and I'm also aware that I haven't set up the list fully. It's only one direction now.
If you want to create a hexagonal grid you should remember that it easily can be simulated using a normal grid!
__ __ __
\__/2 \__/4 \__/6 \
/1 \__/3 \__/5 \__/
\__/8 \__/10\__/12\
/7 \__/9 \__/11\__/
\__/ \__/ \__/ \
This will make life MUCH simpler :)
Hence the easiest way would be
set up a temporary square grid m*n
fill it with tiles
traverse the grid and connect properly
Now the connections, based on the diagram above:
A) Connect to previous and next [x-1,y], [x+1,y]
B) Connect to row above and row below [x,y-1], [x,y+1]
C) Connect to row above previous and next [x-1,y-1], [x+1,y-1]
... and you have all desired connections (just remember to check bounds to decide if the tile isn't on the edge) -- if you hold the tiles in another way, you can even remove the grid :).
I'm only guessing at what MakeNeighbors() does, but instead of blindly doing InputTile->neighbor[x]=new Tile();, you could check to see if neighbor[x] is non-NULL before creating a new one and initializing it. E.g. if its parent creates it and sets all of its neighbor information, then it shouldn't go and create its parent.
When the parent creates the children, it should also define the children's other neighbors appropriately, as far as it knows them. So, it should make sure that child[i] also is neighbors with child[i-1] and child[i+1].
Creation. Recursion is a neat and elegant way to solve some problems, but it isn't perfect for every problem. I suspect that a purely recursive solution to creating the nodes would be much more complicated (i.e. less elegant) than Kornel Kisielewicz's straightforward iterative solution. That's because the Tile constructor needs to know the layout of all tiles in its immediate vicinity, in order to avoid recreating nodes that are already there.
Traversal. The main problem in your node-traversal code is similar in that you will wind up with an infinite loop and blow the stack because every node will eventually "traverse" back to its parent, beginning the cycle again. I presume you're trying to visit every tile exactly once, right? In that case TraverseGrid() needs to have a parameter telling it which direction we are entering the node from, so that we avoid traversing back that way.
But that's not enough -- you also need more discipline in deciding which directions to go. Simply spreading out in all directions except the direction we entered from will still wind up in an infinite loop and stack overflow, since any three adjacent tiles will cycle endlessly. In order to do this recursively you need to really think about which strategies will wind up visiting each node once and only once.
One possibility would be changing the signature of TraverseGrid() to TraverseGrid(Tile *inputTile, int fromDir, bool leftmost) and then using the following rules:
If we entered from above-left, traverse only to above-right, passing leftmost = false.
If we entered from below-left or above-right, traverse only to below-right, passing leftmost = false.
If leftmost, and there is a node to our lower left, then also traverse to that node, passing leftmost = true.
Of course fromDir and leftmost could be combined into a single parameter, but this gives the general idea.
Another alternative would be keeping a visited flag in each tile which is checked before traversing to that tile. Then your traversal will be a flood fill. But again, a simple iterative traversal is likely to be much simpler and easier to understand, and has the additional benefit of using constant stack space.
In the class declaration there is a second constructor Tile(char *Filename);. Maybe this constructor is used to create the main node, but doesn't initialize neighbor properly? (Its implementation isn't shown.)
And on an unrelated node, you have a duplicate strcpy() in the constructor that doesn't serves any purpose and might only lead to problems:
strcpy(Filename, strcpy(Filename, "Data/BlueTile.bmp"));
I actually did the same thing but my pattern was more like this:
00 01 02 03 04
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
This makes it pretty easy to figure out what can be reached, but forces a strange offset pattern. I just got rid of (in the above example) 00,01,10 and 20 to make it more of a hex pattern like this:
02 03 04 05 06
11 12 13 14 15
21 22 23 24 25
30 31 32 33 34
So if you look at the pattern above, reachable is always the same:
from 23 (call 2 "a" and 3 "b") you can get to:
NW(a-1, b), NE(a-1, b+1), W(a, b-1), E(a, b+1), SW(a+1, b-1), SE(a+1,b)
This pattern should hold correct for the entire grid.
EDIT:
I was going to do this in a comment but it got too long. I can see two approaches.
1) Allocate the array of nodes (null, don't allocate them). Whenever you need to allocate a node, just do so, but use the array address whenever you need to reference a node, if it's null populate it, if it has a value use that value. Huge empty arrays shouldn't take up that much memory, but if they do...
2) Create a HashSet to hold your nodes where the Hash value of the node class is calculated like this: (a << 32 || b). In this way you can instantly look up to see if a previous node existed or not. Remember to overload "equals" as well (it should return true only if the compared object is the same type and a and b are equal).
In a mostly populated system where bounds are known, 1 will save memory, but if your system is sparse (as you claim) then #2 could save a LOT of memory with no cost to efficiency.