I'm having a hard time finding an admissible heuristic for the Hungarian Rings puzzle. I'm planing on using IDA* algorithm to solve and am writing the program in Visual Basic. All I am lacking is how to implement the actual solving of the puzzle. I've implemented both the left and right rings into their own arrays and have functions that rotate each ring clockwise and counterclockwise. I'm not asking for code, just somewhere to get started is all.
Here is the 2 ring arrays:
Dim leftRing(19) As Integer
' leftRing(16) is bottom intersection and leftRing(19) is top intersection
Dim rightRing(19) As Integer
' rightRing(4) is top intersection and rightRing(19) is bottom intersection
In the arrays, I store the following as the values for each color:
Red value = 1 Yellow = 2 Blue = 3 and Black = 4
I suggest counting "errors" in each ring separately - how many balls need to be replaced to make the ring solved (1 9-color, 1 10-color, one lone ball from a 9-color). At most two balls can be fixed using a rotation, then another rotation is needed to fix another two. Compute the distance of each ring individually = 2n-1 where n is half the amount of bad positions and take the larger of them. You can iterate over all twenty positions when looking for one that has the least amount of errors, but I suppose there's a better way to compute this metric (apart from simple pruning).
Update:
The discussion with Gareth Reed points to the following heuristic:
For each ring separately, count:
the number of color changes. The target amount is three color changes per ring, and at most four color changes may be eliminated at a time. Credits go to Gareth for this metric.
the count of different colors, neglecting their position. There should be: 10 balls of one 10-color, 9 balls of one 9-color and one ball of the other 9-color. At most 2 colors can be changed at a time.
The second heuristic can be split into three parts:
there should be 10 10-balls and 10 9-balls. Balls over ten need to be replaced.
there should be only one color of 10-balls. Balls of the minor color need to be replaced.
there should be only one ball of a 9-color. Other balls of the color need to be replaced. If all are the same color, and 9-color is not deficient, one additional ball need to be replaced.
Take the larger of both estimates. Note that you will need to alternate the rings, so 2n-1 moves are actually needed for n replacements. If both estimates are equal, or the larger one is for the latest moved ring, add an additional one. One of the rings will not be improved by the first move.
Prune all moves that rotate the same ring twice (assuming a move metric that allows large rotations). These have already been explored.
This should avoid all large local minima.
Related
I searched and even visited a maze-algorithm-collecting website, but nothing satisfies the following statements I require.
To make it clear, I need an infinite maze generating algorithm that:
makes a perfect maze , which is to say,
2d,grid-based
each square is space/wall
every 2 spaces are linked and there's only one path
no 2x2 square is all space/wall
provides an f(s,x,y), where s is used for random seed or something like this
returns type of square at (x,y)
for different s within 0~(32768 or something), gives different results
infinite (probably limited by 64-bit int though)
extra space (I mean in program) is allowed
Clarification:
meaning of infinite here: something like this
function f(s,x,y){
// for each x,y it gives a result, so we consider it "infinite"
return (s*x+y)%32768<30 ? "wall" : "space";
}
this is a finite algorithm (satisfies 1)
init:all walls
choose a square,flag it and add to list
while(list not empty)
{
chose randomly from list
delete from list
if(there's a flag)
{
delete it
continue
}
make a flag
if(surrounding wall num≤1)
{
add 4 surrounding walls to list
}
}
something satisfies 1 and 3
we start from the Eller's Algorithm
it is generated row by row, and saves a set of regions
first row:all regions into a set,wall between regions(randomly)
while(not last row){
foreach(neighbour regions){
if(not in the same set){
break their wall and merge the regions(randomly)
}
}
foreach(region){
break the wall below(randomly,and at least one does this)
}
generate next row
for this row:{
foreach(region){
if(connected with above){
merge to prev-set
}
}
throw away prev-prev-set
}
}
last row:connect all regions that are not in the same set
If we start from the centre and generate it circle by circle, it can be infinite; sadly we have rule 2.
The problem seems a bit overwhelming: infinitely many infinite mazes, such that we can restrict ourselves to a multitude of different bounds (say, if we wanted a roughly 1 million x 1 million square) and still have unique paths between any two spaces (and your other conditions). Let's break this down into smaller pieces.
Suppose we could construct a 7 by 7 square maze-block, and were able to make a border of walls around it, with one or two gates on this border where we wanted. Then all we'd have to do is connect these square blocks in a spiral: a central square with one gate at the top, and a counterclockwise spiral of blocks with two gates each, in the direction of the spiral:
(Each numbered box is a 7x7 maze)
There's two general cases:
'Straight' pieces, where the two gates are on opposite sides, and
'Corner' pieces, where the spiral turns and gates are on adjacent sides.
We want to make these pieces generic, so we can mix and match mazes and have them fit together. To do this, we'll use this template:
Border Rule: The bottom and left sides of each square are all walls, except in the center of each side.
Free space Rule: Unless required by rules 1 or 3, no walls are allowed in the top and right sides of a maze square.
Gate Rule: Where two mazes meet, if the meeting is part of the spiral, both center sides will be open (in other words, crossings happen in the center of the borders). Otherwise, the maze which is below or to the left of the other shall have a wall in the center of this border.
That's a lot, so let's see an example. Here we have a template for a 'straight' horizontal connector, highlighted in blue (all mazes are 7 by 7). X means wall, O means required to be open (a crossing point/open gate between two mazes). Red X's are the border from rule 1, purple X's are blocked gates from rule 3.
The center 5 by 5 of each maze is customizable. We must ensure that there are no inaccessible squares or equal 2x2 within our maze only, since the rules above guarantee this is true where mazes meet.
One possible maze to fit the above template (there are many):
For an example of a corner piece:
I've similarly drawn examples of each possible connection to make sure it's always possible: there are many possible ways to do this for each piece type (including the special center piece).
Now, for how to generate infinitely many infinite mazes based on a seed. Suppose you created at least 2 examples of each connection piece (there are 2 straight connectors and 4 corners), although you can just make one of each and reflect it. (Really you only need 2 different examples of one connection type.)
Given any seed binary string, e.g. 10110, let this denote our choices of which example piece to use while we make the maze spiral, counting up as in the first picture. A '0' means means use our 1st example for this connector; a '1' means we use the second. You can then repeat this/extend the binary string infinitely (10110 10110 ...). Since this is periodic, we can, using some math, figure out the piece type at any point in the sequence.
I've left out the math for the pattern of connection types: this is easy to work out for a counterclockwise spiral. Given this pattern, and a convention that the point x,y = (0,0) is the bottom left corner of the spiral-start-maze-block, you can work out 'wall or space' for arbitrary x and y. This maze is infinite: you can also restrict the borders to any full odd square of mazes in the spiral, i.e. (7*(2n+1))^2 cells for positive n.
This framework pattern for a maze is customizable, but not very difficult to solve, as the regularity means you only need to solve it locally. There's nothing special about 7; any odd number at least 7 should work equally well with the same rules, if you want to make local maze blocks larger and more complex.
I have a big rectangle of size 12*12. Now I have 6 rectangles already placed on the floor of that rectangle. I know the center coordinate of that pre-placed module. Now I have few another 14 rectangles to place upon that floor of that rectangle. How to do so?
here all my pre placed block those having center coordinate as say (2,5),(5,7),(9,2),(7,8),(11,9),(3,11).
Now how could I place 14 another rectangle in this floor so that it would not over lap with any preplaced block.
I would like to code in MATLAB..but what approach should I follow?
If a nice even placement is important, I suggest you look up simulated force-based graph layout. In this problem, you'll use simulated forces pushing the rectangles apart and also away from the border rectangle according to Coulomb's law. The initial configuration is randomly selected. You'll want to give the rectangles mass proportional to their area, I think. You don't have any spring forces due to edges, which makes it easier. The iteration to solve the differential equations of motion will be easy in Matlab. Or there may well be a toolkit to do it for you. Animations of these algorithms are fun.
Unfortunately with constrained problems like this, the fixed rectangles can form barriers that prevent the moving rectangles from getting to a non-overlapping solution. (Think of the case where the fixed rectangles are in a line down the middle and all the moving ones get "trapped" on one side or the other. The same thing happens in graph layout if some nodes have fixed locations.) There are various strategies for overcoming these bad cases. One is to start with no fixed objects at all, let the moving rectangles come to an equilibrium, then add the fixed ones one at a time, largest first, allowing the system regain equilibrium each time. Another, simpler one is just to start from different random initial conditions until you find one that works. There are also approaches related to simulated annealing, which is too big a topic to discuss here.
Here is a function to check overlap for two rectangles. you could loop it to check for more number of rectangles based on #Dov's idea.
For two rectangles Ri, i = 1,2, with centers (xi,yi) and half-lengths of their sides ai,bi > 0 (assuming that the sides are aligned with the coordinate axes).
Here is my implementation based on above equation:
In my code i've taken xcPosition and ycPosition as the center position of the rectangle.
Also length and breadth are the magnitude of sides of the rectangle.
function [ overLap, pivalue ] = checkOverlap( xcPosition1,ycPosition1,xcPosition2,ycPosition2,length1,breadth1,length2,breadth2 )
pix = max((xcPosition2 - xcPosition1 -(length1/2)-(length2/2)),(xcPosition1 -xcPosition2 -(length2/2)-(length1/2)));
piy = max((ycPosition2 - ycPosition1 -(breadth1/2)-(breadth2/2)),(ycPosition1 -ycPosition2 -(breadth2/2)-(breadth1/2)));
pivalue = max(pix, piy);
if (pivalue < 0)
overLap = 1; %// Overlap exists
else
overLap = 0; %// No overlap
end
end
You could also use the pivalue to know the degree of overlap or Non-overlap
The Pseudo-code for looping would be something like this:
for i = 1 : 14
for j = 1 : i-1 + 6 already placed parts
%// check for overlap using the above function here
%// place the part if there is no overlap
end
end
With such a small number, put each rectangle in a list. Each time you add a new rectangle, make sure the new one does not overlap with any of the existing ones.
This is O(n^2), so if you plan to increase to 10^3 or more rectangles you will need a better algorithm, but otherwise you're fine.
Now if your problem specifies that you might not be able to fit them all, then you will have to backtrack and keep trying different places. That is an N! problem, but if you have a lot of open space, many solutions will be possible.
Please look at this picture first:
As you can see, blue and red both have a line showing the frontline bases.
Let's assume two players start playing against eachother.
One placing a base at the far left, the other at the far right.
The players continue by expanding and gaining territory.
After a while, the two sides will meet and battle will start.
Question is, in a randomly ordered list of base positions how would one find the two lines that are drawn in the picture?
You could get the distance between enemy bases, where the distance is shorter is the frontline.
Example:
0 1 2 3 4 5 6
0 aa A B bbb
1 aA B bb
2 A B b
3 aA B b
4 aaaA Bb
5 aaaA B
6 aaaA B
If you substract the X positions of the enemy bases in the same row, the ones with the less distance between them are the front lines, B.x - A.x will give you a smaller number that b.x - a.x. Then you can check which ones were the ones that gave you the smaller distance for each row.
Unless I'm getting your question wrong.
area
many games do not draw territory border by polylines
instead they draw a disc with constant radius (or dependent on base strength) at every base position
if the radius is set big enough then these discs/circles will overlap
and create seamless area of single color representing controlled territory
it is easy but inaccurate
perimeter polyline
first cluster all bases and create lists of bases close together
this can be done by grouping bases with distance <= treshold
process each group
find the outer most bases of group
something like perimeter points
this may help with it
also it contains inverse problem of yours which can solve the whole thing more here
now find the perimeter closed loop of area
the algorithm for that is also in the link above
when done then use this list of points as BEZIER cubics poly-curve control points
if borderline too close to the bases then enlarge the points
first compute avg point ap of group
then any point p is computed p=((p-ap)*scale)+ap
it is not exact but for your purposes it is enough
if you want something better then
p=p-ap
l=|p|
p=ap+(p*(l+dl)/l)
where dl is the step at which your border is enlarged
and if you want the accurate thing then you have to compute polygon enlargement
which is not easy task
handle edge cases
for singular base groups draw circle around
this approach has problem in close proximity of bases
one solution is not to count bases too close to any enemy base
per pixel borders
you can process the map image by pixels
something like this: (beware this is not tested)
per each pixel
compute the min distance to any player bases
remember two closest distances of different players
distance0 is closest
distance1 is second closest (but base owns another player)
select territory ownership
the player which has closest base own this
if the distance0 > treshold then this area is uncontrolled
in that case stop processing this pixel
if ((distance0 >= d-w)&&(distance0 <= d+w)&&(distance1>d+w+s)) then set pixel color to border polyline color
d is border line distance from base
w is half-size of borderline thickness
s is min distance between close front lines
edge case
previous step ignore border points that are closer to bases (close enemy bases)
to add them just add
if ((distance0<d)&&(|distance0-distance1|<=s+w)&&(|distance0-distance1|>=s-w)) then set pixel color to player ownership
also this will fail if any two opposing bases are closer then s-w
[Notes]
I think the best way is the per pixel
it is most close to the solution you want
the render can be a bit slower but you need to change it only if any base is conquered
I'm working on a snake game (Nibbles in Linux) that is played on a 60*60 field, with four snakes competing for an apple which is randomly placed.
I've implemented the movement of my snake with the A* (A star) Algorithm.
My problem is this: When I'm not the nearest snake to the apple, I don't want to go to get the apple, because my chance to get it is lower than at least one snake, so I want to look for a place that I hope at the next place that an apple is generated , Then I'll be the nearest snake to that apple. I mean that I'm looking for a place which is nearest to the maximum number of potential locations.
Please suggest any good way or any algorithm that can help me to find this place.
Here is an image of the game. The red points are the snakes' heads.
I tested some ways and Finally I decided to use this way:
I think the best way is to make a 2D array with size:60*60 , then for each node(x) of the array, calculate how many nodes of the field-which are walkable!(not block), is this node(x) nearest to.
then the answer will be The maximum amount, then I set this node the goal.
but because I must find the next move in less than 0.1sec and to do this work, there is 4 loops of size:60, (60^4) and when I found it, A* algorithm will be run too , this work would never be done in less than 0.1 sec.
So , since the Snake can't move Diagonally and it goes just: up,down,right,left, I decided not to check all the nodes,Since in each cycle(0.1sec) , I can just move 1 unit, I decided to check just 4 nodes(up,down,left,right) and move to a node which It's amount is Max.
now it's working almost right. ;)
Since you have already implemented A*, after you generate your map, you could use A* to create a map of values for each cell based on the total cost from each cell to visit every other cell. If you generate this after you've placed your blocks, then your weighted map will account for their presence.
To generate this, off the top of my head, I would say you could start from each cell, and assign it one point for each cell it can visit in one turn. For example, a cell in the corner would get two points for the first move, because it can only access two other cells. It would get five points for the second turn, because it can access five cells in two moves. Repeat until you've visited all the other squares, and then you have the score for that square.
From that point, if an apple appears and your snake is not the closest to it, your snake could head for the highest weighted cell, which you've calculated beforehand.
Edit: Please see comments below for a more advantageous solution.
If you are nearest to apple you should walk to get it but if you are far apart from apple your best chance is walking in a middle of map, you should find strategy to how to occupy the middle of map.
You can divide your map to four zooms (clockwise), upper left, upper right, bottom right and bottom left (1,2,3,4). We check this between two snakes: If apple currently is in zoom 1 (assume center for average) and you are in center of map, your opponent can be in zooms 1,2,3,4 (again assume it's in the center of this zooms to take average in simpler way) if it's in zoom 1 it has better chance (1-0) if it's in zoom 2 or 4, your distance is sqrt(2)/2 and your opponent distance is 1, so you are nearest, and finally if your opponent is in zoom 3 your distance is sqrt(2)/2 and your opponent distance is sqrt(2), so in 3 cases with one oppnent you have better chance.
But because your shape has some blocks, you should calculate center position in other way, in fact, for each point in your grid calculate its distance to all other points. this will take 60^2 * 60^2 which can be done fast. and find cells with minimum total sums(you can select best 10 cells), this cells can be your centers, everytime you should move from one center to another (except when you are nearest to apple or your snake eats apple and wants comback to nearest centers) .
Nearest to the maximum number of locations is the center as others have stated. Nearer to the maximum number of locations than the other snakes is a much, different and harder questions. In that case, I would A* the head of each snake to see who has the most squares under control. That's the base score. Next, as I'm drawing a blank, I'd Monte Carlo a random set of points around the map and choose the point that gave the highest score as a destination. If you had the processing power, you could try every point on the grid and choose the best as K.G. suggested, but that could get pretty intense.
The true test is when you find your point, figure out how far in the future it takes you to get there, and running some AI for the other snakes to see if they will intercept you. You start getting into plys like chess. :)
What is the most efficient way to randomly fill a space with as many non-overlapping shapes? In my specific case, I'm filling a circle with circles. I'm randomly placing circles until either a certain percentage of the outer circle is filled OR a certain number of placements have failed (i.e. were placed in a position that overlapped an existing circle). This is pretty slow, and often leaves empty spaces unless I allow a huge number of failures.
So, is there some other type of filling algorithm I can use to quickly fill as much space as possible, but still look random?
Issue you are running into
You are running into the Coupon collector's problem because you are using a technique of Rejection sampling.
You are also making strong assumptions about what a "random filling" is. Your algorithm will leave large gaps between circles; is this what you mean by "random"? Nevertheless it is a perfectly valid definition, and I approve of it.
Solution
To adapt your current "random filling" to avoid the rejection sampling coupon-collector's issue, merely divide the space you are filling into a grid. For example if your circles are of radius 1, divide the larger circle into a grid of 1/sqrt(2)-width blocks. When it becomes "impossible" to fill a gridbox, ignore that gridbox when you pick new points. Problem solved!
Possible dangers
You have to be careful how you code this however! Possible dangers:
If you do something like if (random point in invalid grid){ generateAnotherPoint() } then you ignore the benefit / core idea of this optimization.
If you do something like pickARandomValidGridbox() then you will slightly reduce the probability of making circles near the edge of the larger circle (though this may be fine if you're doing this for a graphics art project and not for a scientific or mathematical project); however if you make the grid size 1/sqrt(2) times the radius of the circle, you will not run into this problem because it will be impossible to draw blocks at the edge of the large circle, and thus you can ignore all gridboxes at the edge.
Implementation
Thus the generalization of your method to avoid the coupon-collector's problem is as follows:
Inputs: large circle coordinates/radius(R), small circle radius(r)
Output: set of coordinates of all the small circles
Algorithm:
divide your LargeCircle into a grid of r/sqrt(2)
ValidBoxes = {set of all gridboxes that lie entirely within LargeCircle}
SmallCircles = {empty set}
until ValidBoxes is empty:
pick a random gridbox Box from ValidBoxes
pick a random point inside Box to be center of small circle C
check neighboring gridboxes for other circles which may overlap*
if there is no overlap:
add C to SmallCircles
remove the box from ValidBoxes # possible because grid is small
else if there is an overlap:
increase the Box.failcount
if Box.failcount > MAX_PERGRIDBOX_FAIL_COUNT:
remove the box from ValidBoxes
return SmallCircles
(*) This step is also an important optimization, which I can only assume you do not already have. Without it, your doesThisCircleOverlapAnother(...) function is incredibly inefficient at O(N) per query, which will make filling in circles nearly impossible for large ratios R>>r.
This is the exact generalization of your algorithm to avoid the slowness, while still retaining the elegant randomness of it.
Generalization to larger irregular features
edit: Since you've commented that this is for a game and you are interested in irregular shapes, you can generalize this as follows. For any small irregular shape, enclose it in a circle that represent how far you want it to be from things. Your grid can be the size of the smallest terrain feature. Larger features can encompass 1x2 or 2x2 or 3x2 or 3x3 etc. contiguous blocks. Note that many games with features that span large distances (mountains) and small distances (torches) often require grids which are recursively split (i.e. some blocks are split into further 2x2 or 2x2x2 subblocks), generating a tree structure. This structure with extensive bookkeeping will allow you to randomly place the contiguous blocks, however it requires a lot of coding. What you can do however is use the circle-grid algorithm to place the larger features first (when there's lot of space to work with on the map and you can just check adjacent gridboxes for a collection without running into the coupon-collector's problem), then place the smaller features. If you can place your features in this order, this requires almost no extra coding besides checking neighboring gridboxes for collisions when you place a 1x2/3x3/etc. group.
One way to do this that produces interesting looking results is
create an empty NxM grid
create an empty has-open-neighbors set
for i = 1 to NumberOfRegions
pick a random point in the grid
assign that grid point a (terrain) type
add the point to the has-open-neighbors set
while has-open-neighbors is not empty
foreach point in has-open-neighbors
get neighbor-points as the immediate neighbors of point
that don't have an assigned terrain type in the grid
if none
remove point from has-open-neighbors
else
pick a random neighbor-point from neighbor-points
assign its grid location the same (terrain) type as point
add neighbor-point to the has-open-neighbors set
When done, has-open-neighbors will be empty and the grid will have been populated with at most NumberOfRegions regions (some regions with the same terrain type may be adjacent and so will combine to form a single region).
Sample output using this algorithm with 30 points, 14 terrain types, and a 200x200 pixel world:
Edit: tried to clarify the algorithm.
How about using a 2-step process:
Choose a bunch of n points randomly -- these will become the centres of the circles.
Determine the radii of these circles so that they do not overlap.
For step 2, for each circle centre you need to know the distance to its nearest neighbour. (This can be computed for all points in O(n^2) time using brute force, although it may be that faster algorithms exist for points in the plane.) Then simply divide that distance by 2 to get a safe radius. (You can also shrink it further, either by a fixed amount or by an amount proportional to the radius, to ensure that no circles will be touching.)
To see that this works, consider any point p and its nearest neighbour q, which is some distance d from p. If p is also q's nearest neighbour, then both points will get circles with radius d/2, which will therefore be touching; OTOH, if q has a different nearest neighbour, it must be at distance d' < d, so the circle centred at q will be even smaller. So either way, the 2 circles will not overlap.
My idea would be to start out with a compact grid layout. Then take each circle and perturb it in some random direction. The distance in which you perturb it can also be chosen at random (just make sure that the distance doesn't make it overlap another circle).
This is just an idea and I'm sure there are a number of ways you could modify it and improve upon it.