Animate flood fill in python - python

I have just finished with my food fill algorithm in python. It runs on an N*N matrix filled with integers. I would like to somehow animate it's workings. Is it somehow possible on the console? I think of something like updateing the nodes with a wait() inbetween the updates.

You could use something like this:
#! /usr/bin/python3
import time
m = [ [c for c in line] for line in '''............................
..XXXXXXXXXX...........XXX..
..X........X...........X.X..
..XXXXXX...X....XXXXXXXX.X..
.......X...X....X........X..
....XXXX...XXXXXX........X..
....X....................X..
....X.................XXXX..
....XXXXXXXXXXXXXXXXXXX.....'''.split ('\n') ]
def flood (matrix, start):
maxX = len (matrix [0] )
maxY = len (matrix)
tbf = [start]
while tbf:
x, y = tbf [0]
tbf = tbf [1:]
if x < 0 or x >= maxX or y < 0 or y >= maxY: continue
if matrix [y] [x] == 'X': continue
matrix [y] [x] = 'X'
tbf += [ (x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1) ]
print ('\x1b[0J\x1b[1;1H') #Clear screen and position cursor top left
for line in matrix: print (''.join (line) )
time.sleep (.2)
#flood (m, (0, 0) )
flood (m, (4, 2) )
This should work on any console that supports ANSI escape sequences (CSI). You can use the same CSI codes for outputting colours (Wiki).

Related

How to save the minimum path sum in a recursive function?

This is my solution to given a matrix m x n, find the minimum path sum. It works fine however, I'm not sure how to modify it to see the path / save it in some list, how can this be done?
def get_path(matrix, x, y, seen):
if (x, y) in seen:
return seen[x, y]
x_end = len(matrix) - 1
y_end = len(matrix[0]) - 1
current = matrix[x][y]
if x == x_end and y == y_end:
return current
possible_moves = []
if x < len(matrix) - 1:
possible_moves.append([x + 1, y])
if y < len(matrix[0]) - 1:
possible_moves.append([x, y + 1])
results = [
current + get_path(matrix, *possible, seen) for possible in possible_moves
]
current_best = min(results)
seen[x, y] = current_best
return current_best
You don't need to.
After get_path returns, start from 0,0 look for a move where seen[x', y'] = seen[x,y] - matrix[x,y].
If you have equality (both moves work) pick whatever you want (equals paths).
Keep going until you reach the end.

Array not updating values after function call

I need the array to have all the possible combinations of the (x,y) coordinates that I am generating. The array still prints as an array of 1s.
import numpy as np
coordinates = np.ones([1000, 2])
def translate (x,y):
dx = 5
dy = 5
return x + dx, y + dy
for i in range(0, 100):
for j in range(0, 100):
(x, y) = translate(i, j)
coordinates[i, j] = translate(x, y)
np.append(coordinates, translate(x, y), axis=None)
print(coordinates)
I expect coordinates array to receive the correct values after the translate function is called and not an array of 1s.
If I understand correctly, you want all possible (x,y) coordinates that can be generated by varying x=0..99 and y=0..99 and then adding some dx and dy to x and y, respectively.
One approach, similar to yours, is to initialize an empty list, and then just append a tuple with the translation function you defined:
coordinates = []
def translate (x,y):
dx = 5
dy = 5
return x + dx, y + dy
for x in range(0, 100):
for y in range(0, 100):
coordinates.append(translate(x,y))
print(coordinates)
However, this could be improved. Realize that you are simply adding dx to every x and dy to every y, so you can achieve the same result with simpler code by removing the translate function:
coordinates = []
dx, dy = 5, 5
for x in range(dx, 100+dx):
for y in range(dy, 100+dy):
coordinates.append((x,y))
print(coordinates)
Which will give you the same correct answer.

How to change nearest neighbors function to not work diagonally

