Finding Shortest Distance on Graph -- Logic Issue - c++

In my C++ course we have been working on graphs for a while, and there's a certain question that I've been stuck on for quite some time. The teacher gave us a program that created a graph of integers and then was able to find the shortest path between two integers in the graph. Our job was to adapt this to work for strings (specifically, find the shortest path only jumping to words that have 1 different letter than the previous word e.g bears -> beard).
Here is a sample of what I would expect my program to do:
Given the list [board, beard, bears, brand, boars, bland, blank]
it would create an edge matrix that resembled this:
board | beard boars
beard | board bears
bears | beard boars
brand | bland
boars | board bears
bland | brand blank
blank | bland
And then if asked to find the distance between board & bears it would output:
board->beard->bears
The way I adapted my program is that it creates a graph of a struct named 'node' which contains a number and a word. I use the number to compare the order within one vector to other variables, and the word to create the path. My adapted program successfully creates the graph from data in a text file and connects all words that have a 1 letter difference, however, when I run my function to find the shortest distance it bypasses my edges and simply print out that the start word and end word are a distance of 1 apart.
I will post my full, compile-able program below and explain what I know about the problem.
Here is a link to two pastebin links (I do not have a high enough reputation yet to post more than two links so I must combine them) The first is my full program, I have adapted it to use a set of words that I know are a word distance of 1 apart rather than a text file.
http://pastebin.com/W7HRZG2v
This second link is a download of the code my teacher gave (in case you wish to see a working version of the program)
I've narrowed the problem down to how I'm filling the vector "parents". Somehow it isn't generating properly and is creating an issue when the program tries to retrieve a path from it.
Here is a link to a photo (reputation not high enough to post images yet) comparing what the parents vector looks like in my teacher's "healthy" program (find distance between 2 & 5) to the parents vector in my program:
http://puu.sh/95zQI/26e9b83b9a.png
Notice how in my teacher's, 2 and 4, both integers used in the path, are present in the parents vector and called on to create it.
Notice how in mine the only word present in the parents vector is the beginning word, and hence it is the only word available to call on. However when comparing the way my teacher filled parents with the way I do, there are no differences I can see, aside from the fact that my parents is a string so I am entering a word instead of a number:
(my adapted version is on the left, teacher's is on the right)
if (distanceNodes[edgeNum] > distanceNodes[currNum] + 1) | if (distanceNodes[edge] > distanceNodes[curr] + 1)
{ | {
distanceNodes[edgeNum] = distanceNodes[currNum] + 1; | distanceNodes[edge] = distanceNodes[curr] + 1;
parents[edgeNum] = curr->word; | parents[edge] = curr;
} | }
If someone more proficient in graph application could look at this and assist me I would be extremely grateful. I've been stuck on this problem for over a week and the only tip my teacher will give me is that I should compare my program to his line by line; I did that and I still can't find the problem, I'm about ready to give up.
If you can help me, thank you very much,
Tristan

Here:
node * one = createNewNode(1, "board");
...
node * three = createNewNode(3, "bears");
...
insertEdge(&g, one, three);
The program correctly finds the edge you put there.
More generally, you must learn to step through your code and see what's happening.
And don't use global variables if you can help it.
EDIT:
I had some free time, so here's another problem:
int currNum = start->num;
while (! inTree[currNum])
{
...
parents[edgeNum] = curr->word;
...
}
You iterate by number, but you look things up by a pointer which you never update.
I'm sure there are other problems. The bottom line is that you're not checking things. For some reason, testing, which real coders do all the time, is never taught in programming courses.

Related

OpenOffice Calc SUM of TRUNC number cells, with rows that include text cells

RE: Apache OpenOffice 4.1.7, AOO417m1(Build:9800) - Rev. 46059c9192, 2019-09-03 12:04.
I need to sum non-integer entries across a range of cells, but without including the decimal values (complicated by some cells being text). I started with ROUNDDOWN, then TRUNC, then FLOOR. I'm driving myself nuts trying to find a clean code (or even an arbitrarily extensible ugly code) for what would be the following:
=SUMIF(ISTEXT(R7:CL7);0;TRUNC(R7:CL7))
The above doesn't work, of course, since TRUNC() doesn't apply to ranges, but it conveys what I'm trying to do in a nutshell -- some of the cells contain text, which SUM() ignores (luckily), but they flummox TRUNC, so I needed to handle the text problem.
I started with ISNUMBER, just to get the ball rolling; ISTEXT has fewer characters, but it's not worth fixing that right now.
FLOOR was equally disappointing for ranges:
=SUM(FLOOR(R7:T7;1))
I tried variations of =SUM(IF(... and searches for ROUNDDOWN range (and variations on that) and such pseudocode as "IFTEXT" and "SUMTRUNC" (and variations on that). I found info on ROUNDDOWN(SUM(... and so forth, but not "SUM(ROUNDDOWN(..." or any equivalent.
In my delirium, I got silly and even tried:
=SUMIF(ISTEXT(S7:U7);0;AND(TRUNC(S7);TRUNC(T7);TRUNC(U7)))
To be clear: {2.9→2 + 2.9→2 + 2.9→2 = 6} ≠ {2.9+2.9+2.9 = 8.7→8}. I'm looking for a 6, not an 8 (I'd joke about sixes and sevens, but I'm way past pumpkin o'clock and 2.428571 takes up too much space).
My current test-kludge is:
=SUM(IF(ISNUMBER(R7);ROUNDDOWN(R7);0);IF(ISNUMBER(S7);ROUNDDOWN(S7);0);IF(ISNUMBER(T7);ROUNDDOWN(T7);0); ... ;IF(ISNUMBER(AX7);ROUNDDOWN(AX7);0))
It ends at AX7 only because of the char count. I hope to SUM the whole row in a single sweep, but that ain't gonna cut it. I could do it in large chunks in multiple cells, and then add those cells up, but oy gevalt.
Since it's already ugly anyway, I could use the following to save a few characters, but this would only mean being able to extend the range maybe 6 further cells (not much point in that):
=IF(ISTEXT(R7);0;TRUNC(R7))+IF(ISTEXT(S7);0;TRUNC(S7))+IF(ISTEXT(S7);0;TRUNC(S7))
I'm seriously considering simply going down a bunch of rows (to below my data cells) and entering the following, then copying the cell and pasting it to a complementary range, and telling the SUM cells to just sum up their respectively shadowed rows (instead of the data rows that they sit in):
=IF(ISTEXT(R7);0;TRUNC(R7))
Sorry for the rambling; I need sleep. This started as a need, then multiple failed attempts became a grudge match of principle and obstinacy, and now I'm just plugging away at it out of blind habit developed over the past 2-3 days (hopefully I won't forget what the purpose was).
In summary...: ++?????++ Out of Cheese Error +++DIVIDE BY CUCUMBER.
I'm comfortable enough with macros, though it's been ~7 years (and that was in Excel). Thanks in advance, even if the answer is that I'm stuck with one of these! 🙂
EDIT: I don't see a way to attach a .csv here (though I could open the .csv with Notepad, and copy-and-paste the contents if that would help anyone), so here's a set of pics:

Shortest path to cover all edges, in non-weighted, directed graph

Well, I'm facing a problem with a small work I have in hands right now...
The main goal is, having a given graph (without weights, and directed), I have to discover the group of paths(if possible, only one path, but they can be more) with minimum total length, that cover all edges.
Other "constraint" is that the graph, is a DFA, so the paths should start in an initial state, and end in an acceptance state (they're marked).
Initially I found that this was similar to the Chinese Postman Problem, and in fact, it is. But in my case, the graph is directed (I believe this changes thing a bit), and there isn't any problem in processing an edge more than once, since the resultant path remains the shortest.
I've read some things about Euler paths, and T-Joins, and this is probably the solution to my problem. If I understood it right, what I should do is to find an Euler path in my graph and, if there isn't one, make it exist, duplicating the T-Joins, or something like that... I had lots of trouble understanding this, I don't even know if this is the answer to my problem... (shortest and most understandable text I found here: http://en.wikipedia.org/wiki/Route_inspection_problem)
Just to leave a short example, given this graph (1 is initial and 5 is acceptance):
1 -> 2;
2 -> 3;
2 -> 4;
4 -> 5;
The answer to my problem should be: 1 -> 2 -> 4 -> 5 and 1 -> 2 -> 3.
(In this case I would also have to handle the fact that 3 isn't an acceptance state, but that edge had to be covered. But I can easily get through that by flagging all the states with no edges to other nodes as acceptance states).
Hope I explained everything well enough.
Thanks in advance!

How do you search a vector with hashed names for a match?

So my professor assigned this project for us. It's pretty simple because it's our first hashing program. The program is to take 15 names as input and hash them and store them in something. I did it in a vector. Now once they are hashed the user enters another name and it will should hash that name and try to match it to one in the vector. Maybe it is me or maybe it is how he wrote the question but I'm a little confused. Our program is suppose to have collision protection. Which means we run an algorithm on the name inputted and it will spit out a number and that number is where we store the name in the vector. If there is another name already in that spot we are suppose to store it in the next available spot.
So lets say I enter the name jordan and jon. The algorithm will tell me to store these in the same spot (lets say spot 8) but collision protection will recognize that jordan is already taking up the spot (8) and it will move jon to the next available spot(lets say spot 9). Now when the user is entering names to see if it is in the vector already and he enters jon, the algorithm will see it should be in spot 8. Do you think I should just check to see if that spot is empty, if not say a match has been found in spot 8, even though the name in spot 8 is jordan and the name entered is jon. Or should I start at spot 8 and see if the strings match, and if they don't check the next spot and so on until i return to the original spot or find the match?
I wrote the program and it works fine, I just ran into this one dilemma and can't finish the program. Thanks
Your approach is Open Addressing collision handling.
According to this approach, when you are searching for an element, you should 'keep going' until you find the first empty spot - only then you are guaranteed the requested element is not stored.
Three things can happen when you look up a value.
You find the value you're looking for.
You find an empty spot in your hash table.
You find some other value in the assigned spot you're looking at.
In cases 1 and 2, it's clear what you should do. You know for sure that the value you're looking for is either in your table or it's not. In the third case, you should follow the same procedure that you do when adding items to the table. That is, keep looking in the next spot until you reach either condition 1 or 2 above.

The New Villa Acm solution strategy

I am trying to solve this ACM problem The New Villa
and i am not figuring out how to approach this problem definitely its graph problem but doors and the room that have switches to other rooms are very confusing to make a generic solution. Can some body help me in defining the strategy for this problem.
Also i want some discussion forum for ACM problems if you know any one then please share.
Thanks
A.S
It seems like a pathfinding problem on states.
You can represent each vertex with a binary vector of size n + an indentifier - where which room you are in at the moment [n is the number of rooms].
G=(V,E) where V = {all binary vectors of size n and a recored for which room you are in} and E = {(u,v) | you can switch from binary vector u to v by clicking a button in the room you are in, or move to adjacent lights on room }
Now you only need to run a search algorithm on the possible paths.
Possible search algorithms:
BFS - simplest to program, though slowest run time
bi - directional BFS - since there is only one target node,
a bi-directional search will work here, it is expected to be much
faster then BFS
A* - find an admissible heurstic function and run
informed A* on the problem. It is harder to program it then the rest - but if you find a good heurisitc, it will most likely perform much better.
(*) All of the above are both complete [will find a solution if one exists] and optimal [will find the shortest solution, if one exists]
(*) This solution runs in exponential time on the number of rooms, but it should end up for d <= 10 as indicated in the problem in reasonable time.

C++ pathfinding with a-star, optimization

Im wondering if I can optimize my pathfinding code a bit, lets look at this map:
+ - wall, . - free, S - start, F - finish
.S.............
...............
..........+++..
..........+F+..
..........+++..
...............
The human will look at it and say its impossible, becouse finish is surrounded... But A-star MUST check all fields to ascertain, that there isnt possible road. Well, its not a problem with small maps. But when I have 256x265 map, it takes a lot of time to check all points. I think that i can stop searching while there are closed nodes arround the finish, i mean:
+ - wall, . - free, S - start, F - finish, X - closed node
.S.............
.........XXXXX.
.........X+++X.
.........X+F+X.
.........X+++X.
.........XXXXX.
And I want to finish in this situation (There is no entrance to "room" with finish). I thought to check h, and while none of open nodes is getting closer, then to finish... But im not sure if its ok, maybe there is any better way?
Thanx for any replies.
First of all this problem is better solved with breadth-first search, but I will assume you have a good reason to use a-star instead. However I still recommend you first check the connectivity between S and F with some kind of search(Breadth-first or depth-first search). This will solve our issue.
Assuming the map doesn't change, you can preprocess it by dividing it to connected components. It can be done with a fast disjoint set data structure. Then before launching A* you check in constant time that the source and destination belong to the same component. If not—no path exists, otherwie you run A* to find the path.
The downside is that you will need additional n-bits per cell where n = ceil(log C) for C being the number of connected components. If you have enough memory and can afford it then it's OK.
Edit: in case you fix n being small (e.g. one byte) and have more than that number of components (e.g. more than 256 for 8-bit n) then you can assign the same number to multiple components. To achieve best results make sure each component-id has nearly the same number of cells assigned to it.