I am currently working on an AI for playing the game Dots (link). The objective is to remove as many dots as possible by connecting similarly colored dots with a line. I've gone through the board and grouped each set of neighboring dots with the same color. The groups all currently share the same highlight color (black). So, for example, the four red dots in the top left form a single group, as do the three yellow dots on the top right.
I need to calculate every possible path through one of these groups. Can anyone think of a good algorithm? How could I avoid creating duplicate paths?
I've heard that a slightly modified DFS would be good in this situation. However, the paths are allowed to cross at nodes, but cannot reuse edges. How can I modify DFS accordingly?
Here's some pseudo code to get you started. It's how I would probably do it. Using edges instead of nodes solves the situation with crossing paths neatly, but retrieving edges is more difficult than nodes. You need to map the edge indexes to the node indexes.
You will get every path two times, since a path can be traversed from two directions.
If the dot groups grow large, consider pruning the least interesting paths. The memory requirement grows exponentially as 4^n where n is the number of dots in the group. I can't think of a good way to add incomplete paths without allowing for duplicates, but perhaps you're not interested in paths ending early?
private LinkedList<Edge> recurse(LinkedList<Edge> path) {
Edge last = path.getLast();
Edge right = <get Edge to the right of last>;
Edge bottom = <get Edge below last>;
Edge left = <get Edge to the left of last>;
Edge top = <get Edge above last>;
if( right && !path.contains(right) ) {
LinkedList<Edge> ps = path.clone(); // NOTE: check if the built-in clone() function does a shallow copy
ps.addLast( right );
paths.add( recurse(ps) );
}
if( bottom && !path.contains(bottom) ) {
...
}
if( left && !path.contains(left) ) {
...
}
if( top && !path.contains(top) ) {
...
}
return path;
}
Related
I'm still trying to improve on my coding skills, and this question has got me spinning in my tracks a little bit, so any help is greatly appreciated. I know how to create the random array very easily, no problem with that. However, the logic of finding the chain is proving very difficult for me. I believe the proper approach is some sort of depth first searching algorithm, but I'm not entirely sure of how to implement that in this scenario, or whether that is even correct.
My basic question is, should I be using depth first search, and if so, should I be doing it recursively? Any tips or hints on implementation are also welcome!
Make a program that creates a 3x3 grid of random
positive numbers where 0 <= n <= 9. The program should
find all possible combinations of numbers that add up to the area of
the grid, or 9, using these rules (similar to Boggle):
a. The numbers must be "chained" in sequentially adjacent cells, where
"adjacent" cells are those horizontally, vertically, and diagonally
neighboring
b. The chain does not have to be in a line. For example, it could go
horizontally once, then vertically once, and finally diagonally once
c. At least the “grid width - 1” cells must be used in the chain (a
3x3 grid means that at least two cells must be used)
d. A chain cannot repeat a grid cell that it has already used
e. Chains that use the exact same cells as a previous chain are
considered repeats and should not be counted
I know that for each element, when you are searching through each adjacent element, you must check and keep track of whether it's been visited before, so you don't repeat numbers.
public class GridSolver {
int[][] workingGrid;
public GridSolver(int[][] workingGrid){
this.workingGrid = workingGrid;
}
public String solve(){
int length = this.workingGrid.length;
boolean[][] visited = new boolean[length][length];
for(int rows=0; rows<length; rows++){
for(int columns=0; columns<length; columns++){
if(visited[rows][columns] == false){
dfs(workingGrid[rows][columns]);
}
}
}
return null;
}
public HashSet<ArrayList<Integer>> dfs(int element){
HashSet<ArrayList<Integer>> chains = new HashSet<>();
checkLeft();
checkTopLeft();
checkTopMiddle();
checkTopRight();
checkRight();
checkBottomRight();
checkBottomMiddle();
checkBottomLeft();
return null;
}}
This is what I have so far and I realize that it is pretty sloppy and not the best thought out scheme, but that's why I'm here I guess :P.
Also just to explain some of my thinking in the code, the dfs()method has a return type of HashSet because I know that you can't have duplicate chains, and it is a set of a list of the chains. Also the "check" methods are not implemented, I just wrote them down because I know that you will need to process each of these adjacent blocks for each number.
Once again, any help is greatly appreciated, and thank you for humoring me as a beginner here!
I'm having a problem implementing this method in java. I'm specifically implementing the algorithm FINDINTERSECTIONS in Computational Geometry 3rd Edition using an AVL BST tree for the status. The description from the book is shown below:
The problem I'm having is implementing step 5 in HANDLEEVENTPOINT. When the event point is an intersection, the status is no longer totally ordered there, because for intersection lines, they cross at their intersection point and need to be swapped in the status. Since the BST I'm using is an AVLTree, the delete method fails because the rebalancing method requires proper ordering of the elements (i.e. the delete method assumes the tree is properly ordered, and performs rotations with respect to the order in order to maintain log(n) height). Also, the status I'm using stores the data in the nodes instead of the leaves as shown in the figure. If I understand correctly, the book says that either kind of tree can be used.
First off use a leaf version of a balanced binary search tree whether red-black or AVL. I used red-black.
Get Peter Brass's book on advanced data structures because you will have trouble finding anything on these leaf trees in virtually all the standard algorithm / data structure books. I believe they are also called exogenous trees.
http://www-cs.engr.ccny.cuny.edu/~peter/
Also, you can look at "Algorithms and Data Structures: The Basic Toolbox" by Mehlhorn and Sanders which goes into the "sorted sequence" data structure. They create these with the help of only leaf trees when trees are used. These are also some of the folks that developed LEDA.
Also look at the LEDA book online bc it has a chapter on how to implement this algorithm and how to handle ALL the "problem cases." I think this is chapter 9 and is a bit hard to follow maybe because English is not the native tongue of the authors ... PITA!!
http://people.mpi-inf.mpg.de/~mehlhorn/LEDAbook.html
You can doubly link the leaf nodes data items together and you have created a sorted sequence with the tree as a navigation structure to the linked list of items. That is how LEDA and in think CGAL do this.
Duplicate items are handled differently in the event queue than the sweep line status structure. For the event queue, just add to a leaf a linked list of items (see Brass's book). Here each leaf corresponds to an event point and has a list of all segments with a starting-end-point this that same as the event point. So some will have empty lists like intersection-event-points and ending-event-points. At least that is how some implementations do this.
For the sweep status structure. Overlapping parallel segments are differentiated by say segment ids. They do not talk about these in the book you are reading/referencing. However, the LEDA book tells you how to handle these. So even though sweep status trees comparator says two segments have the same end-point and orientation, the comparator breaks the tie by using the segments indexes in the segments database, array or whatever.
Some more important points:
Pool points! This common pool of points are basic and then make up the segments and are used in all the data structures. Using the pool allows one to test for point equality by just testing for identity! This avoids using a comparator which slows things down and can introduce errors.
It is key that you avoid using the tree comparators as much as possible.
When checking if segments belong to the same bundle or are members of the three sets you are having a question about (i.e, start, end or interesect with and event point on the sweep-line), DO NOT USE THE COMPARATOR.
Instead, use that fact that segments belonging to the same bundle can have some "information property" say in the list that either points to the event queue when a segment intersects an event point, or points to the successor item in the list if the segment overlaps the successor, or points to null otherwise. So you will need some cross-linking between the event queue with the sweepline status structure. Your sets and bundles are the very fast and easy to find. Go to the start or end of the linked-list associate with the status tree and go through it item by item with a very simple test.
BOTTOM LINE. Get the sorted sequence / balanced binary tree data structure right and work on that a lot before implementing the rest of Bentley-Ottmann.
This is really the key and that book does not point that out at all but unfortunately that isn't it's intent since this implementation is tricky. Also, note that the book augments the navigation tree with an extra link in the internal nodes of the tree that point to associated leaf nodes. This just makes find a bit faster but may not be apparent if you are not familiar with leaf trees. A key in a leaf tree is often found twice, at the leaf node and elsewhere in an internal node of the tree.
FINALLY
Packages like LEDA/CGAL use exact arithmetic for things to work well. It took LEDA developers 10 years to get things right and that was mostly was due to using exact arithmetic. You maybe OK with a basic cross-product test used for orientation but if you need an exact version then you can find Prof. Jonathan Shewchuk exact arithmetic package on his site.
I guess your book just left all this out as an "exercise for the reader/student." LOL.
UPDATE: In your posted algorithm from that book, the swap for reversing intersecting segment order is done via delete and then with a re-insert. LEDA uses reverse_items() for these swaps. It's a more efficient way of doing sub-sequence reversals of nodes and items without the use of the comparator. Search for _rs_tree.c to see LEDA source or see below.
// reverse a subsequence of items, assuming that all keys are
// in the correct order afterwards
//
void rs_tree::reverse_items( rst_item pl, rst_item pr )
{
int prio ;
register rst_item ppl = p_item(pl), // pred of pl
ppr = s_item(pr), // succ of pr
ql, qr ;
while( (pl!=pr) && (pl!=ppl) ) { // pl and pr didnt't
// met up to now
// swap all of pl and pr except the key
// swap parents
ql = parent(pl) ; qr = parent(pr) ;
if( pl==r_child(ql) )
r_child(ql) = pr ;
else
l_child(ql) = pr ;
if( pr==r_child(qr) )
r_child(qr) = pl ;
else
l_child(qr) = pl ;
parent(pl ) = qr ; parent(pr) = ql ;
// swap left children
ql = l_child(pl) ; qr = l_child(pr) ;
if( ql != qr ) { // at least one exists
l_child(pl) = qr ; parent(qr) = pl ;
l_child(pr) = ql ; parent(ql) = pr ;
}
// swap right children
ql = r_child(pl) ; qr = r_child(pr) ;
if( ql != qr ) { // at least one exists
r_child(pl) = qr ; parent(qr) = pl ;
r_child(pr) = ql ; parent(ql) = pr ;
}
// swap priorities
prio = pl->prio ; pl->prio = pr->prio ;
pr->prio = prio ;
// swap pred-succ-ptrs
s_item(ppl) = pr ; p_item(ppr) = pl ;
ql = pl ; pl = s_item(pl) ; // shift pl and pr
qr = pr ; pr = p_item(pr) ;
s_item(ql) = ppr ; p_item(qr) = ppl ;
ppl = qr ; ppr = ql ; // shift ppl and ppr
}
// correct "inner" pred-succ-ptrs
p_item(ppr) = pl ; s_item(ppl) = pr ;
if( pl==pr ) { // odd-length subseq.
p_item(pl) = ppl ; s_item(pr) = ppr ;
}
}
ADDITIONALLY: Sorted sequence data structures can use AVL trees, ab-trees, red-black trees, splay trees, or skip lists. An ab-tree with a = 2, b = 16 fared best in speed comparison of search-trees used in LEDA**.
** S. Naber. Comparison of search-tree data structures in LEDA. Personal communication.
Dear Friends I am an intermediate java user. I am stuck in a following problem. I want to construct a unordered binary tree [or general tree having at most two nodes] from a multi line (let say 40 lines) text file. The text file is then divided into two halfs; let say 20:20 lines. Then for each half a specific (let say hash) value is calculated and stored in the root node. So each node contains four elements. Two pointers to the two children (left and right) and two hashes of the two halfs of the original file. Next for each half (20 lines) the process is repeated until at each leaf we have a single line of text. Let the node have
public class BinaryTree {
private BinaryTreeNode leftNode, rightNode;
private String leftHash,rightHash;
}
I need help for writing the tree construction and searching functions. Well searching is performed by entering a line. Then hash code is created for this query line and compared against the two hashes saved at each node. If the hash of query line is close to leftHas then leftNode is accessed and if the hash of query line is close to rightHash then rightNode is accessed. The process continues until an exact hash is found.
I just need the tree construction and search teachnique. The hash comparison etc are not a problem
You'll need to start by reading the file into a string.
The first character in the string could be used as the root. Root + 1 would be the left, root + 2 would be the right
Consider left node of the root (Root + 1), you could also consider this as Root + N. Meaning that the right node would be Root + N + 1.
You can now recursively solve this problem by establishing which Node you are currently on, and setting the left and right now respectively.
So lets think about it,
You have the root node, left node, and right node established. At this point you have used 3 letters/numbers (it really doesnt matter if it is unordered). The next step would be to move down one level and start filling the left, you have the root, you need left and right nodes. Then move to the right node, do the left and right node of this and so on and so forth.
Think about that for a little bit and see where you get.
Cheers,
Mike
EDIT:
To search,
Searching a binary tree is also a recursive theme. (I thought you previously said the tree was unordered, which may change how the tree is laid out if it is suppose to be order).
If it is unordered, you can simply recurse the tree in a manner such that
A.) Check root node
B.) Check left node
C.) Continue checking left nodes until either there is a match, or no more left nodes to check
D.) Recurse back 1, check right node
E.) Check left nodes,
F.) Recuse back, check right node
This theme will continue until eventually you have checked ALL left nodes first, and then the right nodes. The KEY to this, is at any point you have a root node, go left first, then right. (I forget what traversal type this is, but there are others if you wish to implement them over this, i personally think this is the easiest to remember).
You will then repeat for right child of Root node.
If at any time you get a match, exit.
Remember this is recursive, so make sure you think your way through this step by step. It is recursive by definition, in that you will always do steps x,y,z for each part of the tree.
To beat a dead horse, lets look at just 3 nodes to start.
(simplified)
First the root,
if(root == (what your looking for))
{
return root
}
else if(root.leftNode == (what your looking for))
{
return root.leftNode
}
else if(root.rightNode == (what your looking for))
{
return root.rightNode
}
else
{
System.out.println("Value not found")
}
If you have 5 nodes, that would be root would have a left and right, and the root.leftNode would have a left and right... You would repeat the steps above on root.leftNode also, then search root.rightNode
If you have 7 nodes, you would search ALL of root.leftNode and then recurse back to search root.leftNode.
I hope this helps,
pictures work much better in my opinion when talking about traversing trees.
Perhaps look here for a better visual
http://www.newthinktank.com/2013/03/binary-tree-in-java/
i have an assignement to find the longest path in a maze using recursion. i also have to show the process of searching for the path. I think i get the idea of how its supposed to be done but i get myself into truble when it comes to the code. Now i don't want the code done for me. I just need some pointers and some tips on my logic. . this is my recursive method so far. I guess there is no point sharing the graphics methods since the recursive method is where im stuck at.
void findPath(Point a){ // starting point
if (a == mazeEnd){
pathAdd(a);
return;
}
if (wall(a)) return;
if (visited(a)) return;
if (a == mazeStart) pathAdd(a);
length++
printPath;
findPath(new Point(a.x+1, a.y));
findPath(new Point(a.x, a.y+1));
findPath(new Point(a.x-1, a.y));
findPath(new Point(a.x, a.y-1));
}
UPDATE: ok thank you all for the tips and let me further explain. the entire board is a grid. i read the walls, starting and enting point from a file. i create a list for the walls and palce them on the board. wall(a) checks if a coordinate is the walls array. pathAdd is a method taht adds a coordinate to the path array. but doesnt that means that after it has complyted all the paths, the path array will have every coordinate in that board except the ones that are walls? At least in the wway i have coded it. Thats my major issue i think. If i can get the list to only hold one path i guess ill figure out how to get the largest out of it.
There's a few omissions I see.
You never add the current point to your path - you only ever add the start or the end.
You never mark any points as visited.
You check to see if things are visited, but you don't have a way of knowing if they were visited in this path or some other path. Consider the scenario where there is some islands of walls, and you could reach a point via two or more routes: one of those routes may be longer than the other routes, but you're more likely to reach it via the short route first. It will end up being ignored, when it should be considered as a candidate for both routes.
You are triggering length++ on every call to find path. If you do your first node, and then the 4 nodes around it, you're going to have a length of 5 when your longest is 2. That's no good!
If you passed a list into the method, when you found a path that made it to the end of the maze, you could add it to the list. then when recursion finishes, you can iterate through the list to find the longest path.
You are restricting to move further when a cell/point is visited. But I didn't see you marked a cell/point as visited in your code. You can do this just before moving into the four directions. If you do not do this, your recursion will never get an end.
findPath(a) should return a length. Specifically it should return the max(findPath(up) || findpath(down) || findPath(left) || findPath(right)) + 1. If wall(a) or visisted(a), you can return a large negative number and for mazeEnd(a) return 1. To print the path you need to add the new Point that returns the greatest length with pathAdd(). Hope that helps :)
I trying to complete a RPG game for a project, but have no idea on how to make the game map.
It doesn't need to be graphical, but the code for the whole map and each tile must be correct.
So far, I thought about making a non-matricial map (as request by the professor) by using an ArrayList which contain all the linked tiles.
public abstract class Casella {
/**
* #uml.property name="tabellone"
* #uml.associationEnd multiplicity="(1 1)" inverse="casella:Tabellone"
* #uml.association name="contains"
*/
private int id;
private boolean free = true;
private List adjacent;
private List items;
private Tabellone tabellone = null;
public void in(){
free = false;
}
public void out(){
free = true;
}
}
This was the code for a single tile (which has 3 classes that extends it). I still have no idea on how to put together and generate a map.
Thank you for your time.
Don't start with the implementation, start with how you would like to use the map. That will give you some constraints how to implement it. For example:
When drawing the map, how do you access it? By coordinate? Or by "go west from tile X"?
[EDIT] I suggest to start with the main loop of the RPG game. You'll need to place the character/token somewhere (i.e. it needs some kind of relation to a tile).
Then you need to move the character. A character must be able to examine the current tile (opponents, items, type). It needs a way to know how it can move (i.e. is there a wall to the right?)
This gives you an interface for your map: Services which it renders for other objects in the game. When you have an idea of what the interface needs to provide, that should give you an idea how to implement the map (the data structure).
As for generating a map, use a random number generator plus some "common sense". Have a look at the adjacent tiles: When they are all city, this tile is probably city, too. Same for plains. Hills are singular items, and they are least frequent.
Run this code, print the map as ASCII ("C"ity, "P"lain, "H"ill) to see if it works.
To generate a map like this without using a matrix, I recommend starting with a center tile and then populating the map outwards by using a modified breadth first search algorithm. First of all, we'll need something a little better than a list of adjacent tiles. You could simply have four variables, one for each direction that stores the next tile, as such:
private Tabellone up = null;
private Tabellone down = null;
private Tabellone left = null;
private Tabellone right = null;
Say we start with the center-most tile. All you have to do now is figure out how many of the directions are null, and create a new Tablellone object for each direction, making sure to set each of the variables in this current object and to set the appropriate opposite variable in the object created.
Tabellone adj = new Tabellone();
up = adj;
adj.setDown(this);
Once you've filled out all of the directions on this tile, you then choose one of the other tiles you've created and perform the same operation. This is where the breadth-first search algorithm comes in. You can use a queue to go through each tile you've created and fill out the directions. To make the algorithm stop, simply set a limit on the number of tiles you want to create and use a counter to keep track of how many have been created.
int count = 0;
ArrayList<Tabellone> queue = new ArrayList<Tabellone>()
queue.add(/*center tile*/);
while (count < 100) { //if we want 100 tiles
//take out the center tile from the beginning of the array list, create a tile for each direction and add those tiles to the array list, then increment count by 1.
}
Note: This algorithm as it stands will create a diamond shaped map, if you want a square, you'd need to have a variable for each diagonal direction as well.
Of course, if this seems a little more complicated than you'd like, I'd recommend a coordinate system.
The walls, baggs and areas are special containers, which will hold all the walls, baggs and areas of the game.
private String level =
" ######\n"
+ " ## #\n"
+ " ##$ #\n"
+ " #### $##\n"
+ " ## $ $ #\n"
+ "#### # ## # ######\n"
+ "## # ## ##### ..#\n"
+ "## $ $ ..#\n"
+ "###### ### #### ..#\n"
+ " ## #########\n"
+ " ########\n";
This is the level of the game. Except for the space, there are five characters. The hash (#) stands for a wall. The dollar ($) represents the box to move. The dot (.) character represents the place where we must move the box. The at character (#) is the sokoban. And finally the new line character (\n) starts a new row of the world.
Is speed or memory a huge concern for this project? If not, why don't you use a 2d array?
Something like
Casella map [][] = new Casella[xSize][ySize];
From here it is easy to conceptualize, just picture it as an excel spreadsheet where each cell is a tile on the map.
The way you are going is fine though, just a little hard to conceptualize sometimes. You have a List of adjacent tiles. So, when creating your map you start somewhere, possibly top left, and go from there.
You could use nested for loops in order to set up the map, and to help determine the edge items.
for(int i = 0; i < XSIZE ; ++i)
for(int j = 0; j < YSIZE ; ++j)
if(j==0) //found left edge (i.e. no adjacent ones to the left)
if(j==(YSIZE)) //found right edge (you get the picture)
The point of using the loops, and checking the edges, is that you are going to need to link backwards and forward, up and down for each tile except at the edges, where you will have either 2 or 3 links instead of 4.
The code needs to be correct really isn't a functional requirement, so its hard to say exactly what is correct without knowing more about your game/map.
Assuming you have a map that has X tiles and no ordered adjacency a non-matricial solution is best, a common solution is to just model it like a graph using either adjacency list for non-symmetric adjacency or incidence list for symmetric adjacency. If youre using an incidence list you need an edge object that contain the vertices the edge is connecting, if youre using adjacency list a multimap might be cool to use.
If you want a non-matricial solution with ordered adjacency AlbertoPL has the solution for that.
Assuming you have a map thats X tiles wide and Y tiles tall and the tiles that are next to each other are adjacent, so that each tile has at max 4 and min 2 adjacent tiles you could use a matrix to access the tiles and also represent adjacency by matricial adjacency. The idea is that map[Y][X] is adjacent to map[Y+1][X] and map[Y][X+1] and reversely.
This solution could also fit max 6 and min 3 tile adjacency if tile [Y+1][X+1] is adjacent to tile [Y][X].
Upside to this is that you can easily parse the map, and since it has 2 dimensions its natural to model it like this.
Downside is that once a tile is set, you cant change its adjacency without changing the matrix. As this isnt what you professor suggested you might not want to do it, but if you have (static) ordered adjacency this might be easiest way to do it.
I managed this by using adjacency lists.
Each cell will have an ArrayList containing the indexes of the adjacent cells. Those indexes are the ones that the said cell have in the map ArrayList of cells.
http://en.wikipedia.org/wiki/Adjacency_list
If it's a tile-based map, then each room has a fixed relationship with its adjacent rooms. You may not need to worry about co-ordinates (although it might be simpler if the tiles are square), but you will need to worry about directions.
If the tiles are square, cardinal directions (n, s, e, w) may be all you need care about. If they're hex tiles, you can number your exits 1-6 (perhaps with static final constants). Then each adjacent tile may be linked to this one along with its exit.
As said by Aaron, you need to decide first how the maping coordinates will be.
But you are not constrained by an X-Y-Z coordinate system. For instance, each tile could be linked to any other tile on your map. It all depends on how you want to build it.
You say that you're building an RPG game, then you need to have a good view of the terrain surround your character. Is it multi-level? How does the character move from one tile to another? Is the movement one way?
There are, literally, dozens of question to be asked when designing a map for a game.
You need to plan it very well first, before starting coding.