I've working nearest neighbors function but I don't know how to make it work only horizontally and vertically right now it works in all directions. Code below:
nnlst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
MAP_WIDTH = 3
MAP_HEIGHT = 3
def nearest_neighbors(map_x, map_y):
coordinates_list = []
for x_ in range(max(0, map_x - 1), min(MAP_WIDTH, map_x + 2)):
for y_ in range(max(0, map_y - 1), min(MAP_HEIGHT, map_y + 2)):
# we are ignoring result when x_ and y_ equals variable we ask for
if (map_x, map_y) == (x_, y_):
continue
coordinates_list.append([x_, y_])
return coordinates_list
print "function result"
print "nearest neighbors of", nnlst[0][1]
nearest_neighbor_coordinates_list = nearest_neighbors(0, 1)
for coordinates in nearest_neighbor_coordinates_list:
print coordinates, "=", nnlst[coordinates[0]][coordinates[1]]
As you can see right now it works in all directions.
You need to add one more condition to prevent inclusion of the diagonal ones:
def nearest_neighbors(map_x, map_y):
coordinates_list = []
for x_ in range(max(0, map_x - 1), min(MAP_WIDTH, map_x + 2)):
for y_ in range(max(0, map_y - 1), min(MAP_HEIGHT, map_y + 2)):
# we are ignoring result when x_ and y_ equals variable we ask for, also the diagonal neigbors that differ in both x & y coordinates
if (map_x, map_y) == (x_, y_) or (map_x != x_ and map_y != y_):
continue
coordinates_list.append([x_, y_])
return coordinates_list
to get the desired result:
function result
nearest neighbors of 2
[0, 0] = 1
[0, 2] = 3
[1, 1] = 5
alternatively, you could list all "admissible" displacements explicitly:
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
x_ = min(MAP_WIDTH, max(0, map_x + dx))
y_ = min(MAP_HEIGHT, max(0, map_y + dy))
if (map_x, map_y) == (x_, y_):
continue
...
For a problem with such as small number of possibilities, I would just spell them all out and pre-compute the function results for every position. That way the function can be eliminated and the problem reduced to doing simple table look-up operation.
Here's what I mean:
nnlist = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
MAP_WIDTH = len(nnlist[0])
MAP_HEIGHT = len(nnlist)
nearest_neighbors = {} # is now a dictionary
for x in range(MAP_WIDTH):
for y in range(MAP_HEIGHT):
neighbors = [[nx, ny] for nx, ny in [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
if -1 < nx < MAP_WIDTH and -1 < ny < MAP_HEIGHT]
nearest_neighbors[(x, y)] = neighbors
print "look-up result"
print "nearest neighbors of", nnlist[0][1]
nearest_neighbor_coordinates_list = nearest_neighbors[(0, 1)]
for coordinates in nearest_neighbor_coordinates_list:
print coordinates, "=", nnlist[coordinates[0]][coordinates[1]]

Placing graphs in a landscape grid (a python challenge)

I would like to place subplots in matplotlib so that I do not know how many graphs are there (variable number of graphs).
The grid dimensions is R * C so that R <= C, and the grid is filled fromleft to right and from top to bottom.
The challenge is that I want to make a function that returns a tuple of the location (r, c) for the chart number n
A sample diagram of the needed functions is shown below where group represents n(r,c) i.e. the number n should output the tuple(r,c)
sample
0(0, 0) 1(0, 1) 4(0, 2) 9(0, 3) 16(0, 4)
2(1, 0) 3(1, 1) 5(1, 2) 10(1, 3) 17(1, 4)
6(2, 0) 7(2, 1) 8(2, 2) 11(2, 3) 18(2, 4)
12(3, 0) 13(3, 1) 14(3, 2) 15(3, 3) 19(3, 4)
20(4, 0) 21(4, 1) 22(4, 2) 23(4, 3) 24(4, 4)
x = 0
y = 0
print (x,y)
for i in range(1,5):
y = i
print [(x,y) for x in range(i)]
x = i
print [(x,y) for y in range(i+1)]
To add the numbers:
tuples=[]
x = 0
y = 0
n = 0
tuples.append((n,(x,y)))
for i in range(1,5):
y = i
for x in range(i):
n+=1
tuples.append((n,(x,y)))
x = i
for y in range(i+1):
n+=1
tuples.append((n,(x,y)))
print tuples

Bezier Curve using static points

So I found this code on line and it does a random Bezier Curve which uses random points. I was trying to make it non random so that it would use static points I got it to use only 4 points which was easy. I have never used PIL before in python and in fact I am slowly learning python. And I have only really done front end work (html, javascript, css, etc) and I just wanted to know if some one can help me.
Here is the code I found on line:
# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
import random
from PIL import Image, ImageDraw
imgx = 500
imgy = 500
image = Image.new("RGB", (imgx, imgy))
draw = ImageDraw.Draw(image)
def B(coorArr, i, j, t):
if j == 0:
return coorArr[i]
return B(coorArr, i, j - 1, t) * (1 - t) + B(coorArr, i + 1, j - 1, t) * t
n = 4 # number of control points
coorArrX = []
coorArrY = []
for k in range(n):
x = (0, imgx - 1)
y = (0, imgy - 1)
coorArrX.append(x)
coorArrY.append(y)
# plot the curve
numSteps = 10000
for k in range(numSteps):
t = float(k) / (numSteps - 1)
x = int(B(coorArrX, 0, n - 1, t))
y = int(B(coorArrY, 0, n - 1, t))
try:
image.putpixel((x, y), (0, 255, 0))
except:
pass
# plot the control points
cr = 3 # circle radius
for k in range(n):
x = coorArrX[k]
y = coorArrY[k]
try:
draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
except:
pass
# image.save("BezierCurve.png", "PNG")
image.show() I add this so I can see it right away
Any help if at all would be great.
Ok The long detailed BS that began this all is below the long line. The resulting answer is here.
Your static points are x,y coordinates with the x values and y values placed in seperate arrays (coorArrx and coorArrY respectively) make sure to never use a value = imgx or imy.
# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
import random
from PIL import Image, ImageDraw
imgx = 500
imgy = 500
image = Image.new("RGB", (imgx, imgy))
draw = ImageDraw.Draw(image)
def B(coorArr, i, j, t):
if j == 0:
return coorArr[i]
return B(coorArr, i, j - 1, t) * (1 - t) + B(coorArr, i + 1, j - 1, t) * t
# n = random.randint(3, 6) # number of control points
n=4
#coorArrX = []
#coorArrY = []
#for k in range(n):
# x = random.randint(0, imgx - 1)
# y = random.randint(0, imgy - 1)
# coorArrX.append(x)
# coorArrY.append(y)
coorArrX=[3,129,12,77]
coorArrY=[128,52,12,491]
# plot the curve
numSteps = 10000
for k in range(numSteps):
t = float(k) / (numSteps - 1)
x = int(B(coorArrX, 0, n - 1, t))
y = int(B(coorArrY, 0, n - 1, t))
try:
image.putpixel((x, y), (0, 255, 0))
except:
pass
# plot the control points
cr = 3 # circle radius
for k in range(n):
x = coorArrX[k]
y = coorArrY[k]
try:
draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
except:
pass
image.show()
=.........................................................................................=
I am also something of a newcommer to all of this, and I REFUSE to look this up as I see it like you do...a learning experiencee.
But as I look at this code I see something strange
for k in range(n):
x = (0, imgx - 1)
y = (0, imgy - 1)
coorArrX.append(x)
coorArrY.append(y)
Are you sure this part is correct? imgx is defined as 500 elsewhere, and n is 4.
so this could read as
for k in range(4):
x = (0, 500 - 1)
y = (0, 500 - 1)
which (since these values never change at all in this code) means:
x = (0, 499)
y = (0, 499)
on every pass.
So each time they get to :
coorArrX.append(x)
coorArrY.append(y)
They simply keep adding new copies of the same data to the array, so when it is done the array looks like this (internally)
[(0, 499), (0, 499), (0, 499), (0,499)]
What makes this more confusing, is that coorArrX and coorArrY are A) Identical, and B) identical in their basic parts(that is each element is identical). Therefore, when you get to this part of the code:
# plot the control points
cr = 3 # circle radius
for k in range(n):
x = coorArrX[k]
y = coorArrY[k]
try:
draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
except:
pass
and you substitute in the values in the arrays, you get:
# plot the control points
cr = 3 # circle radius
for k in range(n):
x = coorArrX[k]
y = coorArrY[k]
try:
draw.ellipse(((0, 499) - 3, (0, 499) - 3, (0, 499) + 3, (0, 499) + 3), (255, 0, 0))
except:
pass
Now this is the part that controls the drawing of the curved segments for the plot, but I do not see how centering an elispe on those impossible coordinate sets can draw anything?!
Broke down and did a copy paste test run. This code is purely bogus, either placed to dupe people into wasting time, or placed where OP found it for same reason.
But it was fun trying!!
From your description, the only problem seems to be about Python basics. I have rearranged the code as follows, so the only things that need to be touched are at bottom. Now, if you want to manually specify 4 control points, go ahead and do it (in the following code I have specified 4 of them myself as an example). You need to understand that, in the original code, coorArrX and coorArrY are just lists, which will hold 4 points each (x and y coordinates, respectively). If you are manually specifying them, there is no point in using a loop to write them. I hope this code is clear enough:
# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
from PIL import Image, ImageDraw
def plot_curve(image, px, py, steps=1000, color=(0, 255, 0)):
def B(coord, i, j, t):
if j == 0:
return coord[i]
return (B(coord, i, j - 1, t) * (1 - t) +
B(coord, i + 1, j - 1, t) * t)
img = image.load()
for k in range(steps):
t = float(k) / (steps - 1)
x = int(B(px, 0, n - 1, t))
y = int(B(py, 0, n - 1, t))
try:
img[x, y] = color
except IndexError:
pass
def plot_control_points(image, px, py, radi=3, color=(255, 0, 0)):
draw = ImageDraw.Draw(image)
for x, y in zip(px, py):
draw.ellipse((x - radi, y - radi, x + radi, y + radi), color)
# Your fixed, manually specified, points.
n = 4
coord_x = [25, 220, 430, 410]
coord_y = [250, 10, 450, 40]
image = Image.new("RGB", (500, 500))
plot_curve(image, coord_x, coord_y)
plot_control_points(image, coord_x, coord_y)
image.save("BezierCurve.png")

Categories

Resources