Generating Coordinates of a N-sized diamond for Haskell - haskell

So, I have to generate the coordinates to create a diamond on a grid.
I will receive the center (x, y) and the height n from center to top, then I need to generate the coordinates [(x, y),..] to print something like this (n = 4 and center = (4, 4)):
#
# # #
# # # # #
# # # # # # #
# # # # # # # # #
# # # # # # #
# # # # #
# # #
#
Where each # represents a position of the returned list. I don't have any clue about how to do this.
This is how I do it in kotlin:
fun diamond(n: Int, coord: Coord): List<Coord> {
val coords = mutableSetOf<Coord>()
for (i in 0..n) {
for (j in 0..(n - i)) {
coords.add(Coord((coord.x + i).absoluteValue, (coord.y + j).absoluteValue))
coords.add(Coord((coord.x + i).absoluteValue, (coord.y - j).absoluteValue))
coords.add(Coord((coord.x - i).absoluteValue, (coord.y + j).absoluteValue))
coords.add(Coord((coord.x - i).absoluteValue, (coord.y - j).absoluteValue))
}
}
return coords.toList()
}
P.S.: Printing is not a problem, I just need the coordinates.

We can make an analysis of the items in the coordinate. If the center is at (x,y), then we know that there is one symbol exactly n places above the center, and 3 symbols exactly n-1 above the center. etc.
We thus can use list comprehension here:
coordinates :: Integral i => i -> i -> i -> [(i,i)]
coordinates x y n = [(x+dx, y+dy) | dy <- [-n .. n], let ay = n - abs dy, dx <- [-ay .. ay]]

Related

Line intersection turtle script not working as it should

I am creating a script that visualises (or is supposed to) the most amount of intersections given an amount of lines using turtle in python. For some reason, the part of the code that is supposed to highlight all of the crossovers only highlights a few of them. I have experimented with loops, however to no luck. I don't know if it's an issue with the code that grabs the coordinates of intersections or if my loop just wasn't formed properly but it just doesn't (completely) work. My code is below:
import turtle
def find_intersection( p0, p1, p2, p3 ) :
s10_x = p1[0] - p0[0]
s10_y = p1[1] - p0[1]
s32_x = p3[0] - p2[0]
s32_y = p3[1] - p2[1]
denom = s10_x * s32_y - s32_x * s10_y
if denom == 0 : return None # collinear
denom_is_positive = denom > 0
s02_x = p0[0] - p2[0]
s02_y = p0[1] - p2[1]
s_numer = s10_x * s02_y - s10_y * s02_x
if (s_numer < 0) == denom_is_positive : return None # no collision
t_numer = s32_x * s02_y - s32_y * s02_x
if (t_numer < 0) == denom_is_positive : return None # no collision
if (s_numer > denom) == denom_is_positive or (t_numer > denom) == denom_is_positive : return None # no collision
# collision detected
t = t_numer / denom
intersection_point = [p0[0] + (t * s10_x), p0[1] + (t * s10_y)]
return intersection_point
def max_crossovers(num):
segment_points=[]
t = turtle.Turtle()
t.speed(0) # 1:slowest, 3:slow, 5:normal, 10:fast, 0:fastest
t.width(2.5)
count=0 # Keeps track of how many iterations of the loop have taken place.
while count < num:
t.left(360/(num)) # Turns the required angle
t.forward(20*num)
t.backward(40*num) # Gives leeway for lines to crossover
pA=list(t.pos()) # obtain x,y for point A
t.forward(60*num)
pB=list(t.pos()) # obtain x,y for point B
t.backward(30*num) # Prepares turtle in position for the next iteration
segment_points.append([pA, pB])
count+=1
print(segment_points)
# THIS PART ONWARDS NEEDS TO BE IN A LOOP
t.goto(find_intersection(segment_points[0][0], segment_points[0][1], segment_points[0+1][0], segment_points[0+1][1])[0], find_intersection(segment_points[0][0], segment_points[0][1], segment_points[0+1][0], segment_points[0+1][1])[1]) # go to the position of an intersection
t.pencolor("red") # begin process of drawing a circle
t.penup()
t.left(90)
t.backward(10)
t.right(90)
t.pendown()
t.circle(10)
t.penup()
t.left(90)
t.forward(10)
t.right(90)
# UNTIL HERE
max_crossovers(5) # Input number of lines to give the program.
I have tried experimenting with loops and to no luck. Maybe the issue is that the function to detect intersections doesn't work properly otherwise I might just have implemented the loop incorrectly?

Speed Up a for Loop - Python

I have a code that works perfectly well but I wish to speed up the time it takes to converge. A snippet of the code is shown below:
def myfunction(x, i):
y = x + (min(0, target[i] - data[i, :]x))*data[i]/(norm(data[i])**2))
return y
rows, columns = data.shape
start = time.time()
iterate = 0
iterate_count = []
norm_count = []
res = 5
x_not = np.ones(columns)
norm_count.append(norm(x_not))
iterate_count.append(0)
while res > 1e-8:
for row in range(rows):
y = myfunction(x_not, row)
x_not = y
iterate += 1
iterate_count.append(iterate)
norm_count.append(norm(x_not))
res = abs(norm_count[-1] - norm_count[-2])
print('Converge at {} iterations'.format(iterate))
print('Duration: {:.4f} seconds'.format(time.time() - start))
I am relatively new in Python. I will appreciate any hint/assistance.
Ax=b is the problem we wish to solve. Here, 'A' is the 'data' and 'b' is the 'target'
Ugh! After spending a while on this I don't think it can be done the way you've set up your problem. In each iteration over the row, you modify x_not and then pass the updated result to get the solution for the next row. This kind of setup can't be vectorized easily. You can learn the thought process of vectorization from the failed attempt, so I'm including it in the answer. I'm also including a different iterative method to solve linear systems of equations. I've included a vectorized version -- where the solution is updated using matrix multiplication and vector addition, and a loopy version -- where the solution is updated using a for loop to demonstrate what you can expect to gain.
1. The failed attempt
Let's take a look at what you're doing here.
def myfunction(x, i):
y = x + (min(0, target[i] - data[i, :] # x)) * (data[i] / (norm(data[i])**2))
return y
You subtract
the dot product of (the ith row of data and x_not)
from the ith row of target,
limited at zero.
You multiply this result with the ith row of data divided my the norm of that row squared. Let's call this part2
Then you add this to the ith element of x_not
Now let's look at the shapes of the matrices.
data is (M, N).
target is (M, ).
x_not is (N, )
Instead of doing these operations rowwise, you can operate on the entire matrix!
1.1. Simplifying the dot product.
Instead of doing data[i, :] # x, you can do data # x_not and this gives an array with the ith element giving the dot product of the ith row with x_not. So now we have data # x_not with shape (M, )
Then, you can subtract this from the entire target array, so target - (data # x_not) has shape (M, ).
So far, we have
part1 = target - (data # x_not)
Next, if anything is greater than zero, set it to zero.
part1[part1 > 0] = 0
1.2. Finding rowwise norms.
Finally, you want to multiply this by the row of data, and divide by the square of the L2-norm of that row. To get the norm of each row of a matrix, you do
rownorms = np.linalg.norm(data, axis=1)
This is a (M, ) array, so we need to convert it to a (M, 1) array so we can divide each row. rownorms[:, None] does this. Then divide data by this.
part2 = data / (rownorms[:, None]**2)
1.3. Add to x_not
Finally, we're adding each row of part1 * part2 to the original x_not and returning the result
result = x_not + (part1 * part2).sum(axis=0)
Here's where we get stuck. In your approach, each call to myfunction() gives a value of part1 that depends on target[i], which was changed in the last call to myfunction().
2. Why vectorize?
Using numpy's inbuilt methods instead of looping allows it to offload the calculation to its C backend, so it runs faster. If your numpy is linked to a BLAS backend, you can extract even more speed by using your processor's SIMD registers
The conjugate gradient method is a simple iterative method to solve certain systems of equations. There are other more complex algorithms that can solve general systems well, but this should do for the purposes of our demo. Again, the purpose is not to have an iterative algorithm that will perfectly solve any linear system of equations, but to show what kind of speedup you can expect if you vectorize your code.
Given your system
data # x_not = target
Let's define some variables:
A = data.T # data
b = data.T # target
And we'll solve the system A # x = b
x = np.zeros((columns,)) # Initial guess. Can be anything
resid = b - A # x
p = resid
while (np.abs(resid) > tolerance).any():
Ap = A # p
alpha = (resid.T # resid) / (p.T # Ap)
x = x + alpha * p
resid_new = resid - alpha * Ap
beta = (resid_new.T # resid_new) / (resid.T # resid)
p = resid_new + beta * p
resid = resid_new + 0
To contrast the fully vectorized approach with one that uses iterations to update the rows of x and resid_new, let's define another implementation of the CG solver that does this.
def solve_loopy(data, target, itermax = 100, tolerance = 1e-8):
A = data.T # data
b = data.T # target
rows, columns = data.shape
x = np.zeros((columns,)) # Initial guess. Can be anything
resid = b - A # x
resid_new = b - A # x
p = resid
niter = 0
while (np.abs(resid) > tolerance).any() and niter < itermax:
Ap = A # p
alpha = (resid.T # resid) / (p.T # Ap)
for i in range(len(x)):
x[i] = x[i] + alpha * p[i]
resid_new[i] = resid[i] - alpha * Ap[i]
# resid_new = resid - alpha * A # p
beta = (resid_new.T # resid_new) / (resid.T # resid)
p = resid_new + beta * p
resid = resid_new + 0
niter += 1
return x
And our original vector method:
def solve_vect(data, target, itermax = 100, tolerance = 1e-8):
A = data.T # data
b = data.T # target
rows, columns = data.shape
x = np.zeros((columns,)) # Initial guess. Can be anything
resid = b - A # x
resid_new = b - A # x
p = resid
niter = 0
while (np.abs(resid) > tolerance).any() and niter < itermax:
Ap = A # p
alpha = (resid.T # resid) / (p.T # Ap)
x = x + alpha * p
resid_new = resid - alpha * Ap
beta = (resid_new.T # resid_new) / (resid.T # resid)
p = resid_new + beta * p
resid = resid_new + 0
niter += 1
return x
Let's solve a simple system to see if this works first:
2x1 + x2 = -5
−x1 + x2 = -2
should give a solution of [-1, -3]
data = np.array([[ 2, 1],
[-1, 1]])
target = np.array([-5, -2])
print(solve_loopy(data, target))
print(solve_vect(data, target))
Both give the correct solution [-1, -3], yay! Now on to bigger things:
data = np.random.random((100, 100))
target = np.random.random((100, ))
Let's ensure the solution is still correct:
sol1 = solve_loopy(data, target)
np.allclose(data # sol1, target)
# Output: False
sol2 = solve_vect(data, target)
np.allclose(data # sol2, target)
# Output: False
Hmm, looks like the CG method doesn't work for badly conditioned random matrices we created. Well, at least both give the same result.
np.allclose(sol1, sol2)
# Output: True
But let's not get discouraged! We don't really care if it works perfectly, the point of this is to demonstrate how amazing vectorization is. So let's time this:
import timeit
timeit.timeit('solve_loopy(data, target)', number=10, setup='from __main__ import solve_loopy, data, target')
# Output: 0.25586539999994784
timeit.timeit('solve_vect(data, target)', number=10, setup='from __main__ import solve_vect, data, target')
# Output: 0.12008900000000722
Nice! A ~2x speedup simply by avoiding a loop while updating our solution!
For larger systems, this will be even better.
for N in [10, 50, 100, 500, 1000]:
data = np.random.random((N, N))
target = np.random.random((N, ))
t_loopy = timeit.timeit('solve_loopy(data, target)', number=10, setup='from __main__ import solve_loopy, data, target')
t_vect = timeit.timeit('solve_vect(data, target)', number=10, setup='from __main__ import solve_vect, data, target')
print(N, t_loopy, t_vect, t_loopy/t_vect)
This gives us:
N t_loopy t_vect speedup
00010 0.002823 0.002099 1.345390
00050 0.051209 0.014486 3.535048
00100 0.260348 0.114601 2.271773
00500 0.980453 0.240151 4.082644
01000 1.769959 0.508197 3.482822

Hyperbolic sin and cos of an array

I'm trying to define some function for an eady stream function model as shown in the next line:
# Geometry of the wave / domain / mean state:
Lx = 3800 # Zonal Wavelength in km
H = 10000 # tropopause height in meters
Shear = 30/H # shear in sec^-1
k = 2*np.pi/(Lx*1000) # wavenumber (zonal)
l = np.pi/3.e6 # meridional wavenumber in 1/m
# Constants:
cor = 2*(7.292e-5)*np.sin(np.pi/4) # Coriolis parameter
bv2 = 1.e-4 # buoyancy frequency squared
sigma = 2.e-6 # static stability parameter
R = 287 # gas constant
# Grid points on which fields are computed:
xx = np.linspace(0,1.5*Lx,151) # gridpoints in x
yy = np.linspace( -1500,1500,101) # gridpoints in y
zz = np.linspace(0,H,51) # gridpoints in z
# Set array for grid system in x, y, and z
x,y,z = np.meshgrid(xx*1000, yy*1000, zz)
# Define coefficients for the model
mu2 = ((bv2*(H**2))/cor**2)*(k**2 + l**2)
mu = np.sqrt(mu2)
c = (Shear*H/2) + ((Shear*H)/mu)*np.sqrt((mu/2 - coth(mu/2))*(mu/2 - tanh(mu/2)))
# Note: try switching this to (Shear*H/2) - (Shear*H/mu)*...
ci = np.imag(c)
cr = np.real(c)
t = 0*np.pi/(10*cr*k)
A = 2.e7 # streamfunction amplitude (arbitrary)
B = -A*Shear*H/(mu*c)
Psi_z = A*cosh(mu*z/H) + B*sinh(mu*z/H)
I noticed that I'm getting an error when it comes to taking the hyperbolic sin and cos of the array with the following message:
TypeError: cannot create mpf from array (mu*z/H) for both sin and cos.
I've never encountered this error message before, so I'm not familiar enough to try and figure out an approach to this error.

Region growing implementation in python, without seeding

I am trying to implement the region growing segmentation algorithm in python, but I am not allowed to use seed points. My idea so far is this:
Start from the very first pixel, verify its neighbors for boundaries check (within width and height), then verify the neighbors so that they are within the threshold (I obtained this by using the euclidean distance between the current pixel and the neighbor). To be made sure that I don't visit the same pixel again, I created a matrix with the same dimensions as the image (width, height) and made all elements 0 in the beginning. I will start from currentArea number 1 and increment as it goes. In the end, after obaining all areas with their respective average colors, I will use a function that writes down the new Image based on the tuples I have obtained. (averagePixelColor, areaNumber)
This is my code:
from PIL import Image
from scipy.spatial import distance
import statistics
import numpy as np
import sys
sys.setrecursionlimit(10**9)
# SCRIPT: color palette reduction applier script
# SCRIPT: this is the second method. region growing segmentation
# list of red values of pixels
rList = []
# list of green values of pixels
gList = []
# list of blue values of pixels
bList = []
# this matrix will be initially 0, then every region growth
# will be updated to its number
overlayMatrix = []
# starting area number
currentArea = 1
def isValidPixel(x, y, width, height):
if x < 0 or x >= width:
return False
if y < 0 or y >= height:
return False
return True
def get_average_color():
global rList
global gList
global bList
# set values to none
r = None
g = None
b = None
# get average value for each chanel
if rList != []:
r = sum(rList)/len(rList)
g = sum(gList)/len(gList)
b = sum(bList)/len(bList)
# make values integers to be used as pixel
r = int(r)
g = int(g)
b = int(b)
# return values
return (r, g, b)
def add_pixel_to_lists(pixel):
global rList
global gList
global bList
rList.append(pixel[0])
gList.append(pixel[1])
bList.append(pixel[2])
def region_growing(x, y, pixel, img, currentArea):
global overlayMatrix
global rList
global gList
global bList
# get width, heihgt
width, height = img.size
# set this pixel to be visited on current area
overlayMatrix[x][y] = currentArea
# set a list for all possible neighbours
neighbouringPixels = [(x-1, y), (x-1, y-1), (x-1, y+1), (x, y-1), (x, y+1), (x+1, y), (x+1, y-1), (x+1, y+1)]
# filter to get only valid neighbours
validPixels = [x for x in neighbouringPixels if isValidPixel(x[0], x[1], width, height) == True]
# filter pixels to be not visited
notVisitedPixels = [x for x in validPixels if overlayMatrix[x[0]][x[1]] == 0]
# set a threshold value
threshold = 5
# filter to get only pixels in threshold
thresholdPixels = []
thresholdPixels = [x for x in notVisitedPixels if distance.euclidean(img.getpixel(x), pixel) < threshold]
# set the list for pixels to make recursive calls
toVisitRecursive = []
# for every pixel that is a valid neighbour, add it to the toVisit list in recursive call
# and add its rgb values to the lists so an average can be computed
for pixel in thresholdPixels:
toVisitRecursive.append(pixel)
add_pixel_to_lists(img.getpixel(pixel))
# compute average
averagePixel = get_average_color()
# if I still have neighoburs that haven't been visited
# and are within the threshold, get first from list
# remove it so we don't do the same again, then apply
# the algorithm for it
if toVisitRecursive != []:
pixel = toVisitRecursive[0]
toVisitRecursive.remove(pixel)
region_growing(pixel[0], pixel[1], averagePixel, img, currentArea)
# finally, return
return (averagePixel, currentArea+1)
def write_image():
pass
# this will write to the image based on the list of tuples
# average color to the area with number X
def palette_reduction_mt2(input_image):
# open original image
img = Image.open(input_image)
tuple_list = []
# get width, height
width, height = img.size
# make overlay matrix of 0, initial
global overlayMatrix
overlayMatrix = np.zeros((width, height), dtype=np.int32)
# create new image
newimg = Image.new("RGB", (width, height), "white")
currentArea = 1
# iterate through image pixels
for y in range(0, height-1):
for x in range(0, width-1):
global rList
global gList
global bList
# get pixel from edge image
p = img.getpixel((x, y))
# apply region growing
average, currentArea = region_growing(x, y, p, img, currentArea)
tuple_list.append((average, currentArea-1))
# reset color lists to compute new average
rList = []
gList = []
bList = []
print(tuple_list)
# Save image
newimg.save("images/reduced_mt1.jpg")
# return the name of the image
return "images/reduced_mt1.jpg"
For some reason, when I print the tuples list, I only get a single value: [(0,0,0), 1]
Can anyone please point me in the right direction?
Thank you!
Seems like you are not actually iterating over the toVisitRecursive list.
Maybe you should add a loop like:
for pixel in toVisitRecursive:
// region_growing...
or change this line if toVisitRecursive != []: for a while loop;

Generalize the construction of a Greek-Roman Matrix - Python

I wrote a python program that has as input a matrix, in which, each element appears in each row and column once. Elements are only positive integers.
e.g.
0,2,3,1
3,1,0,2
1,3,2,0
2,0,1,3
Then i find all possible traversals. They are defined as such:
choose an element from the first column
move on to the next column and
choose the element that is not in the same line from previous elements in traversal and the element has not the same value with previous elements in traversal.
e.g.
0,*,*,*
*,*,*,2
*,3,*,*
*,*,1,*
I have constructed the code that finds the traversals for matrices 4x4, but i have trouble generalizing it for NxN matrices. My code follows below. Not looking for a solution, any tip would be helpful.
import sys # Import to input arguments from cmd.
import pprint # Import for a cool print of the graph
import itertools # Import to find all crossings' combinations
# Input of arguments
input_filename = sys.argv[1]
# Create an empty graph
g = {}
# Initialize variable for the list count
i = 0
# Opens the file to make the transfer into a matrix
with open(input_filename) as graph_input:
for line in graph_input:
# Split line into four elements.
g[i] = [int(x) for x in line.split(',')]
i += 1
# Initialize variable
var = 0
# Lists for the crossings, plus rows and cols of to use for archiving purposes
f = {}
r = {}
c = {}
l = 0
# Finds the all the crossings
if len(g) == 4:
for x in range (len(g)):
for y in range (len(g)):
# When we are in the first column
if y == 0:
# Creates the maximum number of lists that don't include the first line
max_num = len(g) -1
for z in range (max_num):
f[l] = [g[x][y]]
r[l] = [x]
c[l] = [y]
l += 1
# When on other columns
if y != 0:
for z in range(len(g)):
# Initializes a crossing archive
used = [-1]
for item in f:
# Checks if the element should go in that crossing
if f[item][0] == g[x][0]:
if g[z][y] not in f[item] and z not in r[item] and y not in c[item] and g[z][y] not in used:
# Appends the element and the archive
f[item].append(g[z][y])
used.append(g[z][y])
r[item].append(z)
c[item].append(y)
# Removes unused lists
for x in range (len(f)):
if len(f[x]) != len(g):
f.pop(x)
#Transfers the value from a dictionary to a list
f_final = f.values()
# Finds all the combinations from the existing crossings
list_comb = list(itertools.combinations(f_final, i))
# Initialize variables
x = 0
w = len(list_comb)
v = len(list_comb[0][0])
# Excludes from the combinations all invalid crossings
while x < w:
# Initialize y
y = 1
while y < v:
# Initialize z
z = 0
while z < v:
# Check if the crossings have the same element in the same position
if list_comb[x][y][z] == list_comb[x][y-1][z]:
# Removes the combination from the pool
list_comb.pop(x)
# Adjust loop variables
x -= 1
w -= 1
y = v
z = v
z += 1
y += 1
x += 1
# Inputs the first valid solution as the one to create the orthogonal latin square
final_list = list_comb[0]
# Initializes the orthogonal latin square matrix
orthogonal = [[v for x in range(v)] for y in range(v)]
# Parses through the latin square and the chosen solution
# and creates the orthogonal latin square
for x in range (v):
for y in range (v):
for z in range (v):
if final_list[x][y] == g[z][y]:
orthogonal[z][y] = int(final_list[x][0])
break
# Initializes the orthogonal latin square matrix
gr_la = [[v for x in range(v)] for y in range(v)]
# Creates the greek-latin square
for x in range (v):
for y in range (v):
coords = tuple([g[x][y],orthogonal[x][y]])
gr_la[x][y] = coords
pprint.pprint(gr_la)
Valid traversals for the 4x4 matrix above are:
[[0123],[0312],[3210],[3021],[1203],[1032],[2130],[2301]]

Resources