I want to do random generation of levels using 2D arrays. 0 = emptiness, 1 = wall, how generate levels which have a passable route from a starting point to a finish(yellow circle, appears in a random free spot on the map) location?
pole = [[0] * 20 for i in range(20)]
for i in range(20):
for j in range(20):
pole[i][j] = random.randint(0, 1)
At the moment it just randomizes the ones and zeros and it comes out:
The best way to do this is to generate a random map just like you do now and them check with an algorithm if there is an open route between start and finish. If not, just generate a new map and check again.
A "flood fill" algorithm where you start filling from start and see if the fill reaches the finish spot could work. For algorithm help, see:
Need help implementing flood-fill algorithm
Related
I have a set of sphere coordinates in 3D that evolves.
They represent a stack of spheres which are continuously removed from a box from the bottom of the geometry, and reinserted at the top at a random location. Since this kind of simulation is really periodic, I would like to simulate the drainage of the box a few times (say, 5 times, so t=1 takes positions 1 -> t=5 takes positions 5), and then come back to the first state to simulate the next steps (t=6 takes position 1, t=10 takes positions 5, same for t=11->15, etc.)
The problem is that at the coordinates of a given sphere (say, sphere 1) can be very different from the first state to the last simulated one. However, it is very important, for the sake of the simulation, to have a simulation as smooth as possible. If I had to quantify it, I would say that I need the distance between state 5 and state 6 for each pebble to be as low as possible.
It seems to me like an assignment problem. Is there any known solution and method for this kind of problems?
Here is an example of what I would like to have (I mostly use Python):
import numpy as np
# Mockup of the simulation positions
Nspheres = 100
Nsteps = 5 # number of simulated steps
coordinates = np.random.uniform(0,100, (Nsteps, Nspheres, 3)) # mockup x,y,z for each step
initial_positions = coordinates[0]
final_positions = coordinates[Nsteps-1]
**indices_adjust_initial_positions = adjust_initial_positions(initial_positions, final_positions) # to do**
adjusted_initial_positions = initial_positions[indices_adjust_initial_positions]
# Quantification of error made
mean_error = np.mean(np.abs(final_positions-adjusted_initial_positions))
max_error = np.max(np.abs(final_positions-adjusted_initial_positions))
print(mean_error, max_error)
# Assign it for each "cycle"
Ncycles = 5 # Number of times the simulation is repeated
simulation_coordinates = np.empty((Nsteps*Ncycles, Nspheres, 3))
simulation_coordinates[:Nsteps] = np.array(coordinates)
for n in range(1, Ncycles):
new_cycle_coordinates = simulation_coordinates[Nsteps*(n-1):Nsteps*(n):, indices_adjust_initial_positions, :]
simulation_coordinates[Nsteps*n:Nsteps*(n+1)] = new_cycle_coordinates
# Print result
print(simulation_coordinates)
The adjust_initial_positions would therefore take the initial and final states, and determine what would be the ideal set of indices to apply to the initial state to look the most like the final state. Please note that if that makes the problem any simpler, I do not really care if the very top spheres are not really matching between the two states, however it is important to be as close as possible at more towards the bottom.
Would you have any suggestion?
After some research, it seems that scipy.optimize has some nice features able to do something like it. If list1 is my first step, list2 is my last simulated step, we can do something like:
cost = np.linalg.norm(list2[:, np.newaxis, :] - list1, axis=2)
_, indexes = scipy.optimize.linear_sum_assignment(cost)
list3 = list1[indexes]
Therefore, list3 will be as close as list2 as possible thanks to the index sorting, while taking the positions of list1.
I have a problem where in a grid of x*y size I am provided a single dot, and I need to find the nearest neighbour. In practice, I am trying to find the closest dot to the cursor in pygame that crosses a color distance threshold that is calculated as following:
sqrt(((rgb1[0]-rgb2[0])**2)+((rgb1[1]-rgb2[1])**2)+((rgb1[2]-rgb2[2])**2))
So far I have a function that calculates the different resolutions for the grid and reduces it by a factor of two while always maintaining the darkest pixel. It looks as following:
from PIL import Image
from typing import Dict
import numpy as np
#we input a pillow image object and retrieve a dictionary with every grid version of the 3 dimensional array:
def calculate_resolutions(image: Image) -> Dict[int, np.ndarray]:
resolutions = {}
#we start with the highest resolution image, the size of which we initially divide by 1, then 2, then 4 etc.:
divisor = 1
#reduce the grid by 5 iterations
resolution_iterations = 5
for i in range(resolution_iterations):
pixel_lookup = image.load() #convert image to PixelValues object, which allows for pixellookup via [x,y] index
#calculate the resolution of the new grid, round upwards:
resolution = (int((image.size[0] - 1) // divisor + 1), int((image.size[1] - 1) // divisor + 1))
#generate 3d array with new grid resolution, fill in values that are darker than white:
new_grid = np.full((resolution[0],resolution[1],3),np.array([255,255,255]))
for x in range(image.size[0]):
for y in range(image.size[1]):
if not x%divisor and not y%divisor:
darkest_pixel = (255,255,255)
x_range = divisor if x+divisor<image.size[0] else (0 if image.size[0]-x<0 else image.size[0]-x)
y_range = divisor if y+divisor<image.size[1] else (0 if image.size[1]-y<0 else image.size[1]-y)
for x_ in range(x,x+x_range):
for y_ in range(y,y+y_range):
if pixel_lookup[x_,y_][0]+pixel_lookup[x_,y_][1]+pixel_lookup[x_,y_][2] < darkest_pixel[0]+darkest_pixel[1]+darkest_pixel[2]:
darkest_pixel = pixel_lookup[x_,y_]
if darkest_pixel != (255,255,255):
new_grid[int(x/divisor)][int(y/divisor)] = np.array(darkest_pixel)
resolutions[i] = new_grid
divisor = divisor*2
return resolutions
This is the most performance efficient solution I was able to come up with. If this function is run on a grid that continually changes, like a video with x fps, it will be very performance intensive. I also considered using a kd-tree algorithm that simply adds and removes any dots that happen to change on the grid, but when it comes to finding individual nearest neighbours on a static grid this solution has the potential to be more resource efficient. I am open to any kinds of suggestions in terms of how this function could be improved in terms of performance.
Now, I am in a position where for example, I try to find the nearest neighbour of the current cursor position in a 100x100 grid. The resulting reduced grids are 50^2, 25^2, 13^2, and 7^2. In a situation where a part of the grid looks as following:
And I am on the aggregation step where a part of the grid consisting of six large squares, the black one being the current cursor position and the orange dots being dots where the color distance threshold is crossed, I would not know which diagonally located closest neighbour I would want to pick to search next. In this case, going one aggregation step down shows that the lower left would be the right choice. Depending on how many grid layers I have this could result in a very large error in terms of the nearest neighbour search. Is there a good way how I can solve this problem? If there are multiple squares that show they have a relevant location, do I have to search them all in the next step to be sure? And if that is the case, the further away I get the more I would need to make use of math functions such as the pythagorean theorem to assert whether the two positive squares I find are overlapping in terms of distance and could potentially contain the closest neighbour, which would start to be performance intensive again if the function is called frequently. Would it still make sense to pursue this solution over a regular kd tree? For now the grid size is still fairly small (~800-600) but if the grid gets larger the performance may start suffering again. Is there a good scalable solution to this problem that could be applied here?
I have a set of approximately 10,000 vectors max (random directions) in 3d space and I'm looking for a new direction v_dev (vector) which deviates from all other directions in the set by e.g. a minimum of 5 degrees. My naive initial try is the following, which has of course bad runtime complexity but succeeds for some cases.
#!/usr/bin/env python
import numpy as np
numVecs = 10000
vecs = np.random.rand(numVecs, 3)
randVec = np.random.rand(1, 3)
notFound=True
foundVec=randVec
below=False
iter = 1
for vec in vecs:
angle = np.rad2deg(np.arccos(np.vdot(vec, foundVec)/(np.linalg.norm(vec) * np.linalg.norm(foundVec))))
print("angle: %f\n" % angle)
while notFound:
for vec in vecs:
angle = np.rad2deg(np.arccos(np.vdot(vec, randVec)/(np.linalg.norm(vec) * np.linalg.norm(randVec))))
if angle < 5:
below=True
if below:
randVec = np.random.rand(1, 3)
else:
notFound=False
print("iteration no. %i" % iter)
iter = iter + 1
Any hints how to approach this problem (language agnostic) would be appreciate.
Consider the vectors in a spherical coordinate system (u,w,r), where r is always 1 because vector length doesn't matter here. Any vector can be expressed as (u,w) and the "deadzone" around each vector x, in which the target vector t cannot fall, can be expressed as dist((u_x, w_x, 1), (u_x-u_t, w_x-w_t, 1)) < 5°. However calculating this distance can be a bit tricky, so converting back into cartesian coordinates might be easier. These deadzones are circular on the spherical shell around the origin and you're looking for a t that doesn't hit any on them.
For any fixed u_t you can iterate over all x and using the distance function can find the start and end point of a range of w_t, that are blocked because they fall into the deadzone of the vector x. The union of all 10000 ranges build the possible values of w_t for that given u_t. The same can be done for any fixed w_t, looking for a u_t.
Now comes the part that I'm not entirely sure of: Given that you have two unknows u_t and w_t and 20000 knowns, the system is just a tad overdetermined and if there's a solution, it should be possible to find it.
My suggestion: Set u_t fixed to a random value and check which w_t are possible. If you find a non-empty range, great, you're done. If all w_t are blocked, select a different u_t and try again. Now, selecting u_t at random will work eventually, yet a smarter iteration should be possible. Maybe u_t(n) = u_t(n-1)*phi % 360°, where phi is the golden ratio. That way the u_t never repeat and will cover the whole space with finer and finer granularity instead of starting from one end and going slowly to the other.
Edit: You might also have more luck on the mathematics stackexchange since this isn't so much a code question as it is a mathematics question. For example I'm not sure what I wrote is all that rigorous, so I don't even know it works.
One way would be two build a 2d manifold (area on the sphere) of forbidden areas. You start by adding a point, then, the forbidden area is a circle on the sphere surface.
While true, pick a point on the boundary of the area. If this is not close (within 5 degrees) to any other vector, then, you're done, return it. If not, you just found a new circle of forbidden area. Add it to your manifold of forbidden area. You'll need to chop the circle in line or arc segments and build the boundary as a list.
If the set of vector has no solution, you boundary will collapse to an empty point. Then you return failure.
It's not the easiest approach, and you'll have to deal with the boundaries of a complex shape over a sphere. But it's guaranteed to work and should have reasonable complexity.
Question Explanation:
I have a fairly large file(up to 1 million lines) containing data from a mining machine. The data includes the X and Y coordinates of the machine. The machine should only be able to mine to the left (-X direction) or to the right (+X direction) and this occurs in a 'lane'. It should not be able to mine the same area again, but it can change Y-coordinates at any time(i.e, it can change lanes at any time) and skip certain areas. I want to determine in which direction the machine is moving at a given time. For example I want to see where the machine is moving to the left or to the right. Although this sounds simple enough, I am having a bit of trouble.
My attempt:
I am currently finding the sum of 100 values of the difference array of the X-coordinates (the difference array gives the distance the machine has moved). Ideally, if the X-coordinates are decreasing in a 100 point interval, then it should be moving to the left, and if the X-coordinates were increasing in that interval, it should be moving to the right. So if the sum was negative, it will append "0" to an array 100 times. I chose 100 because I thought it would be fairly accurate considering the high number of samples.
# miner_x = array of the x-coordinates of the machine
# miner_x_diff = numpy.diff(miner_x)
# 0 = Negative X direction
# 1 = Positive X direction
diffSample= [sum(miner_x_diff[i:i+100]) for i in range(0, len(miner_x_diff), 100)]
Direction = np.array([])
for value in diffSample:
if value < 0:
for _ in itertools.repeat(None, 100):
Direction = np.append(Direction,0)
else:
for _ in itertools.repeat(None, 100):
Direction = np.append(Direction,1)
# correct size
if Direction.size > miner_x.size:
Direction = Direction[0:Direction.size-(Direction.size-miner_x.size)]
The problem I am having is at the point it changes direction from left to right or vice versa, and this mostly occurs during a lane change. This if course expected, since the sum around that area could be close to 0. But I am not sure how to go about accounting for this change using my current method. Is there a more accurate way to determine the direction of the machine?
An example of a plot of the machines position using one particular data set is shown below (code omitted because it is unnecessary). The yellow points are positions where I had incorrect results occur .In this example there shouldn't be any yellow points. I have not shown the direction color in this example but you can of course see it if I say the start position is at the bottom right.
I will appreciate any help/advice/hints :)
Edit:
Here is a picture of what I want (mind the Paint skills). Note that I don't want to 'see' a straight line, just to know that it is moving in those directions at those points. Green is the start point.
Start by using a smaller sample window. How much time is represented by 100 sample points? The interval should be small enough that you can simply look at the displacement between the initial and final position and have a direction for that time segment. (You do realize that summing the difference of consecutive pairs of numbers is the same as subtracting the first from the last number, don't you?) If you catch the machine at a point where it's turning around, you may get indeterminate data but the samples before and after will show a straight vector.
I'm coding in python. I've created a spiral with my current for loop below. I want to create tiny spiral off-shoots around every 10 degrees. The problem is I don't know how to do that. I'm trying to do something like this:
My question is how would I create the off-shoots? Is this even possible or not?
Any suggestions are greatly appreciated.
import turtle
import math
me = turtle.Turtle()
def miniSpiral():
for i in range(0,360):
x,y = me.position()
me.left(1)
if x%10==0:
x2,y2 = me.forward(((5*i)+5)*math.pi/360)
else:
x2,y2= me.forward(5*math.pi/360)
me.goto((x+x2),(y+y2))
for x2 in range(0,720):
me.left(1)
if x2%10==0:
me.forward(((10*x2)+10)*math.pi/360)
#miniSpiral()
me.forward(10*math.pi/360)
In general, the easiest way to draw a fractal programmatically is to use recursion. Start with the code to draw one "segment" of your fractal. In the image you linked to, that would be one 90-degree piece of the spiral (since that's the distance between the branchings).
Once you have code that can draw one segment, you add a recursive call to it. Give it some parameter (e.g. the initial size), and have the recursive call reduce the value passed on to the next call. Add a base case where a call with that parameter set too small gets skipped (e.g. if size < 1: return) so that the recursion doesn't go on forever.
Now you can add branching. Instead of just one recursive call, make two. You'll need to add some extra logic to move the position of the turtle in between the calls (so the second one starts at roughly the same spot as the first), but that shouldn't be too hard. To make the two branches distinct, vary their initial position or angle, or give them different parameters. In your example image, the "extra" branches all start going the oposite direction from the "main" branch, and they start smaller.
Here's a pseudo-code implementation of the spiral you want (I'm not adding actual turtle code because you seem to be using a different turtle module than the one I have from the standard library):
def spiral(size):
if size < 1: return # base case
draw_segment(size) # this draws a 90 degree piece of the spiral
position = getposition() # save state so we can back up after the first recursive call
angle = getangle()
spiral(size - 1) # main branch of the recursion
penup() # restore state (mostly)
setposition(position)
pendown()
setangle(angle + 180) # we want to start facing the other direction for the second branch
spiral(size - 2) # extra branch of the recursion
You can play around with the details (like how you modify the size for the recursive calls) to suit your tastes or the fractal design you're looking for. For instance, you could multiply the size by some factor (e.g. size * 0.75) rather than subtracting a fixed amount.
Each mini spiral is just a smaller version of the original spiral, as such you can carefully call the original function to make each smaller one.
import turtle
import math
def spiral(steps, left, forward, level):
for step in range(50, steps):
me.left(left)
me.forward(step / forward)
if step % 200 == 0 and level > 0:
x, y = me.position()
heading = me.heading()
spiral((steps * 2) / 3, -left * 1.2, forward * 1.2, level - 1)
me.up()
me.setpos(x, y)
me.setheading(heading)
me.down()
#turtle.tracer(5, 200) # to speed things up
me = turtle.Turtle()
spiral(800, 0.6, 200.0, 4)
Each time spiral() is called, the arguments are modified slightly and the level is reduced by 1. Also the left argument is made negative which has the effect of changing the direction for each sub spiral. Each sub spiral is called after 200 steps. Each sub spiral has 2/3rds of the original steps and so on.... lots of numbers to play with to see how they effect the outcome. When the sub spiral finishes drawing, it jumps back to the point where it started drawing it an continues with the original spiral.
Calling it with a level of 0 would give you a single simple spiral for example.
This would give you the following type of output: